]> 4ch.mooo.com Git - 16.git/commitdiff
wwww
authorsparky4 <sparky4@cock.li>
Mon, 21 Dec 2015 16:08:03 +0000 (10:08 -0600)
committersparky4 <sparky4@cock.li>
Mon, 21 Dec 2015 16:08:03 +0000 (10:08 -0600)
493 files changed:
16.exe
16/x/default.fnt [new file with mode: 0755]
16/x/makefile [new file with mode: 0755]
16/x/modex.def [new file with mode: 0755]
16/x/modex.h [new file with mode: 0755]
16/x/modex.lbr [new file with mode: 0755]
16/x/modex.pas [new file with mode: 0755]
16/x/modex/DEMO01.EXE [new file with mode: 0755]
16/x/modex/DEMO01.PAS [new file with mode: 0755]
16/x/modex/DEMO02.EXE [new file with mode: 0755]
16/x/modex/DEMO02.PAS [new file with mode: 0755]
16/x/modex/DEMO03.EXE [new file with mode: 0755]
16/x/modex/DEMO03.PAS [new file with mode: 0755]
16/x/modex/DEMO04.DAT [new file with mode: 0755]
16/x/modex/DEMO04.EXE [new file with mode: 0755]
16/x/modex/DEMO04.PAS [new file with mode: 0755]
16/x/modex/DEMO05.EXE [new file with mode: 0755]
16/x/modex/DEMO05.PAS [new file with mode: 0755]
16/x/modex/DEMO06.DAT [new file with mode: 0755]
16/x/modex/DEMO06.EXE [new file with mode: 0755]
16/x/modex/DEMO06.PAS [new file with mode: 0755]
16/x/modex/DEMO07.EXE [new file with mode: 0755]
16/x/modex/DEMO07.PAS [new file with mode: 0755]
16/x/modex/MATH.INC [new file with mode: 0755]
16/x/modex/PLASMA.PAS [new file with mode: 0755]
16/x/modex/QIX2.EXE [new file with mode: 0755]
16/x/modex/QIX2.PAS [new file with mode: 0755]
16/x/modex/README.TXT [new file with mode: 0755]
16/x/modex/SINCOS.INC [new file with mode: 0755]
16/x/modex/THREED.ASM [new file with mode: 0755]
16/x/modex/THREED.H [new file with mode: 0755]
16/x/modex/THREED.PAS [new file with mode: 0755]
16/x/mxbb.asm [new file with mode: 0755]
16/x/mxcc.asm [new file with mode: 0755]
16/x/mxcg.asm [new file with mode: 0755]
16/x/mxcl.asm [new file with mode: 0755]
16/x/mxcr.asm [new file with mode: 0755]
16/x/mxel.asm [new file with mode: 0755]
16/x/mxfb.asm [new file with mode: 0755]
16/x/mxfp.asm [new file with mode: 0755]
16/x/mxgc.asm [new file with mode: 0755]
16/x/mxgi.asm [new file with mode: 0755]
16/x/mxgm.asm [new file with mode: 0755]
16/x/mxgp.asm [new file with mode: 0755]
16/x/mxgv.asm [new file with mode: 0755]
16/x/mxhl.asm [new file with mode: 0755]
16/x/mxit.asm [new file with mode: 0755]
16/x/mxll.asm [new file with mode: 0755]
16/x/mxln.asm [new file with mode: 0755]
16/x/mxot.asm [new file with mode: 0755]
16/x/mxpb.asm [new file with mode: 0755]
16/x/mxpf.asm [new file with mode: 0755]
16/x/mxpg.asm [new file with mode: 0755]
16/x/mxpi.asm [new file with mode: 0755]
16/x/mxpn.asm [new file with mode: 0755]
16/x/mxpp.asm [new file with mode: 0755]
16/x/mxra.asm [new file with mode: 0755]
16/x/mxrp.asm [new file with mode: 0755]
16/x/mxsa.asm [new file with mode: 0755]
16/x/mxsc.asm [new file with mode: 0755]
16/x/mxsi.asm [new file with mode: 0755]
16/x/mxsl.asm [new file with mode: 0755]
16/x/mxsm.asm [new file with mode: 0755]
16/x/mxsp.asm [new file with mode: 0755]
16/x/mxss.asm [new file with mode: 0755]
16/x/mxtl.asm [new file with mode: 0755]
16/x/mxvs.asm [new file with mode: 0755]
16/x/mxwd.asm [new file with mode: 0755]
16/x/mxwm.asm [new file with mode: 0755]
16/x/mxwp.asm [new file with mode: 0755]
16/x/mxwr.asm [new file with mode: 0755]
16/x/readme.txt [new file with mode: 0755]
16/x_/MODEX.BAK [new file with mode: 0755]
16/x_/default.fnt [new file with mode: 0755]
16/x_/makefile [new file with mode: 0755]
16/x_/modex.def [new file with mode: 0755]
16/x_/modex.h [new file with mode: 0755]
16/x_/modex.lbr [new file with mode: 0755]
16/x_/modex.pas [new file with mode: 0755]
16/x_/modex/DEMO01.EXE [new file with mode: 0755]
16/x_/modex/DEMO01.PAS [new file with mode: 0755]
16/x_/modex/DEMO02.EXE [new file with mode: 0755]
16/x_/modex/DEMO02.PAS [new file with mode: 0755]
16/x_/modex/DEMO03.EXE [new file with mode: 0755]
16/x_/modex/DEMO03.PAS [new file with mode: 0755]
16/x_/modex/DEMO04.DAT [new file with mode: 0755]
16/x_/modex/DEMO04.EXE [new file with mode: 0755]
16/x_/modex/DEMO04.PAS [new file with mode: 0755]
16/x_/modex/DEMO05.EXE [new file with mode: 0755]
16/x_/modex/DEMO05.PAS [new file with mode: 0755]
16/x_/modex/DEMO06.DAT [new file with mode: 0755]
16/x_/modex/DEMO06.EXE [new file with mode: 0755]
16/x_/modex/DEMO06.PAS [new file with mode: 0755]
16/x_/modex/DEMO07.EXE [new file with mode: 0755]
16/x_/modex/DEMO07.PAS [new file with mode: 0755]
16/x_/modex/MATH.INC [new file with mode: 0755]
16/x_/modex/PLASMA.PAS [new file with mode: 0755]
16/x_/modex/QIX2.EXE [new file with mode: 0755]
16/x_/modex/QIX2.PAS [new file with mode: 0755]
16/x_/modex/README.TXT [new file with mode: 0755]
16/x_/modex/SINCOS.INC [new file with mode: 0755]
16/x_/modex/THREED.ASM [new file with mode: 0755]
16/x_/modex/THREED.H [new file with mode: 0755]
16/x_/modex/THREED.PAS [new file with mode: 0755]
16/x_/mxbb.asm [new file with mode: 0755]
16/x_/mxcc.asm [new file with mode: 0755]
16/x_/mxcg.asm [new file with mode: 0755]
16/x_/mxcl.asm [new file with mode: 0755]
16/x_/mxcr.asm [new file with mode: 0755]
16/x_/mxel.asm [new file with mode: 0755]
16/x_/mxfb.asm [new file with mode: 0755]
16/x_/mxfp.asm [new file with mode: 0755]
16/x_/mxgc.asm [new file with mode: 0755]
16/x_/mxgi.asm [new file with mode: 0755]
16/x_/mxgm.asm [new file with mode: 0755]
16/x_/mxgp.asm [new file with mode: 0755]
16/x_/mxgv.asm [new file with mode: 0755]
16/x_/mxhl.asm [new file with mode: 0755]
16/x_/mxit.asm [new file with mode: 0755]
16/x_/mxll.asm [new file with mode: 0755]
16/x_/mxln.asm [new file with mode: 0755]
16/x_/mxot.asm [new file with mode: 0755]
16/x_/mxpb.asm [new file with mode: 0755]
16/x_/mxpf.asm [new file with mode: 0755]
16/x_/mxpg.asm [new file with mode: 0755]
16/x_/mxpi.asm [new file with mode: 0755]
16/x_/mxpn.asm [new file with mode: 0755]
16/x_/mxpp.asm [new file with mode: 0755]
16/x_/mxra.asm [new file with mode: 0755]
16/x_/mxrp.asm [new file with mode: 0755]
16/x_/mxsa.asm [new file with mode: 0755]
16/x_/mxsc.asm [new file with mode: 0755]
16/x_/mxsi.asm [new file with mode: 0755]
16/x_/mxsl.asm [new file with mode: 0755]
16/x_/mxsm.asm [new file with mode: 0755]
16/x_/mxsp.asm [new file with mode: 0755]
16/x_/mxss.asm [new file with mode: 0755]
16/x_/mxtl.asm [new file with mode: 0755]
16/x_/mxvs.asm [new file with mode: 0755]
16/x_/mxwd.asm [new file with mode: 0755]
16/x_/mxwm.asm [new file with mode: 0755]
16/x_/mxwp.asm [new file with mode: 0755]
16/x_/mxwr.asm [new file with mode: 0755]
16/x_/readme.txt [new file with mode: 0755]
16/xlib/demo1.exe [deleted file]
16/xlib/demo2.exe [deleted file]
16/xlib/demo3.exe [deleted file]
16/xlib/demo4.exe [deleted file]
16/xlib/demo5.exe [deleted file]
16/xlib/demo6.exe [deleted file]
16/xlib/demo7.exe [deleted file]
16/xlib/demo8.exe [deleted file]
16/xlib/makefile
16/xlib/model.inc
16/xlib/xbmtools.asm
16/xlib/xfileio.asm
16/xlib/xlib.inc
16/xlib/xline.asm
16/xlib/xmain.asm
16/xlib/xmain.inc
16/xlib/xpal.asm
16/xlib/xpoint.asm
16/xw/default.fnt [new file with mode: 0755]
16/xw/makefile [new file with mode: 0755]
16/xw/makefile.bcc [new file with mode: 0755]
16/xw/modex.bak [new file with mode: 0755]
16/xw/modex.def [new file with mode: 0755]
16/xw/modex.h [new file with mode: 0755]
16/xw/modex.lbr [new file with mode: 0755]
16/xw/modex.pas [new file with mode: 0755]
16/xw/modex/DEMO01.EXE [new file with mode: 0755]
16/xw/modex/DEMO01.PAS [new file with mode: 0755]
16/xw/modex/DEMO02.EXE [new file with mode: 0755]
16/xw/modex/DEMO02.PAS [new file with mode: 0755]
16/xw/modex/DEMO03.EXE [new file with mode: 0755]
16/xw/modex/DEMO03.PAS [new file with mode: 0755]
16/xw/modex/DEMO04.DAT [new file with mode: 0755]
16/xw/modex/DEMO04.EXE [new file with mode: 0755]
16/xw/modex/DEMO04.PAS [new file with mode: 0755]
16/xw/modex/DEMO05.EXE [new file with mode: 0755]
16/xw/modex/DEMO05.PAS [new file with mode: 0755]
16/xw/modex/DEMO06.DAT [new file with mode: 0755]
16/xw/modex/DEMO06.EXE [new file with mode: 0755]
16/xw/modex/DEMO06.PAS [new file with mode: 0755]
16/xw/modex/DEMO07.EXE [new file with mode: 0755]
16/xw/modex/DEMO07.PAS [new file with mode: 0755]
16/xw/modex/MATH.INC [new file with mode: 0755]
16/xw/modex/PLASMA.PAS [new file with mode: 0755]
16/xw/modex/QIX2.EXE [new file with mode: 0755]
16/xw/modex/QIX2.PAS [new file with mode: 0755]
16/xw/modex/README.TXT [new file with mode: 0755]
16/xw/modex/SINCOS.INC [new file with mode: 0755]
16/xw/modex/THREED.ASM [new file with mode: 0755]
16/xw/modex/THREED.H [new file with mode: 0755]
16/xw/modex/THREED.PAS [new file with mode: 0755]
16/xw/modex/demo01.c [new file with mode: 0755]
16/xw/mxbb.asm [new file with mode: 0755]
16/xw/mxcc.asm [new file with mode: 0755]
16/xw/mxcg.asm [new file with mode: 0755]
16/xw/mxcl.asm [new file with mode: 0755]
16/xw/mxcr.asm [new file with mode: 0755]
16/xw/mxel.asm [new file with mode: 0755]
16/xw/mxfb.asm [new file with mode: 0755]
16/xw/mxfp.asm [new file with mode: 0755]
16/xw/mxgc.asm [new file with mode: 0755]
16/xw/mxgi.asm [new file with mode: 0755]
16/xw/mxgm.asm [new file with mode: 0755]
16/xw/mxgp.asm [new file with mode: 0755]
16/xw/mxgv.asm [new file with mode: 0755]
16/xw/mxhl.asm [new file with mode: 0755]
16/xw/mxit.asm [new file with mode: 0755]
16/xw/mxll.asm [new file with mode: 0755]
16/xw/mxln.asm [new file with mode: 0755]
16/xw/mxot.asm [new file with mode: 0755]
16/xw/mxpb.asm [new file with mode: 0755]
16/xw/mxpf.asm [new file with mode: 0755]
16/xw/mxpg.asm [new file with mode: 0755]
16/xw/mxpi.asm [new file with mode: 0755]
16/xw/mxpn.asm [new file with mode: 0755]
16/xw/mxpp.asm [new file with mode: 0755]
16/xw/mxra.asm [new file with mode: 0755]
16/xw/mxrp.asm [new file with mode: 0755]
16/xw/mxsa.asm [new file with mode: 0755]
16/xw/mxsc.asm [new file with mode: 0755]
16/xw/mxsi.asm [new file with mode: 0755]
16/xw/mxsl.asm [new file with mode: 0755]
16/xw/mxsm.asm [new file with mode: 0755]
16/xw/mxsp.asm [new file with mode: 0755]
16/xw/mxss.asm [new file with mode: 0755]
16/xw/mxtl.asm [new file with mode: 0755]
16/xw/mxvs.asm [new file with mode: 0755]
16/xw/mxwd.asm [new file with mode: 0755]
16/xw/mxwm.asm [new file with mode: 0755]
16/xw/mxwp.asm [new file with mode: 0755]
16/xw/mxwr.asm [new file with mode: 0755]
16/xw/readme.txt [new file with mode: 0755]
16/xw_/default.fnt [new file with mode: 0755]
16/xw_/makefile [new file with mode: 0755]
16/xw_/makefile.bcc [new file with mode: 0755]
16/xw_/modex.bak [new file with mode: 0755]
16/xw_/modex.def [new file with mode: 0755]
16/xw_/modex.h [new file with mode: 0755]
16/xw_/modex.lbr [new file with mode: 0755]
16/xw_/modex.pas [new file with mode: 0755]
16/xw_/modex/DEMO01.EXE [new file with mode: 0755]
16/xw_/modex/DEMO01.PAS [new file with mode: 0755]
16/xw_/modex/DEMO02.EXE [new file with mode: 0755]
16/xw_/modex/DEMO02.PAS [new file with mode: 0755]
16/xw_/modex/DEMO03.EXE [new file with mode: 0755]
16/xw_/modex/DEMO03.PAS [new file with mode: 0755]
16/xw_/modex/DEMO04.DAT [new file with mode: 0755]
16/xw_/modex/DEMO04.EXE [new file with mode: 0755]
16/xw_/modex/DEMO04.PAS [new file with mode: 0755]
16/xw_/modex/DEMO05.EXE [new file with mode: 0755]
16/xw_/modex/DEMO05.PAS [new file with mode: 0755]
16/xw_/modex/DEMO06.DAT [new file with mode: 0755]
16/xw_/modex/DEMO06.EXE [new file with mode: 0755]
16/xw_/modex/DEMO06.PAS [new file with mode: 0755]
16/xw_/modex/DEMO07.EXE [new file with mode: 0755]
16/xw_/modex/DEMO07.PAS [new file with mode: 0755]
16/xw_/modex/MATH.INC [new file with mode: 0755]
16/xw_/modex/PLASMA.PAS [new file with mode: 0755]
16/xw_/modex/QIX2.EXE [new file with mode: 0755]
16/xw_/modex/QIX2.PAS [new file with mode: 0755]
16/xw_/modex/README.TXT [new file with mode: 0755]
16/xw_/modex/SINCOS.INC [new file with mode: 0755]
16/xw_/modex/THREED.ASM [new file with mode: 0755]
16/xw_/modex/THREED.H [new file with mode: 0755]
16/xw_/modex/THREED.PAS [new file with mode: 0755]
16/xw_/modex/demo01.c [new file with mode: 0755]
16/xw_/mxbb.asm [new file with mode: 0755]
16/xw_/mxcc.asm [new file with mode: 0755]
16/xw_/mxcg.asm [new file with mode: 0755]
16/xw_/mxcl.asm [new file with mode: 0755]
16/xw_/mxcr.asm [new file with mode: 0755]
16/xw_/mxel.asm [new file with mode: 0755]
16/xw_/mxfb.asm [new file with mode: 0755]
16/xw_/mxfp.asm [new file with mode: 0755]
16/xw_/mxgc.asm [new file with mode: 0755]
16/xw_/mxgi.asm [new file with mode: 0755]
16/xw_/mxgm.asm [new file with mode: 0755]
16/xw_/mxgp.asm [new file with mode: 0755]
16/xw_/mxgv.asm [new file with mode: 0755]
16/xw_/mxhl.asm [new file with mode: 0755]
16/xw_/mxit.asm [new file with mode: 0755]
16/xw_/mxll.asm [new file with mode: 0755]
16/xw_/mxln.asm [new file with mode: 0755]
16/xw_/mxot.asm [new file with mode: 0755]
16/xw_/mxot_.asm [new file with mode: 0755]
16/xw_/mxpb.asm [new file with mode: 0755]
16/xw_/mxpf.asm [new file with mode: 0755]
16/xw_/mxpg.asm [new file with mode: 0755]
16/xw_/mxpi.asm [new file with mode: 0755]
16/xw_/mxpn.asm [new file with mode: 0755]
16/xw_/mxpp.asm [new file with mode: 0755]
16/xw_/mxra.asm [new file with mode: 0755]
16/xw_/mxrp.asm [new file with mode: 0755]
16/xw_/mxsa.asm [new file with mode: 0755]
16/xw_/mxsc.asm [new file with mode: 0755]
16/xw_/mxsi.asm [new file with mode: 0755]
16/xw_/mxsl.asm [new file with mode: 0755]
16/xw_/mxsm.asm [new file with mode: 0755]
16/xw_/mxsp.asm [new file with mode: 0755]
16/xw_/mxss.asm [new file with mode: 0755]
16/xw_/mxtl.asm [new file with mode: 0755]
16/xw_/mxvs.asm [new file with mode: 0755]
16/xw_/mxwd.asm [new file with mode: 0755]
16/xw_/mxwm.asm [new file with mode: 0755]
16/xw_/mxwp.asm [new file with mode: 0755]
16/xw_/mxwr.asm [new file with mode: 0755]
16/xw_/readme.txt [new file with mode: 0755]
16/xw_/xw.bat [new file with mode: 0755]
16/xw__/default.fnt [new file with mode: 0755]
16/xw__/makefile [new file with mode: 0755]
16/xw__/makefile.bcc [new file with mode: 0755]
16/xw__/modex.bak [new file with mode: 0755]
16/xw__/modex.def [new file with mode: 0755]
16/xw__/modex.h [new file with mode: 0755]
16/xw__/modex.lbr [new file with mode: 0755]
16/xw__/modex.pas [new file with mode: 0755]
16/xw__/modex/DEMO01.EXE [new file with mode: 0755]
16/xw__/modex/DEMO01.PAS [new file with mode: 0755]
16/xw__/modex/DEMO02.EXE [new file with mode: 0755]
16/xw__/modex/DEMO02.PAS [new file with mode: 0755]
16/xw__/modex/DEMO03.EXE [new file with mode: 0755]
16/xw__/modex/DEMO03.PAS [new file with mode: 0755]
16/xw__/modex/DEMO04.DAT [new file with mode: 0755]
16/xw__/modex/DEMO04.EXE [new file with mode: 0755]
16/xw__/modex/DEMO04.PAS [new file with mode: 0755]
16/xw__/modex/DEMO05.EXE [new file with mode: 0755]
16/xw__/modex/DEMO05.PAS [new file with mode: 0755]
16/xw__/modex/DEMO06.DAT [new file with mode: 0755]
16/xw__/modex/DEMO06.EXE [new file with mode: 0755]
16/xw__/modex/DEMO06.PAS [new file with mode: 0755]
16/xw__/modex/DEMO07.EXE [new file with mode: 0755]
16/xw__/modex/DEMO07.PAS [new file with mode: 0755]
16/xw__/modex/MATH.INC [new file with mode: 0755]
16/xw__/modex/PLASMA.PAS [new file with mode: 0755]
16/xw__/modex/QIX2.EXE [new file with mode: 0755]
16/xw__/modex/QIX2.PAS [new file with mode: 0755]
16/xw__/modex/README.TXT [new file with mode: 0755]
16/xw__/modex/SINCOS.INC [new file with mode: 0755]
16/xw__/modex/THREED.ASM [new file with mode: 0755]
16/xw__/modex/THREED.H [new file with mode: 0755]
16/xw__/modex/THREED.PAS [new file with mode: 0755]
16/xw__/modex/demo01.c [new file with mode: 0755]
16/xw__/mxbb.asm [new file with mode: 0755]
16/xw__/mxcc.asm [new file with mode: 0755]
16/xw__/mxcg.asm [new file with mode: 0755]
16/xw__/mxcl.asm [new file with mode: 0755]
16/xw__/mxcr.asm [new file with mode: 0755]
16/xw__/mxel.asm [new file with mode: 0755]
16/xw__/mxfb.asm [new file with mode: 0755]
16/xw__/mxfp.asm [new file with mode: 0755]
16/xw__/mxgc.asm [new file with mode: 0755]
16/xw__/mxgi.asm [new file with mode: 0755]
16/xw__/mxgm.asm [new file with mode: 0755]
16/xw__/mxgp.asm [new file with mode: 0755]
16/xw__/mxgv.asm [new file with mode: 0755]
16/xw__/mxhl.asm [new file with mode: 0755]
16/xw__/mxit.asm [new file with mode: 0755]
16/xw__/mxll.asm [new file with mode: 0755]
16/xw__/mxln.asm [new file with mode: 0755]
16/xw__/mxot.asm [new file with mode: 0755]
16/xw__/mxot_.asm [new file with mode: 0755]
16/xw__/mxpb.asm [new file with mode: 0755]
16/xw__/mxpf.asm [new file with mode: 0755]
16/xw__/mxpg.asm [new file with mode: 0755]
16/xw__/mxpi.asm [new file with mode: 0755]
16/xw__/mxpn.asm [new file with mode: 0755]
16/xw__/mxpp.asm [new file with mode: 0755]
16/xw__/mxra.asm [new file with mode: 0755]
16/xw__/mxrp.asm [new file with mode: 0755]
16/xw__/mxsa.asm [new file with mode: 0755]
16/xw__/mxsc.asm [new file with mode: 0755]
16/xw__/mxsi.asm [new file with mode: 0755]
16/xw__/mxsl.asm [new file with mode: 0755]
16/xw__/mxsm.asm [new file with mode: 0755]
16/xw__/mxsp.asm [new file with mode: 0755]
16/xw__/mxss.asm [new file with mode: 0755]
16/xw__/mxtl.asm [new file with mode: 0755]
16/xw__/mxvs.asm [new file with mode: 0755]
16/xw__/mxwd.asm [new file with mode: 0755]
16/xw__/mxwm.asm [new file with mode: 0755]
16/xw__/mxwp.asm [new file with mode: 0755]
16/xw__/mxwr.asm [new file with mode: 0755]
16/xw__/readme.txt [new file with mode: 0755]
16/xw__/xw.bat [new file with mode: 0755]
awoo.sh
bakapi.exe
exmmtest.exe
fmemtest.exe
fontgfx.exe
fonttest.exe
inputest.exe
makefile
maptest.exe
palettec.exe
palettel.exe
pcxtest.exe
pcxtest2.exe
planrpcx.exe
scroll.exe
sparky4.do
src/bakapi.c
src/lib/16_in.c
src/lib/bakapee.c
src/lib/bakapee.h
src/lib/modex/asm.bat [new file with mode: 0755]
src/lib/modex/c_utils.asm [new file with mode: 0755]
src/lib/modex/c_utils.h [new file with mode: 0755]
src/lib/modex/c_utils.lst [new file with mode: 0755]
src/lib/modex/c_utils.sbr [new file with mode: 0755]
src/lib/modex/demos/basic7/chardemo.bas [new file with mode: 0755]
src/lib/modex/demos/basic7/make-lib.bat [new file with mode: 0755]
src/lib/modex/demos/basic7/modex.bi [new file with mode: 0755]
src/lib/modex/demos/basic7/modex.qlb [new file with mode: 0755]
src/lib/modex/demos/basic7/test6.bas [new file with mode: 0755]
src/lib/modex/demos/basic7/uasm-bc7.bat [new file with mode: 0755]
src/lib/modex/demos/basic7/utils.asm [new file with mode: 0755]
src/lib/modex/demos/basic7/utils.bi [new file with mode: 0755]
src/lib/modex/demos/c/c_utils.asm [new file with mode: 0755]
src/lib/modex/demos/c/c_utils.h [new file with mode: 0755]
src/lib/modex/demos/c/c_utils.lst [new file with mode: 0755]
src/lib/modex/demos/c/c_utils.sbr [new file with mode: 0755]
src/lib/modex/demos/c/makefile [new file with mode: 0755]
src/lib/modex/demos/c/modex.asm [new file with mode: 0755]
src/lib/modex/demos/c/modex.bi [new file with mode: 0755]
src/lib/modex/demos/c/modex.h [new file with mode: 0755]
src/lib/modex/demos/c/utls-asm.bat [new file with mode: 0755]
src/lib/modex/demos/c/w.sh [new file with mode: 0755]
src/lib/modex/demos/c/x-demo.c [new file with mode: 0755]
src/lib/modex/demos/c/x-demo.dsk [new file with mode: 0755]
src/lib/modex/demos/c/x-demo.exe [new file with mode: 0755]
src/lib/modex/demos/c/x-demo.prj [new file with mode: 0755]
src/lib/modex/demos/c/x.exe [new file with mode: 0755]
src/lib/modex/demos/chardemo.exe [new file with mode: 0755]
src/lib/modex/demos/pascal/test5.pas [new file with mode: 0755]
src/lib/modex/demos/qb45/make-lib.bat [new file with mode: 0755]
src/lib/modex/demos/qb45/modex.bi [new file with mode: 0755]
src/lib/modex/demos/qb45/modex.qlb [new file with mode: 0755]
src/lib/modex/demos/qb45/test6a.bas [new file with mode: 0755]
src/lib/modex/demos/qb45/test6a.exe [new file with mode: 0755]
src/lib/modex/demos/qb45/uasm-qb4.bat [new file with mode: 0755]
src/lib/modex/demos/qb45/utils.asm [new file with mode: 0755]
src/lib/modex/demos/qb45/utils.bi [new file with mode: 0755]
src/lib/modex/demos/rom_8x8.fnt [new file with mode: 0755]
src/lib/modex/demos/spaceage.fnt [new file with mode: 0755]
src/lib/modex/demos/system.fnt [new file with mode: 0755]
src/lib/modex/demos/test6.exe [new file with mode: 0755]
src/lib/modex/fontedit/charsets.cs [new file with mode: 0755]
src/lib/modex/fontedit/csedit.doc [new file with mode: 0755]
src/lib/modex/fontedit/csedit.exe [new file with mode: 0755]
src/lib/modex/fontedit/inverse.fnt [new file with mode: 0755]
src/lib/modex/fontedit/mouseimg.cs [new file with mode: 0755]
src/lib/modex/fontedit/palette.cs [new file with mode: 0755]
src/lib/modex/fontedit/rom_8x8.fnt [new file with mode: 0755]
src/lib/modex/fontedit/spaceage.fnt [new file with mode: 0755]
src/lib/modex/fontedit/system.fnt [new file with mode: 0755]
src/lib/modex/makefile [new file with mode: 0755]
src/lib/modex/mode-x.txt [new file with mode: 0755]
src/lib/modex/modex.asm [new file with mode: 0755]
src/lib/modex/modex.bi [new file with mode: 0755]
src/lib/modex/modex.h [new file with mode: 0755]
src/lib/modex/modex.lst [new file with mode: 0755]
src/lib/modex/modex.sbr [new file with mode: 0755]
src/lib/modex/modex105.zip [new file with mode: 0755]
src/lib/modex/packing.lst [new file with mode: 0755]
src/lib/modex/paledit/bakapi.pal [new file with mode: 0755]
src/lib/modex/paledit/charsets.cs [new file with mode: 0755]
src/lib/modex/paledit/diagonal.pal [new file with mode: 0755]
src/lib/modex/paledit/gamecolr.pal [new file with mode: 0755]
src/lib/modex/paledit/mouseimg.cs [new file with mode: 0755]
src/lib/modex/paledit/paledit.doc [new file with mode: 0755]
src/lib/modex/paledit/paledit.exe [new file with mode: 0755]
src/lib/modex/paledit/palview.exe [new file with mode: 0755]
src/lib/modex/paledit/prime.pal [new file with mode: 0755]
src/lib/modex/paledit/rgb.pal [new file with mode: 0755]
src/lib/modex/paledit/scroll.pal [new file with mode: 0755]
src/lib/modex/readme.doc [new file with mode: 0755]
src/lib/modex/utls-asm.bat [new file with mode: 0755]
src/lib/modex/w.sh [new file with mode: 0755]
src/lib/modex/x.exe [new file with mode: 0755]
src/lib/modex/x_demo.c [new file with mode: 0755]
src/lib/modex/x_demo.dsk [new file with mode: 0755]
src/lib/modex/x_demo.exe [new file with mode: 0755]
src/lib/modex/x_demo.prj [new file with mode: 0755]
test.exe
test2.exe
vgmtest.exe
x-demo.smp [new file with mode: 0755]
x_demo.exe [new file with mode: 0755]
x_demo.smp [new file with mode: 0755]

diff --git a/16.exe b/16.exe
index 46a5d4c8687a1b65ab76eb48b8304ba6f68dcf98..b6f2dbe73359399267d4da03382884eb7bcbc8bf 100755 (executable)
Binary files a/16.exe and b/16.exe differ
diff --git a/16/x/default.fnt b/16/x/default.fnt
new file mode 100755 (executable)
index 0000000..12eb22c
--- /dev/null
@@ -0,0 +1,260 @@
+;\r
+; MODEX library default font\r
+; Copyright (c) 1993-1994 by Alessandro Scotti\r
+;\r
+  DB    000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h  ; #0\r
+  DB   07Eh, 081h, 0A5h, 081h, 0A5h, 099h, 081h, 07Eh  ; #1\r
+  DB   07Eh, 0FFh, 0DBh, 0FFh, 0DBh, 0E7h, 0FFh, 07Eh  ; #2\r
+  DB   06Ch, 0FEh, 0FEh, 0FEh, 07Ch, 038h, 010h, 000h  ; #3\r
+  DB   010h, 038h, 07Ch, 0FEh, 07Ch, 038h, 010h, 000h  ; #4\r
+  DB   010h, 038h, 010h, 054h, 0FEh, 054h, 010h, 0FEh  ; #5\r
+  DB   010h, 038h, 07Ch, 0FEh, 0FEh, 07Ch, 010h, 0FEh  ; #6\r
+  DB   000h, 018h, 03Ch, 07Eh, 07Eh, 03Ch, 018h, 000h  ; #7\r
+  DB   0FFh, 0E7h, 0C3h, 081h, 081h, 0C3h, 0E7h, 0FFh  ; #8\r
+  DB   000h, 03Ch, 066h, 042h, 042h, 066h, 03Ch, 000h  ; #9\r
+  DB   0FFh, 0C3h, 099h, 0BDh, 0BDh, 099h, 0C3h, 0FFh  ; #10\r
+  DB   007h, 003h, 005h, 078h, 084h, 084h, 084h, 078h  ; #11\r
+  DB   07Ch, 082h, 082h, 082h, 07Ch, 010h, 038h, 010h  ; #12\r
+  DB   01Ch, 010h, 01Ch, 010h, 010h, 010h, 030h, 030h  ; #13\r
+  DB   03Eh, 022h, 03Eh, 022h, 022h, 026h, 066h, 060h  ; #14\r
+  DB   099h, 05Ah, 03Ch, 0E7h, 0E7h, 03Ch, 05Ah, 099h  ; #15\r
+  DB   000h, 010h, 030h, 070h, 0F0h, 070h, 030h, 010h  ; #16\r
+  DB   000h, 080h, 0C0h, 0E0h, 0F0h, 0E0h, 0C0h, 080h  ; #17\r
+  DB   010h, 038h, 054h, 010h, 010h, 054h, 038h, 010h  ; #18\r
+  DB   048h, 048h, 048h, 048h, 048h, 000h, 048h, 000h  ; #19\r
+  DB   07Eh, 092h, 092h, 072h, 012h, 012h, 012h, 000h  ; #20\r
+  DB   03Ch, 022h, 018h, 024h, 024h, 018h, 044h, 03Ch  ; #21\r
+  DB   000h, 000h, 000h, 000h, 000h, 03Eh, 03Eh, 000h  ; #22\r
+  DB   038h, 054h, 010h, 010h, 010h, 054h, 038h, 0FEh  ; #23\r
+  DB   000h, 010h, 038h, 054h, 010h, 010h, 010h, 000h  ; #24\r
+  DB   000h, 010h, 010h, 010h, 054h, 038h, 010h, 000h  ; #25\r
+  DB   000h, 008h, 004h, 0FEh, 004h, 008h, 000h, 000h  ; #26\r
+  DB   000h, 020h, 040h, 0FEh, 040h, 020h, 000h, 000h  ; #27\r
+  DB   000h, 000h, 080h, 080h, 080h, 0FCh, 000h, 000h  ; #28\r
+  DB   000h, 024h, 042h, 0FFh, 042h, 024h, 000h, 000h  ; #29\r
+  DB   000h, 000h, 010h, 038h, 07Ch, 0FEh, 000h, 000h  ; #30\r
+  DB   000h, 000h, 0FEh, 07Ch, 038h, 010h, 000h, 000h  ; #31\r
+  DB   000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h  ;  \r
+  DB   010h, 010h, 010h, 010h, 010h, 000h, 010h, 000h  ; !\r
+  DB   000h, 024h, 024h, 000h, 000h, 000h, 000h, 000h  ; "\r
+  DB   024h, 024h, 07Eh, 024h, 07Eh, 024h, 024h, 000h  ; #\r
+  DB   038h, 054h, 050h, 038h, 014h, 054h, 038h, 010h  ; $\r
+  DB   000h, 002h, 044h, 008h, 010h, 020h, 042h, 000h  ; %\r
+  DB   038h, 044h, 038h, 060h, 094h, 088h, 074h, 000h  ; &\r
+  DB   020h, 020h, 040h, 000h, 000h, 000h, 000h, 000h  ; '\r
+  DB   010h, 020h, 040h, 040h, 040h, 020h, 010h, 000h  ; (\r
+  DB   040h, 020h, 010h, 010h, 010h, 020h, 040h, 000h  ; )\r
+  DB   000h, 024h, 018h, 07Eh, 018h, 024h, 000h, 000h  ; *\r
+  DB   000h, 010h, 010h, 07Ch, 010h, 010h, 000h, 000h  ; +\r
+  DB   000h, 000h, 000h, 000h, 000h, 010h, 010h, 020h  ; ,\r
+  DB   000h, 000h, 000h, 0FCh, 000h, 000h, 000h, 000h  ; -\r
+  DB   000h, 000h, 000h, 000h, 000h, 000h, 010h, 000h  ; .\r
+  DB   000h, 004h, 008h, 010h, 020h, 040h, 080h, 000h  ; /\r
+  DB   07Ch, 0C6h, 08Ah, 092h, 0A2h, 0C6h, 07Ch, 000h  ; 0\r
+  DB   010h, 030h, 010h, 010h, 010h, 010h, 038h, 000h  ; 1\r
+  DB   078h, 084h, 004h, 018h, 060h, 080h, 0FCh, 000h  ; 2\r
+  DB   078h, 084h, 004h, 038h, 004h, 084h, 078h, 000h  ; 3\r
+  DB   01Ch, 024h, 044h, 084h, 0FEh, 004h, 00Eh, 000h  ; 4\r
+  DB   0FCh, 080h, 0F8h, 004h, 004h, 084h, 078h, 000h  ; 5\r
+  DB   078h, 084h, 080h, 0F8h, 084h, 084h, 078h, 000h  ; 6\r
+  DB   0FCh, 004h, 004h, 008h, 010h, 020h, 020h, 000h  ; 7\r
+  DB   078h, 084h, 084h, 078h, 084h, 084h, 078h, 000h  ; 8\r
+  DB   078h, 084h, 084h, 07Ch, 004h, 084h, 078h, 000h  ; 9\r
+  DB   000h, 000h, 010h, 000h, 000h, 000h, 010h, 000h  ; :\r
+  DB   000h, 000h, 010h, 000h, 000h, 010h, 010h, 020h  ; ;\r
+  DB   008h, 010h, 020h, 040h, 020h, 010h, 008h, 000h  ; <\r
+  DB   000h, 000h, 0FCh, 000h, 000h, 0FCh, 000h, 000h  ; =\r
+  DB   040h, 020h, 010h, 008h, 010h, 020h, 040h, 000h  ; >\r
+  DB   078h, 084h, 004h, 008h, 010h, 000h, 010h, 000h  ; ?\r
+  DB   07Ch, 082h, 0BAh, 0A6h, 0BEh, 080h, 07Ch, 000h  ; @\r
+  DB   078h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h  ; A\r
+  DB   0F8h, 084h, 084h, 0F8h, 084h, 084h, 0F8h, 000h  ; B\r
+  DB   078h, 084h, 080h, 080h, 080h, 084h, 078h, 000h  ; C\r
+  DB   0F0h, 088h, 084h, 084h, 084h, 088h, 0F0h, 000h  ; D\r
+  DB   0FCh, 080h, 080h, 0F0h, 080h, 080h, 0FCh, 000h  ; E\r
+  DB   0FCh, 080h, 080h, 0F0h, 080h, 080h, 080h, 000h  ; F\r
+  DB   078h, 084h, 080h, 09Ch, 084h, 084h, 078h, 000h  ; G\r
+  DB   084h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h  ; H\r
+  DB   038h, 010h, 010h, 010h, 010h, 010h, 038h, 000h  ; I\r
+  DB   01Ch, 008h, 008h, 008h, 088h, 088h, 070h, 000h  ; J\r
+  DB   084h, 088h, 090h, 0E0h, 090h, 088h, 084h, 000h  ; K\r
+  DB   080h, 080h, 080h, 080h, 080h, 080h, 0FCh, 000h  ; L\r
+  DB   0C6h, 0AAh, 092h, 082h, 082h, 082h, 082h, 000h  ; M\r
+  DB   082h, 0C2h, 0A2h, 092h, 08Ah, 086h, 082h, 000h  ; N\r
+  DB   078h, 084h, 084h, 084h, 084h, 084h, 078h, 000h  ; O\r
+  DB   0F8h, 084h, 084h, 0F8h, 080h, 080h, 080h, 000h  ; P\r
+  DB   078h, 084h, 084h, 084h, 094h, 088h, 076h, 000h  ; Q\r
+  DB   0F8h, 084h, 084h, 0F8h, 090h, 088h, 084h, 000h  ; R\r
+  DB   078h, 084h, 080h, 078h, 004h, 084h, 078h, 000h  ; S\r
+  DB   0FEh, 010h, 010h, 010h, 010h, 010h, 010h, 000h  ; T\r
+  DB   084h, 084h, 084h, 084h, 084h, 084h, 078h, 000h  ; U\r
+  DB   084h, 084h, 084h, 084h, 084h, 048h, 030h, 000h  ; V\r
+  DB   082h, 082h, 082h, 082h, 092h, 0AAh, 0C6h, 000h  ; W\r
+  DB   082h, 044h, 028h, 010h, 028h, 044h, 082h, 000h  ; X\r
+  DB   044h, 044h, 044h, 038h, 010h, 010h, 010h, 000h  ; Y\r
+  DB   0FEh, 004h, 008h, 010h, 020h, 040h, 0FEh, 000h  ; Z\r
+  DB   078h, 040h, 040h, 040h, 040h, 040h, 078h, 000h  ; [\r
+  DB   000h, 080h, 040h, 020h, 010h, 008h, 004h, 000h  ; \\r
+  DB   078h, 008h, 008h, 008h, 008h, 008h, 078h, 000h  ; ]\r
+  DB   010h, 028h, 044h, 082h, 000h, 000h, 000h, 000h  ; ^\r
+  DB   000h, 000h, 000h, 000h, 000h, 000h, 000h, 0FFh  ; _\r
+  DB   020h, 020h, 010h, 000h, 000h, 000h, 000h, 000h  ; `\r
+  DB   000h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; a\r
+  DB   000h, 040h, 040h, 078h, 044h, 044h, 078h, 000h  ; b\r
+  DB   000h, 000h, 03Ch, 040h, 040h, 040h, 03Ch, 000h  ; c\r
+  DB   000h, 004h, 004h, 03Ch, 044h, 044h, 03Ch, 000h  ; d\r
+  DB   000h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h  ; e\r
+  DB   000h, 00Ch, 010h, 03Ch, 010h, 010h, 010h, 000h  ; f\r
+  DB   000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 038h  ; g\r
+  DB   000h, 040h, 040h, 078h, 044h, 044h, 044h, 000h  ; h\r
+  DB   000h, 010h, 000h, 010h, 010h, 010h, 010h, 000h  ; i\r
+  DB   000h, 004h, 000h, 004h, 004h, 004h, 044h, 038h  ; j\r
+  DB   000h, 040h, 040h, 050h, 060h, 050h, 048h, 000h  ; k\r
+  DB   000h, 030h, 010h, 010h, 010h, 010h, 010h, 000h  ; l\r
+  DB   000h, 000h, 068h, 054h, 054h, 044h, 044h, 000h  ; m\r
+  DB   000h, 000h, 078h, 044h, 044h, 044h, 044h, 000h  ; n\r
+  DB   000h, 000h, 038h, 044h, 044h, 044h, 038h, 000h  ; o\r
+  DB   000h, 000h, 078h, 044h, 044h, 078h, 040h, 040h  ; p\r
+  DB   000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 004h  ; q\r
+  DB   000h, 000h, 05Ch, 060h, 040h, 040h, 040h, 000h  ; r\r
+  DB   000h, 000h, 038h, 040h, 07Ch, 004h, 07Ch, 000h  ; s\r
+  DB   000h, 010h, 038h, 010h, 010h, 010h, 018h, 000h  ; t\r
+  DB   000h, 000h, 044h, 044h, 044h, 044h, 038h, 000h  ; u\r
+  DB   000h, 000h, 044h, 044h, 044h, 028h, 010h, 000h  ; v\r
+  DB   000h, 000h, 044h, 044h, 054h, 054h, 06Ch, 000h  ; w\r
+  DB   000h, 000h, 044h, 028h, 010h, 028h, 044h, 000h  ; x\r
+  DB   000h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch  ; y\r
+  DB   000h, 000h, 07Ch, 004h, 038h, 040h, 07Ch, 000h  ; z\r
+  DB   000h, 008h, 010h, 010h, 030h, 010h, 010h, 008h  ; {\r
+  DB   000h, 010h, 010h, 010h, 000h, 010h, 010h, 010h  ; |\r
+  DB   000h, 020h, 010h, 010h, 018h, 010h, 010h, 020h  ; }\r
+  DB   064h, 098h, 000h, 000h, 000h, 000h, 000h, 000h  ; ~\r
+  DB   000h, 010h, 028h, 044h, 082h, 082h, 0FEh, 000h  ; \7f\r
+  DB   07Ch, 080h, 080h, 080h, 080h, 07Ch, 004h, 07Ch  ; #128\r
+  DB   000h, 028h, 000h, 044h, 044h, 044h, 038h, 000h  ; #129\r
+  DB   03Ch, 000h, 07Ch, 044h, 07Ch, 040h, 07Ch, 000h  ; #130\r
+  DB   07Eh, 081h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #131\r
+  DB   024h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #132\r
+  DB   078h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #133\r
+  DB   018h, 018h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #134\r
+  DB   000h, 000h, 078h, 080h, 080h, 078h, 008h, 038h  ; #135\r
+  DB   07Ch, 082h, 038h, 044h, 07Ch, 040h, 03Ch, 000h  ; #136\r
+  DB   048h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h  ; #137\r
+  DB   078h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h  ; #138\r
+  DB   000h, 028h, 000h, 010h, 010h, 010h, 010h, 000h  ; #139\r
+  DB   010h, 028h, 000h, 010h, 010h, 010h, 010h, 000h  ; #140\r
+  DB   000h, 030h, 000h, 010h, 010h, 010h, 010h, 000h  ; #141\r
+  DB   048h, 000h, 078h, 084h, 0FCh, 084h, 084h, 000h  ; #142\r
+  DB   030h, 030h, 078h, 084h, 0FCh, 084h, 084h, 000h  ; #143\r
+  DB   038h, 000h, 0FCh, 080h, 0F0h, 080h, 0FCh, 000h  ; #144\r
+  DB   000h, 000h, 07Eh, 008h, 07Eh, 048h, 07Eh, 000h  ; #145\r
+  DB   07Eh, 090h, 090h, 0FCh, 090h, 090h, 09Eh, 000h  ; #146\r
+  DB   07Ch, 082h, 038h, 044h, 044h, 044h, 038h, 000h  ; #147\r
+  DB   028h, 000h, 038h, 044h, 044h, 044h, 038h, 000h  ; #148\r
+  DB   070h, 000h, 038h, 044h, 044h, 044h, 038h, 000h  ; #149\r
+  DB   038h, 044h, 000h, 044h, 044h, 044h, 038h, 000h  ; #150\r
+  DB   070h, 000h, 044h, 044h, 044h, 044h, 038h, 000h  ; #151\r
+  DB   028h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch  ; #152\r
+  DB   048h, 000h, 078h, 084h, 084h, 084h, 078h, 000h  ; #153\r
+  DB   048h, 000h, 084h, 084h, 084h, 084h, 078h, 000h  ; #154\r
+  DB   000h, 010h, 038h, 040h, 040h, 040h, 038h, 010h  ; #155\r
+  DB   038h, 044h, 040h, 0E0h, 040h, 040h, 082h, 0FCh  ; #156\r
+  DB   044h, 07Ch, 010h, 07Ch, 010h, 07Ch, 010h, 000h  ; #157\r
+  DB   0F0h, 088h, 08Ah, 0F7h, 082h, 082h, 082h, 000h  ; #158\r
+  DB   00Ch, 012h, 010h, 018h, 030h, 010h, 090h, 060h  ; #159\r
+  DB   03Ch, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #160\r
+  DB   000h, 018h, 000h, 010h, 010h, 010h, 010h, 000h  ; #161\r
+  DB   01Ch, 000h, 038h, 044h, 044h, 044h, 038h, 000h  ; #162\r
+  DB   01Ch, 000h, 044h, 044h, 044h, 044h, 038h, 000h  ; #163\r
+  DB   07Ch, 000h, 078h, 044h, 044h, 044h, 044h, 000h  ; #164\r
+  DB   07Ch, 000h, 044h, 064h, 054h, 04Ch, 044h, 000h  ; #165\r
+  DB   018h, 024h, 024h, 01Eh, 000h, 03Eh, 000h, 000h  ; #166\r
+  DB   01Ch, 022h, 022h, 01Ch, 000h, 03Eh, 000h, 000h  ; #167\r
+  DB   010h, 000h, 010h, 020h, 040h, 042h, 03Ch, 000h  ; #168\r
+  DB   000h, 000h, 000h, 0FCh, 080h, 080h, 000h, 000h  ; #169\r
+  DB   000h, 000h, 000h, 0FCh, 004h, 004h, 000h, 000h  ; #170\r
+  DB   040h, 044h, 048h, 057h, 021h, 047h, 004h, 007h  ; #171\r
+  DB   040h, 044h, 048h, 052h, 026h, 04Ah, 01Fh, 002h  ; #172\r
+  DB   010h, 000h, 010h, 010h, 010h, 010h, 010h, 000h  ; #173\r
+  DB   000h, 024h, 048h, 090h, 048h, 024h, 000h, 000h  ; #174\r
+  DB   000h, 048h, 024h, 012h, 024h, 048h, 000h, 000h  ; #175\r
+  DB   022h, 088h, 022h, 088h, 022h, 088h, 022h, 088h  ; #176\r
+  DB   055h, 0AAh, 055h, 0AAh, 055h, 0AAh, 055h, 0AAh  ; #177\r
+  DB   0DBh, 077h, 0DBh, 0EEh, 0DBh, 077h, 0DBh, 0EEh  ; #178\r
+  DB   018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h  ; #179\r
+  DB   018h, 018h, 018h, 018h, 0F8h, 018h, 018h, 018h  ; #180\r
+  DB   018h, 018h, 0F8h, 018h, 0F8h, 018h, 018h, 018h  ; #181\r
+  DB   036h, 036h, 036h, 036h, 0F6h, 036h, 036h, 036h  ; #182\r
+  DB   000h, 000h, 000h, 000h, 0FEh, 036h, 036h, 036h  ; #183\r
+  DB   000h, 000h, 0F8h, 018h, 0F8h, 018h, 018h, 018h  ; #184\r
+  DB   036h, 036h, 0F6h, 006h, 0F6h, 036h, 036h, 036h  ; #185\r
+  DB   036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h  ; #186\r
+  DB   000h, 000h, 0FEh, 006h, 0F6h, 036h, 036h, 036h  ; #187\r
+  DB   036h, 036h, 0F6h, 006h, 0FEh, 000h, 000h, 000h  ; #188\r
+  DB   036h, 036h, 036h, 036h, 0FEh, 000h, 000h, 000h  ; #189\r
+  DB   018h, 018h, 0F8h, 018h, 0F8h, 000h, 000h, 000h  ; #190\r
+  DB   000h, 000h, 000h, 000h, 0F8h, 018h, 018h, 018h  ; #191\r
+  DB   018h, 018h, 018h, 018h, 01Fh, 000h, 000h, 000h  ; #192\r
+  DB   018h, 018h, 018h, 018h, 0FFh, 000h, 000h, 000h  ; #193\r
+  DB   000h, 000h, 000h, 000h, 0FFh, 018h, 018h, 018h  ; #194\r
+  DB   018h, 018h, 018h, 018h, 01Fh, 018h, 018h, 018h  ; #195\r
+  DB   000h, 000h, 000h, 000h, 0FFh, 000h, 000h, 000h  ; #196\r
+  DB   018h, 018h, 018h, 018h, 0FFh, 018h, 018h, 018h  ; #197\r
+  DB   018h, 018h, 01Fh, 018h, 01Fh, 018h, 018h, 018h  ; #198\r
+  DB   036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h  ; #199\r
+  DB   036h, 036h, 037h, 030h, 03Fh, 000h, 000h, 000h  ; #200\r
+  DB   000h, 000h, 03Fh, 030h, 037h, 036h, 036h, 036h  ; #201\r
+  DB   036h, 036h, 0F7h, 000h, 0FFh, 000h, 000h, 000h  ; #202\r
+  DB   000h, 000h, 0FFh, 000h, 0F7h, 036h, 036h, 036h  ; #203\r
+  DB   036h, 036h, 037h, 030h, 037h, 036h, 036h, 036h  ; #204\r
+  DB   000h, 000h, 0FFh, 000h, 0FFh, 000h, 000h, 000h  ; #205\r
+  DB   036h, 036h, 0F7h, 000h, 0F7h, 036h, 036h, 036h  ; #206\r
+  DB   018h, 018h, 0FFh, 000h, 0FFh, 000h, 000h, 000h  ; #207\r
+  DB   036h, 036h, 036h, 036h, 0FFh, 000h, 000h, 000h  ; #208\r
+  DB   000h, 000h, 0FFh, 000h, 0FFh, 018h, 018h, 018h  ; #209\r
+  DB   000h, 000h, 000h, 000h, 0FFh, 036h, 036h, 036h  ; #210\r
+  DB   036h, 036h, 036h, 036h, 03Fh, 000h, 000h, 000h  ; #211\r
+  DB   018h, 018h, 01Fh, 018h, 01Fh, 000h, 000h, 000h  ; #212\r
+  DB   000h, 000h, 01Fh, 018h, 01Fh, 018h, 018h, 018h  ; #213\r
+  DB   000h, 000h, 000h, 000h, 03Fh, 036h, 036h, 036h  ; #214\r
+  DB   036h, 036h, 036h, 036h, 0FFh, 036h, 036h, 036h  ; #215\r
+  DB   018h, 018h, 0FFh, 018h, 0FFh, 018h, 018h, 018h  ; #216\r
+  DB   018h, 018h, 018h, 018h, 0F8h, 000h, 000h, 000h  ; #217\r
+  DB   000h, 000h, 000h, 000h, 01Fh, 018h, 018h, 018h  ; #218\r
+  DB   0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh  ; #219\r
+  DB   000h, 000h, 000h, 000h, 0FFh, 0FFh, 0FFh, 0FFh  ; #220\r
+  DB   0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h  ; #221\r
+  DB   00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh  ; #222\r
+  DB   0FFh, 0FFh, 0FFh, 0FFh, 000h, 000h, 000h, 000h  ; #223\r
+  DB   000h, 000h, 062h, 094h, 088h, 094h, 062h, 000h  ; #224\r
+  DB   000h, 0F0h, 088h, 0F0h, 088h, 088h, 0F0h, 080h  ; #225\r
+  DB   000h, 0F8h, 088h, 080h, 080h, 080h, 080h, 000h  ; #226\r
+  DB   000h, 0FCh, 048h, 048h, 048h, 048h, 048h, 000h  ; #227\r
+  DB   0FCh, 084h, 040h, 020h, 040h, 084h, 0FCh, 000h  ; #228\r
+  DB   03Ch, 040h, 038h, 044h, 044h, 044h, 038h, 000h  ; #229\r
+  DB   000h, 000h, 044h, 044h, 044h, 078h, 040h, 040h  ; #230\r
+  DB   000h, 036h, 048h, 008h, 008h, 008h, 008h, 000h  ; #231\r
+  DB   038h, 010h, 038h, 044h, 044h, 038h, 010h, 038h  ; #232\r
+  DB   078h, 084h, 084h, 0FCh, 084h, 084h, 078h, 000h  ; #233\r
+  DB   078h, 084h, 084h, 084h, 048h, 048h, 0CCh, 000h  ; #234\r
+  DB   078h, 004h, 038h, 044h, 044h, 044h, 038h, 000h  ; #235\r
+  DB   000h, 000h, 06Ch, 092h, 092h, 06Ch, 000h, 000h  ; #236\r
+  DB   000h, 000h, 03Ah, 044h, 05Ah, 022h, 05Ch, 000h  ; #237\r
+  DB   018h, 020h, 040h, 078h, 040h, 020h, 018h, 000h  ; #238\r
+  DB   078h, 084h, 084h, 084h, 084h, 084h, 084h, 000h  ; #239\r
+  DB   000h, 0FCh, 000h, 0FCh, 000h, 0FCh, 000h, 000h  ; #240\r
+  DB   020h, 020h, 0F8h, 020h, 020h, 000h, 0F8h, 000h  ; #241\r
+  DB   020h, 010h, 008h, 010h, 020h, 000h, 07Ch, 000h  ; #242\r
+  DB   008h, 010h, 020h, 010h, 008h, 000h, 07Ch, 000h  ; #243\r
+  DB   00Ch, 012h, 010h, 010h, 010h, 010h, 010h, 010h  ; #244\r
+  DB   010h, 010h, 010h, 010h, 010h, 010h, 090h, 060h  ; #245\r
+  DB   000h, 010h, 000h, 07Ch, 000h, 010h, 000h, 000h  ; #246\r
+  DB   000h, 032h, 04Ch, 000h, 032h, 04Ch, 000h, 000h  ; #247\r
+  DB   038h, 044h, 044h, 038h, 000h, 000h, 000h, 000h  ; #248\r
+  DB   000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h  ; #249\r
+  DB   000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h  ; #250\r
+  DB   00Eh, 008h, 008h, 008h, 048h, 028h, 018h, 008h  ; #251\r
+  DB   038h, 024h, 024h, 024h, 024h, 000h, 000h, 000h  ; #252\r
+  DB   03Ch, 004h, 03Ch, 020h, 03Ch, 000h, 000h, 000h  ; #253\r
+  DB   000h, 000h, 03Ch, 03Ch, 03Ch, 03Ch, 000h, 000h  ; #254\r
+  DB   000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h  ; #255\r
diff --git a/16/x/makefile b/16/x/makefile
new file mode 100755 (executable)
index 0000000..8ad2f24
--- /dev/null
@@ -0,0 +1,81 @@
+#\r
+# MODEX library makefile (for Borland MAKE)\r
+# Copyright (c) 1993,1994 by Alessandro Scotti\r
+#\r
+LIBINCS = MODEX.DEF\r
+\r
+LIBOBJS = MXBB.OBJ \\r
+          MXCC.OBJ \\r
+          MXCG.OBJ \\r
+          MXCL.OBJ \\r
+          MXCR.OBJ \\r
+          MXFB.OBJ \\r
+          MXFP.OBJ \\r
+          MXGC.OBJ \\r
+          MXGI.OBJ \\r
+          MXGM.OBJ \\r
+          MXGP.OBJ \\r
+          MXGV.OBJ \\r
+          MXHL.OBJ \\r
+          MXIT.OBJ \\r
+          MXLL.OBJ \\r
+          MXLN.OBJ \\r
+          MXOT.OBJ \\r
+          MXPB.OBJ \\r
+          MXPF.OBJ \\r
+          MXPG.OBJ \\r
+          MXPI.OBJ \\r
+          MXPN.OBJ \\r
+          MXPP.OBJ \\r
+          MXRA.OBJ \\r
+          MXRP.OBJ \\r
+          MXSA.OBJ \\r
+          MXSC.OBJ \\r
+          MXSI.OBJ \\r
+          MXSL.OBJ \\r
+          MXSM.OBJ \\r
+          MXSP.OBJ \\r
+          MXSS.OBJ \\r
+          MXTL.OBJ \\r
+          MXVS.OBJ \\r
+          MXWD.OBJ \\r
+          MXWM.OBJ \\r
+          MXWP.OBJ \\r
+          MXWR.OBJ\r
+\r
+#\r
+# ASM compiler\r
+#\r
+ASMC = tasm\r
+ASMO = /m5 /p\r
+\r
+#\r
+# PAS compiler\r
+#\r
+PASC = tpc\r
+PASO = /m -$D- -$L- -$S-\r
+\r
+#\r
+# LIB maker, uses response file\r
+#\r
+LIBC = tlib\r
+\r
+.asm.obj:\r
+        $(ASMC) $(ASMO) $<\r
+\r
+target: modex.lib\r
+# modex.tpu modex.tpp\r
+\r
+#modex.tpu: $(LIBOBJS) modex.pas\r
+#        $(PASC) $(PASO) modex\r
+#        copy modex.tpu ..\r
+#        copy modex.pas ..\r
+\r
+#modex.tpp: $(LIBOBJS) modex.pas\r
+#        $(PASC) /cp $(PASO) modex\r
+#        copy modex.tpp ..\r
+\r
+modex.lib: modex.lbr $(LIBOBJS)\r
+        $(LIBC) modex.lib @modex.lbr\r
+\r
+$(LIBOBJS):   modex.def\r
diff --git a/16/x/modex.def b/16/x/modex.def
new file mode 100755 (executable)
index 0000000..45bd900
--- /dev/null
@@ -0,0 +1,163 @@
+;------------------------------------------------------------\r
+;\r
+; MODEX.DEF - Include file\r
+; Copyright (c) 1993-1994 by Alessandro Scotti\r
+;\r
+JUMPS\r
+LOCALS\r
+\r
+TRUE            EQU     1       ; Boolean constants\r
+FALSE           EQU     0\r
+\r
+USE286  = FALSE                  ; TRUE enables 80286 instructions\r
+USE386  = FALSE                  ; TRUE enables 80386 (and 80286) instructions\r
+\r
+IF USE286 EQ TRUE\r
+        P286\r
+ENDIF\r
+\r
+IF USE386 EQ TRUE\r
+        P386\r
+        USE286  = TRUE\r
+ENDIF\r
+\r
+MXVERSION       EQU     0128h   ; Library version (1.40)\r
+\r
+;------------------------------------------------------------\r
+;\r
+; VGA definitions\r
+;\r
+MISC    EQU     3C2h            ; Miscellaneous output\r
+TS      EQU     3C4h            ; Timing Sequencer index register\r
+GDC     EQU     3CEh            ; Graphics Data Controller index register\r
+CRTC    EQU     3D4h            ; CRTC index register\r
+STATUS  EQU     3DAh            ; Input Status register one\r
+\r
+;------------------------------------------------------------\r
+;\r
+; Raster operators\r
+;\r
+OP_SET          EQU     0\r
+OP_MOVE         EQU     0       ; Same as OP_SET\r
+OP_AND          EQU     1\r
+OP_OR           EQU     2\r
+OP_XOR          EQU     3\r
+OP_TRANS        EQU     4\r
+OP_ADD          EQU     5       ; Must be last op\r
+\r
+;------------------------------------------------------------\r
+;\r
+; Polygon fill functions\r
+;\r
+POLYSCANBUFSIZE EQU     4*1024\r
+\r
+;------------------------------------------------------------\r
+; Macro to push registers, variables or flags onto the stack\r
+; Usage: .push "loc16"[,"loc16"...]\r
+; where "loc16" is a 16-bit register, a word-sized variable or the\r
+; keyword "FLAGS".\r
+; Exmpl: .push ax, flags, var1\r
+;        .pop  ax, flags, var1\r
+;\r
+.push   MACRO   r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10\r
+    IFNB <r10>\r
+        .ERROR <.PUSH has more than 10 arguments>\r
+    ENDIF\r
+    IRP $reg, <r0, r1, r2, r3, r4, r5, r6, r7, r8, r9>\r
+        IFB <$reg>                      ;; Is argument blank?\r
+            EXITM                       ;; Yes, exit\r
+        ELSEIFIDNI <$reg>, <FLAGS>      ;; Is argument the keyword "FLAGS"?\r
+            pushf                       ;; Yes, push flags\r
+        ELSE\r
+            push    $reg                ;; Push argument\r
+        ENDIF\r
+    ENDM\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+; Macro to pop registers, variables or flags from the stack\r
+; Usage: .pop "loc16"[,"loc16"...]\r
+; where "loc16" is a 16-bit register, a word-sized variable or the\r
+; keyword "FLAGS".\r
+; Exmpl: .push ax, flags, var1\r
+;        .pop  ax, flags, var1\r
+;\r
+.pop    MACRO   r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10\r
+    IFNB <r10>\r
+        .ERROR <.POP has more than 10 arguments>\r
+    ENDIF\r
+    IRP $reg, <r9, r8, r7, r6, r5, r4, r3, r2, r1, r0>\r
+        IFNB <$reg>                     ;; Is argument non-blank?\r
+            IFIDNI <$reg>, <FLAGS>      ;; Yes, is it the keyword "FLAGS"?\r
+                popf                    ;; Yes, pop flags\r
+            ELSE\r
+                pop     $reg            ;; Pop argument\r
+            ENDIF\r
+        ENDIF\r
+    ENDM\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.enter  MACRO   localsize\r
+    IF USE286 EQ TRUE\r
+        enter   localsize, 0\r
+    ELSE\r
+        push    bp\r
+        mov     bp, sp\r
+        sub     sp, localsize\r
+    ENDIF\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.leave  MACRO   argsize\r
+    IF USE286 EQ TRUE\r
+        leave\r
+    ELSE\r
+        mov     sp, bp\r
+        pop     bp\r
+    ENDIF\r
+    IFNB <argspace>\r
+        ret     argsize\r
+    ELSE\r
+        ret\r
+    ENDIF\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.shr    MACRO   arg, count\r
+    IF USE286 EQ TRUE\r
+        shr     arg, count\r
+    ELSE\r
+        $temp = count\r
+        WHILE $temp GT 0\r
+            shr arg, 1\r
+            $temp = $temp-1\r
+        ENDM\r
+    ENDIF\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.shl    MACRO   arg, count\r
+    IF USE286 EQ TRUE\r
+        shl     arg, count\r
+    ELSE\r
+        $temp = count\r
+        WHILE $temp GT 0\r
+            shl arg, 1\r
+            $temp = $temp-1\r
+        ENDM\r
+    ENDIF\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.chk386 MACRO   name, jump\r
+    IF USE386 EQ FALSE\r
+        .OUT    "Warning: ", <name>, " needs a 386 or better to run!"\r
+        jmp     @@jump\r
+    ENDIF\r
+ENDM\r
diff --git a/16/x/modex.h b/16/x/modex.h
new file mode 100755 (executable)
index 0000000..2c1f1eb
--- /dev/null
@@ -0,0 +1,153 @@
+/*\r
+    MODEX.H - C/C++ include file for the MODEX library\r
+    Copyright (c) 1994 Alessandro Scotti\r
+*/\r
+\r
+#ifndef _MODEX_H_               // Avoid nested inclusions\r
+#define _MODEX_H_\r
+\r
+//\r
+// Video modes\r
+//\r
+#define MX_TEXT     0           // 80x25 text\r
+#define MX_320x175  1           // 320x175x256\r
+#define MX_320x200  2           // 320x200x256, 4 pages, aspect 6:5\r
+#define MX_320x240  3           // 320x240x256, 3 pages, aspect 1:1\r
+#define MX_320x350  4           // 320x350x256\r
+#define MX_320x400  5           // 320x400x256, 2 pages\r
+#define MX_320x480  6           // 320x480x256, 1 page\r
+#define MX_360x175  7           // 360x175x256\r
+#define MX_360x200  8           // 360x200x256, 3 pages\r
+#define MX_360x240  9           // 360x240x256, 2 pages\r
+#define MX_360x350  10          // 360x350x256\r
+#define MX_360x400  11          // 360x400x256, 1 page\r
+#define MX_360x480  12          // 360x480x256, 1 page\r
+#define MX_400x600  13          // 400x600x256, 1 page\r
+\r
+//\r
+// Fade effects\r
+//\r
+#define MX_FADEIN   0\r
+#define MX_FADEOUT  1\r
+\r
+//\r
+// Raster ops\r
+//\r
+#define OP_SET      0           // No operator\r
+#define OP_AND      1           // And\r
+#define OP_OR       2           // Or\r
+#define OP_XOR      3           // Xor\r
+#define OP_TRANS    4           // Transparent\r
+#define OP_ADD      5           // Additive\r
+#define OP_MOVE     0           // Alias for OP_SET\r
+\r
+//\r
+// Temporary definitions\r
+//\r
+#define MXBYTE      unsigned char\r
+#define MXBOOL      short int\r
+#define MXSINT      short int\r
+#define MXUINT      unsigned short int\r
+#define MXAPI       far pascal\r
+#define MXPTR       void far *\r
+\r
+// Functions\r
+\r
+#ifdef __cplusplus                      // Avoid C++ name mangling\r
+extern "C" {\r
+#endif\r
+\r
+//\r
+// Initialization\r
+//\r
+MXSINT  MXAPI mxInit( void );             // Returns 0 if successful\r
+void    MXAPI mxTerm( void );\r
+MXUINT  MXAPI mxGetVersion( void );\r
+//\r
+// Mode setting\r
+//\r
+void    MXAPI mxChangeMode( MXUINT mode );\r
+void    MXAPI mxSetMode( MXUINT mode );\r
+void    MXAPI mxGetAspect( MXUINT far *aspectx, MXUINT far *aspecty );\r
+void    MXAPI mxGetScreenSize( MXUINT far *width, MXUINT far *height );\r
+//\r
+// Hardware support\r
+//\r
+void    MXAPI mxWriteMode( MXBYTE wm );\r
+void    MXAPI mxSplitScreen( MXUINT line );\r
+void    MXAPI mxStartAddress( MXUINT sa );\r
+void    MXAPI mxStartLine( MXUINT sl );\r
+void    MXAPI mxWaitDisplay( void );\r
+void    MXAPI mxWaitRetrace( void );\r
+void    MXAPI mxWritePlane( MXBYTE wp );\r
+void    MXAPI mxReadPlane( MXBYTE rp );\r
+void    MXAPI mxRowAddress( MXBYTE ra );\r
+//\r
+// Virtual screen\r
+//\r
+void    MXAPI mxGetVirtualScreen( MXUINT far *width, MXUINT far *height );\r
+void    MXAPI mxSetVirtualScreen( MXUINT width, MXUINT height );\r
+void    MXAPI mxPan( MXUINT x, MXUINT y );\r
+//\r
+// Clipping\r
+//\r
+MXBOOL  MXAPI mxGetClip( void );\r
+MXBOOL  MXAPI mxGetClipRegion( MXSINT far *x, MXSINT far *y, MXSINT far *w, MXSINT far *h );\r
+MXBOOL  MXAPI mxSetClip( MXBOOL );\r
+void    MXAPI mxSetClipRegion( MXUINT x, MXUINT y, MXUINT width, MXUINT height );\r
+//\r
+// Graphics\r
+//\r
+void    MXAPI mxBitBlt( MXSINT sx, MXSINT sy, MXUINT width, MXUINT height, MXSINT dx, MXSINT dy );\r
+void    MXAPI mxFillBox( MXSINT x, MXSINT y, MXUINT width, MXUINT height, MXUINT color, MXUINT op );\r
+MXBYTE  MXAPI mxGetPixel( MXSINT x, MXSINT y );\r
+void    MXAPI mxPutPixel( MXSINT x, MXSINT y, MXBYTE color );\r
+void    MXAPI mxLine( MXSINT x1, MXSINT y1, MXSINT x2, MXSINT y2, MXUINT color, MXUINT op );\r
+void    MXAPI mxGetImage( MXPTR img, MXSINT x, MXSINT y, MXUINT width, MXUINT height );\r
+void    MXAPI mxPutImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT op );\r
+void    MXAPI mxPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT width, MXUINT height );\r
+void    MXAPI mxTransPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT w, MXUINT h );\r
+void    MXAPI mxCircle( MXSINT x, MXSINT y, MXUINT radius, MXBYTE color );\r
+void    MXAPI mxStretchImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT neww, MXUINT newh, MXUINT op );\r
+//\r
+// Palette\r
+//\r
+void    MXAPI mxColorToGray( MXPTR source, MXPTR dest, MXUINT count );\r
+void    MXAPI mxGammaCorrect( MXPTR source, MXPTR dest, MXUINT count );\r
+void    MXAPI mxGetColor( MXUINT index, MXSINT far *r, MXSINT far *g, MXSINT far *b );\r
+void    MXAPI mxSetColor( MXUINT index, MXSINT red, MXSINT green, MXSINT blue );\r
+void    MXAPI mxGetPalette( MXPTR palette, MXUINT index, MXUINT count );\r
+void    MXAPI mxSetPalette( MXPTR palette, MXUINT index, MXUINT count );\r
+void    MXAPI mxFadePalette( MXPTR, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT );\r
+void    MXAPI mxRotatePalette( MXPTR palette, MXUINT count, MXSINT step );\r
+//\r
+// Text\r
+//\r
+MXSINT  MXAPI mxSetFont( MXPTR font, MXUINT charwidth, MXUINT charheight );\r
+void    MXAPI mxSetTextColor( MXUINT color, MXUINT op );\r
+void    MXAPI mxGetTextStep( MXSINT far *deltax, MXSINT far *deltay );\r
+void    MXAPI mxSetTextStep( MXSINT deltax, MXSINT deltay );\r
+void    MXAPI mxOutChar( MXSINT x, MXSINT y, char c );\r
+void    MXAPI mxOutText( MXSINT x, MXSINT y, char far *sz );\r
+//\r
+// Convex polygons\r
+//\r
+void    MXAPI mxFillPoly( MXUINT, MXPTR, MXPTR, MXUINT, MXUINT );\r
+void    MXAPI mxGouraudPoly( MXUINT, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT );\r
+void    MXAPI mxTexturePoly( MXUINT, MXPTR, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+//\r
+// Remove temporary defines\r
+//\r
+#undef  MXBYTE\r
+#undef  MXBOOL\r
+#undef  MXSINT\r
+#undef  MXUINT\r
+#undef  MXPTR\r
+#undef  MXAPI\r
+\r
+#endif  // _MODEX_H_\r
diff --git a/16/x/modex.lbr b/16/x/modex.lbr
new file mode 100755 (executable)
index 0000000..b1ec26b
--- /dev/null
@@ -0,0 +1,38 @@
++-MXBB.OBJ &\r
++-MXCC.OBJ &\r
++-MXCG.OBJ &\r
++-MXCL.OBJ &\r
++-MXCR.OBJ &\r
++-MXFB.OBJ &\r
++-MXFP.OBJ &\r
++-MXGC.OBJ &\r
++-MXGI.OBJ &\r
++-MXGM.OBJ &\r
++-MXGP.OBJ &\r
++-MXGV.OBJ &\r
++-MXHL.OBJ &\r
++-MXIT.OBJ &\r
++-MXLL.OBJ &\r
++-MXLN.OBJ &\r
++-MXOT.OBJ &\r
++-MXPB.OBJ &\r
++-MXPF.OBJ &\r
++-MXPG.OBJ &\r
++-MXPI.OBJ &\r
++-MXPN.OBJ &\r
++-MXPP.OBJ &\r
++-MXRA.OBJ &\r
++-MXRP.OBJ &\r
++-MXSA.OBJ &\r
++-MXSC.OBJ &\r
++-MXSI.OBJ &\r
++-MXSL.OBJ &\r
++-MXSM.OBJ &\r
++-MXSP.OBJ &\r
++-MXSS.OBJ &\r
++-MXTL.OBJ &\r
++-MXVS.OBJ &\r
++-MXWD.OBJ &\r
++-MXWM.OBJ &\r
++-MXWP.OBJ &\r
++-MXWR.OBJ\r
diff --git a/16/x/modex.pas b/16/x/modex.pas
new file mode 100755 (executable)
index 0000000..7d9d26e
--- /dev/null
@@ -0,0 +1,194 @@
+(*\r
+   Turbo Pascal interface to the MODEX library\r
+   Copyright (c) 1993,1994 by Alessandro Scotti\r
+*)\r
+unit ModeX;\r
+interface\r
+\r
+const\r
+  (* Video modes *)\r
+  MX_TEXT       = 0;\r
+  MX_320x175    = 1;\r
+  MX_320x200    = 2;\r
+  MX_320x240    = 3;\r
+  MX_320x350    = 4;\r
+  MX_320x400    = 5;\r
+  MX_320x480    = 6;\r
+  MX_360x175    = 7;\r
+  MX_360x200    = 8;\r
+  MX_360x240    = 9;\r
+  MX_360x350    = 10;\r
+  MX_360x400    = 11;\r
+  MX_360x480    = 12;\r
+  MX_400x600    = 13;\r
+\r
+  (* Fade effects *)\r
+  MX_FADEIN     = 0;\r
+  MX_FADEOUT    = 1;\r
+\r
+  (* Raster ops *)\r
+  OP_SET        = 0;\r
+  OP_AND        = 1;\r
+  OP_OR         = 2;\r
+  OP_XOR        = 3;\r
+  OP_TRANS      = 4;\r
+  OP_ADD        = 5;\r
+  OP_MOVE       = 0;                    (* Alias for OP_SET *)\r
+\r
+procedure mxBitBlt( SX, SY: integer; Width, Height: word; DX, DY: integer );\r
+procedure mxCircle( CX, CY: integer; Radius: word; Color: byte );\r
+procedure mxChangeMode( Mode: word );\r
+procedure mxColorToGray( ColorPalette, GrayPalette: pointer; Count: word );\r
+procedure mxFadePalette( Palette: pointer; Cmd, Start, Count, R, G, B: word );\r
+procedure mxFillBox( X, Y: integer; Width, Height: word; Color: byte; Op: word );\r
+procedure mxGammaCorrect( ColorPalette, GammaPalette: pointer; Count: word );\r
+procedure mxGetAspect( var AspectX, AspectY: word );\r
+function  mxGetClipRegion( var X1, Y1, Width, Height: word ): boolean;\r
+function  mxGetClip: boolean;\r
+procedure mxGetImage( Image: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxGetPalette( Palette: pointer; Start, Count: word );\r
+function  mxGetPixel( X, Y: word ): byte;\r
+procedure mxGetScreenSize( var Width, Height: word );\r
+procedure mxGetTextStep( var DeltaX, DeltaY: integer );\r
+function  mxGetVersion: word;\r
+procedure mxGetVirtualScreen( var Width, Height: word );\r
+procedure mxInit;\r
+procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word );\r
+procedure mxOutChar( X, Y: integer; C: char );\r
+procedure mxOutText( X, Y: integer; S: pointer );\r
+procedure mxPan( X, Y: word );\r
+procedure mxPutImage( Image: pointer; X, Y: integer; Width, Height, Op: word );\r
+procedure mxPutPixel( X, Y: word; C: byte );\r
+procedure mxPutTile( Tile: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxReadPlane( Plane: byte );\r
+procedure mxRotatePalette( Palette: pointer; Count: word; Step: integer );\r
+procedure mxRowAddress( RowAddress: byte );\r
+function  mxSetClip( Clip: boolean ): boolean;\r
+procedure mxSetClipRegion( X1, Y1, Width, Height: word );\r
+procedure mxSetColor( Index, R, G, B: word );\r
+procedure mxSetFont( Font: pointer; Width, Height: word );\r
+procedure mxSetMode( Mode: word );\r
+procedure mxSetPalette( Palette: pointer; Start, Count: word );\r
+procedure mxSetTextColor( Color, Op: word );\r
+procedure mxSetTextStep( DeltaX, DeltaY: integer );\r
+procedure mxSetVirtualScreen( Width, Height: word );\r
+procedure mxStretchImage( Image: pointer; X, Y: integer; Width, Height, NewWidth, NewHeight, Op: word );\r
+procedure mxSplitScreen( Line: word );\r
+procedure mxStartAddress( StartAddress: word );\r
+procedure mxStartLine( Line: word );\r
+procedure mxTerm;\r
+procedure mxTransPutTile( Tile: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxWaitDisplay;\r
+procedure mxWaitRetrace;\r
+procedure mxWriteMode( Mode: byte );\r
+procedure mxWritePlane( Plane: byte );\r
+\r
+procedure mxFillPoly( Count: word; var Map, Points; Color: word );\r
+procedure mxGouraudPoly( Count: word; var Map, Points, Colors; BaseColor: word );\r
+procedure mxTexturePoly( Count: word; var Map, Points, ImgPoints, Texture; Width: word );\r
+\r
+procedure mxOutStr( X, Y: integer; S: string );\r
+\r
+implementation\r
+\r
+procedure mxBitBlt;                                             external;\r
+procedure mxChangeMode( Mode: word );                           external;\r
+procedure mxCircle;                                             external;\r
+procedure mxColorToGray;                                        external;\r
+procedure mxFadePalette;                                        external;\r
+procedure mxFillBox;                                            external;\r
+procedure mxGammaCorrect;                                       external;\r
+procedure mxGetAspect( var AspectX, AspectY: word );            external;\r
+function  mxGetClipRegion;                                      external;\r
+function  mxGetClip: boolean;                                   external;\r
+procedure mxGetImage;                                           external;\r
+procedure mxGetPalette( Palette: pointer; Start, Count: word ); external;\r
+function  mxGetPixel( X, Y: word ): byte;                       external;\r
+procedure mxGetScreenSize( var Width, Height: word );           external;\r
+procedure mxGetTextStep( var DeltaX, DeltaY: integer );         external;\r
+function  mxGetVersion: word;                                   external;\r
+procedure mxGetVirtualScreen( var Width, Height: word );        external;\r
+procedure mxInit;                                               external;\r
+procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word );   external;\r
+procedure mxOutChar( X, Y: integer; C: char );                  external;\r
+procedure mxOutText( X, Y: integer; S: pointer );               external;\r
+procedure mxPan( X, Y: word );                                  external;\r
+procedure mxPutImage;                                           external;\r
+procedure mxPutPixel( X, Y: word; C: byte );                    external;\r
+procedure mxPutTile;                                            external;\r
+procedure mxReadPlane( Plane: byte );                           external;\r
+procedure mxRotatePalette;                                      external;\r
+procedure mxRowAddress( RowAddress: byte );                     external;\r
+function  mxSetClip( Clip: boolean ): boolean;                  external;\r
+procedure mxSetClipRegion( X1, Y1, Width, Height: word );       external;\r
+procedure mxSetColor( Index, R, G, B: word );                   external;\r
+procedure mxSetFont( Font: pointer; Width, Height: word );      external;\r
+procedure mxSetMode( Mode: word );                              external;\r
+procedure mxSetPalette( Palette: pointer; Start, Count: word ); external;\r
+procedure mxSetTextColor( Color, Op: word );                    external;\r
+procedure mxSetTextStep( DeltaX, DeltaY: integer );             external;\r
+procedure mxSetVirtualScreen( Width, Height: word );            external;\r
+procedure mxSplitScreen( Line: word );                          external;\r
+procedure mxStartAddress( StartAddress: word );                 external;\r
+procedure mxStartLine;                                          external;\r
+procedure mxStretchImage;                                       external;\r
+procedure mxTerm;                                               external;\r
+procedure mxTransPutTile;                                       external;\r
+procedure mxWaitDisplay;                                        external;\r
+procedure mxWaitRetrace;                                        external;\r
+procedure mxWriteMode( Mode: byte );                            external;\r
+procedure mxWritePlane( Plane: byte );                          external;\r
+\r
+procedure mxFillPoly;                                           external;\r
+procedure mxGouraudPoly;                                        external;\r
+procedure mxTexturePoly;                                        external;\r
+{$L MXPB}\r
+{$L MXPF}\r
+{$L MXPG}\r
+{$L MXPT}\r
+\r
+{$L MXBB}\r
+{$L MXCC}\r
+{$L MXCG}\r
+{$L MXCL}\r
+{$L MXCR}\r
+{$L MXFB}\r
+{$L MXFP}\r
+{$L MXGI}\r
+{$L MXGM}\r
+{$L MXGP}\r
+{$L MXGV}\r
+{$L MXHL}\r
+{$L MXIT}\r
+{$L MXLN}\r
+{$L MXOT}\r
+{$L MXPI}\r
+{$L MXPN}\r
+{$L MXPP}\r
+{$L MXRA}\r
+{$L MXRP}\r
+{$L MXSA}\r
+{$L MXSC}\r
+{$L MXSI}\r
+{$L MXSL}\r
+{$L MXSM}\r
+{$L MXSP}\r
+{$L MXSS}\r
+{$L MXTL}\r
+{$L MXVS}\r
+{$L MXWD}\r
+{$L MXWM}\r
+{$L MXWP}\r
+{$L MXWR}\r
+\r
+(*\r
+   Prints a Turbo Pascal string.\r
+   Note: BP 7.0 supports ASCIIZ strings (PChar type).\r
+*)\r
+procedure mxOutStr;\r
+begin\r
+  S := S + #0;\r
+  mxOutText( X, Y, @S[1] );\r
+end;\r
+\r
+end.\r
diff --git a/16/x/modex/DEMO01.EXE b/16/x/modex/DEMO01.EXE
new file mode 100755 (executable)
index 0000000..28caff8
Binary files /dev/null and b/16/x/modex/DEMO01.EXE differ
diff --git a/16/x/modex/DEMO01.PAS b/16/x/modex/DEMO01.PAS
new file mode 100755 (executable)
index 0000000..c684acd
--- /dev/null
@@ -0,0 +1,126 @@
+(*\r
+    DEMO01 - Sprites, page flipping and palette rotation\r
+    Copyright (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+  MAX_SPRITE = 100;\r
+type\r
+  (* Sprite structure *)\r
+  TSprite = record\r
+    X, Y : integer;                        (* Sprite coordinates *)\r
+    DX,DY: integer;                        (* Deltas for sprite movement *)\r
+    W, H : integer;                        (* Sprite width and height *)\r
+    Image: array[ 1..16, 1..16 ] of byte;  (* Sprite image data *)\r
+  end;\r
+  (* RGB color structure *)\r
+  TRgb    = record\r
+    R, G, B: byte;\r
+  end;\r
+var\r
+  S      : array[ 1..MAX_SPRITE ] of TSprite;   (* An array of sprites *)\r
+  Palette: array[ byte ] of TRgb;               (* Palette *)\r
+  Page   : word;                                (* Page offset *)\r
+  I      : word;\r
+\r
+(* Initializes a sprite structure *)\r
+procedure sxInit( var S: TSprite );\r
+var\r
+  I: word;\r
+begin\r
+  S.X := Random( 320 );  (* Initialize position with random values *)\r
+  S.Y := Random( 240 );\r
+  S.DX := Random( 7 )-3; (* Initialize speed with random values *)\r
+  S.DY := Random( 7 )-3;\r
+  S.W := 16;             (* Size is fixed in this program *)\r
+  S.H := 16;\r
+  (* The image is a square with a hole inside *)\r
+  FillChar( S.Image, SizeOf(S.Image), Random(15)+1 );\r
+  for I:=5 to 12 do FillChar( S.Image[ I, 5 ], 8, 0 );\r
+end;\r
+\r
+(* Moves a sprite *)\r
+procedure sxMove( var S: TSprite );\r
+begin\r
+  Inc( S.X, S.DX );     (* Get new position *)\r
+  Inc( S.Y, S.DY );\r
+  (* Check sprite position, change delta if needed *)\r
+  if( S.X > 320 ) then begin\r
+    S.X := 320;\r
+    S.DX := -S.DX;\r
+  end;\r
+  if( S.X < -16 ) then begin\r
+    S.X := -16;\r
+    S.DX := -S.DX;\r
+  end;\r
+  if( S.Y > 240 ) then begin\r
+    S.Y := 240;\r
+    S.DY := -S.DY;\r
+  end;\r
+  if( S.Y < -16 ) then begin\r
+    S.Y := -16;\r
+    S.DY := -S.DY;\r
+  end;\r
+  (* Draw the sprite, note the Page offset added to the *)\r
+  (* Y coordinate of the image *)\r
+  mxPutImage( @S.Image, S.X, Page+S.Y, S.W, S.H, OP_TRANS );\r
+end;\r
+\r
+begin\r
+  (* Initialize library *)\r
+  mxInit;\r
+\r
+  (* Enter graphics mode *)\r
+  mxSetMode( MX_320x240 );\r
+\r
+  (* Print initialization message *)\r
+  mxSetTextColor( 15, OP_TRANS );\r
+  mxOutStr( 4, 4, 'Initializing...' );\r
+\r
+  (* Initialize sprites *)\r
+  for I:=1 to MAX_SPRITE do sxInit( S[I] );\r
+\r
+  (* Draw background *)\r
+  for I:=1 to 192 do begin\r
+    mxCircle( 160, 480+120, I, I+63 );\r
+    mxCircle( 161, 480+120, I, I+63 );\r
+  end;\r
+\r
+  (* Compute and set palette *)\r
+  for I:=1 to 192 do with Palette[I+63] do begin\r
+    R := 0;\r
+    G := 0;\r
+    B := 0;\r
+    if( I < 64 ) then\r
+      R := I shr 1+31\r
+    else if( I < 128 ) then\r
+      G := (I-64) shr 1+31\r
+    else\r
+      B := (I-128) shr 1+31;\r
+  end;\r
+  mxSetPalette( @Palette[64], 64, 192 );\r
+\r
+  (* Main loop *)\r
+  Page := 240;\r
+  while( not KeyPressed ) do begin\r
+    (* Set clip region to current page *)\r
+    mxSetClipRegion( 0, Page, 320, 240 );\r
+    mxSetClip( TRUE );\r
+    (* Restore background *)\r
+    mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+    (* Draw sprites *)\r
+    for I:=1 to MAX_SPRITE do sxMove( S[I] );\r
+    (* Print message *)\r
+    mxOutStr( 4, Page+4, 'Some sprites moving...' );\r
+    (* Flip page *)\r
+    mxStartLine( Page );\r
+    Page := 240-Page;\r
+    (* Animate palette *)\r
+    mxSetPalette( @Palette[64], 64, 192 );\r
+    mxRotatePalette( @Palette[64], 192, 3 );\r
+  end;\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/x/modex/DEMO02.EXE b/16/x/modex/DEMO02.EXE
new file mode 100755 (executable)
index 0000000..14e7dc7
Binary files /dev/null and b/16/x/modex/DEMO02.EXE differ
diff --git a/16/x/modex/DEMO02.PAS b/16/x/modex/DEMO02.PAS
new file mode 100755 (executable)
index 0000000..6b4fb6f
--- /dev/null
@@ -0,0 +1,125 @@
+(*\r
+    DEMO02 - Texture mapping and palette rotation\r
+    (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Plasma, Threed;\r
+\r
+const\r
+  LSIZE = 85;\r
+  Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+type\r
+  T2DPoint = record\r
+    X, Y: integer;\r
+  end;\r
+  TTexture = record\r
+    Desc   : array[ 0..3 ] of T2DPoint;\r
+    Width  : word;\r
+    Data   : array[ 1..64*64 ] of byte;\r
+  end;\r
+  TQuad = record\r
+    VtxCnt : word;\r
+    Vtx    : array[ 0..3 ] of word;\r
+    Texture: word;\r
+  end;\r
+var\r
+  Vtx   : array[ 0..7 ] of TPoint;\r
+  XVtx  : array[ 0..7 ] of TPoint;\r
+  VVtx  : array[ 0..7 ] of T2DPoint;\r
+  Face  : array[ 0..5 ] of TQuad;\r
+  Txts  : array[ 0..5 ] of TTexture;\r
+  Nrm   : array[ 0..5 ] of TPoint;\r
+  XNrm  : array[ 0..5 ] of TPoint;\r
+  Page  : word;\r
+  Palette: array[ byte ] of record R, G, B: byte; end;\r
+\r
+(* Make a 64x64 plasma to be used as texture *)\r
+procedure MakeTexture( Idx: word );\r
+var\r
+  I: word;\r
+begin\r
+  mxFillBox( 0, 0, 64, 64, 0, OP_SET );\r
+  MakePlasma( 0, 0, 64, 64, 96, Random(192)+1, Random(192)+1, Random(192)+1 );\r
+  mxGetImage( @Txts[Idx].Data, 0, 0, 64, 64 );\r
+  (* Texture vertexes are 8:8 fixed, add $80 (0.5) for best results *)\r
+  with Txts[Idx] do begin\r
+    Desc[0].X := $80; Desc[0].Y := $80;\r
+    Desc[1].X := $80; Desc[1].Y := $3F80;\r
+    Desc[2].X := $3F80; Desc[2].Y := $3F80;\r
+    Desc[3].X := $3F80; Desc[3].Y := $80;\r
+    Width := 64;\r
+  end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+  I: integer;\r
+begin\r
+  (* Build vertexes for a cube *)\r
+  with Vtx[0] do begin X:=-LSIZE; Y:=-LSIZE; Z:=-LSIZE; end;\r
+  with Vtx[1] do begin X:=+LSIZE; Y:=-LSIZE; Z:=-LSIZE; end;\r
+  with Vtx[2] do begin X:=-LSIZE; Y:=+LSIZE; Z:=-LSIZE; end;\r
+  with Vtx[3] do begin X:=+LSIZE; Y:=+LSIZE; Z:=-LSIZE; end;\r
+  with Vtx[4] do begin X:=-LSIZE; Y:=-LSIZE; Z:=+LSIZE; end;\r
+  with Vtx[5] do begin X:=+LSIZE; Y:=-LSIZE; Z:=+LSIZE; end;\r
+  with Vtx[6] do begin X:=-LSIZE; Y:=+LSIZE; Z:=+LSIZE; end;\r
+  with Vtx[7] do begin X:=+LSIZE; Y:=+LSIZE; Z:=+LSIZE; end;\r
+  for I:=0 to 7 do begin          (* Make points 16:16 fixed *)\r
+    Vtx[I].X := Vtx[I].X*$10000;\r
+    Vtx[I].Y := Vtx[I].Y*$10000;\r
+    Vtx[I].Z := Vtx[I].Z*$10000;\r
+  end;\r
+  (* Build faces *)\r
+  with Face[0] do begin Vtx[0]:=0; Vtx[1]:=2; Vtx[2]:=3; Vtx[3]:=1; end;\r
+  with Face[1] do begin Vtx[0]:=4; Vtx[1]:=5; Vtx[2]:=7; Vtx[3]:=6; end;\r
+  with Face[2] do begin Vtx[0]:=0; Vtx[1]:=1; Vtx[2]:=5; Vtx[3]:=4; end;\r
+  with Face[3] do begin Vtx[0]:=1; Vtx[1]:=3; Vtx[2]:=7; Vtx[3]:=5; end;\r
+  with Face[4] do begin Vtx[0]:=2; Vtx[1]:=0; Vtx[2]:=4; Vtx[3]:=6; end;\r
+  with Face[5] do begin Vtx[0]:=7; Vtx[1]:=3; Vtx[2]:=2; Vtx[3]:=6; end;\r
+  for I:=0 to 5 do Face[I].Texture := I;\r
+  (* Build textures and palette *)\r
+  Randomize;\r
+  FillChar( Palette, SizeOf(Palette), 0 );\r
+  MakePlasmaPalette( Palette, PAL_RGB );\r
+  mxSetPalette( @Palette, 0, 193 );\r
+  for I:=0 to 5 do MakeTexture( I );\r
+end;\r
+\r
+var\r
+  AX, AY, AZ: byte;\r
+  I: word;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;          (* Start with hidden page *)\r
+\r
+  AX := 0;\r
+  AY := 0;\r
+  AZ := 0;\r
+  (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+  tdSetTranslation( Trans );\r
+  tdSetPerspective( 400*$10000, $10000, $10000 );\r
+  (* Main loop, all magic here! *)\r
+  while( not KeyPressed ) do begin\r
+    tdSetRotation( AX, AY, AZ );                (* Set new angles *)\r
+    tdTransform( Vtx, XVtx, 8 );                (* 3D transform points *)\r
+    tdTransformToImage( XVtx, VVtx, 8, 160, 120+Page );\r
+    Inc( AX, 1 );                               (* Bump angles *)\r
+    Inc( AY, 1 );\r
+    Inc( AZ, 2 );\r
+    mxSetClipRegion( 0, Page, 320, 240 );       (* Set clip to new page *)\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+    mxRotatePalette( @Palette[1], 192, 3 );     (* Rotate palette *)\r
+    (* Draw cube: backface culling is straighforward in this case, so *)\r
+    (* it can be handled by the polygon filling procedure *)\r
+    for I:=0 to 5 do\r
+      mxTexturePoly( 4, Face[I].Vtx, VVtx, Txts[I].Desc, Txts[I].Data, Txts[I].Width );\r
+    mxStartLine( Page );                        (* Flip pages *)\r
+    mxSetPalette( @Palette[1], 1, 192 );        (* Set new palette *)\r
+    Page := 240-Page;\r
+  end;\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/x/modex/DEMO03.EXE b/16/x/modex/DEMO03.EXE
new file mode 100755 (executable)
index 0000000..c646c4b
Binary files /dev/null and b/16/x/modex/DEMO03.EXE differ
diff --git a/16/x/modex/DEMO03.PAS b/16/x/modex/DEMO03.PAS
new file mode 100755 (executable)
index 0000000..01d10f4
--- /dev/null
@@ -0,0 +1,152 @@
+(*\r
+    DEMO03 - Simple star animation, morphs between a cube and a sphere\r
+    (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+const\r
+  MAXVTX = 1000;        (* Number of points *)\r
+  EDGE = 70;            (* Length of cube edge *)\r
+  RADIUS = 90;          (* Radius of sphere *)\r
+  WAITCOUNT = 192;      (* Frames to wait for non-morphing shapes *)\r
+  MS = 32;              (* Number of steps for morphing *)\r
+  Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+  InitMorph1: array[ 0..3 ] of integer = ( 0, MS, 0, 0 );\r
+  InitMorph2: array[ 0..3 ] of integer = ( 0, 0, 0, MS );\r
+  InitDelta1: array[ 0..3 ] of integer = ( 0, -1, 0, +1 );\r
+  InitDelta2: array[ 0..3 ] of integer = ( 0, +1, 0, -1 );\r
+type\r
+  T2DPoint = record\r
+    X, Y: integer;\r
+  end;\r
+  T3DPointArray = array[ 0..MAXVTX-1 ] of TPoint;\r
+  P3DPointArray = ^T3DPointArray;\r
+var\r
+  CubeVtx, SphereVtx, Vtx, XVtx: P3DPointArray;\r
+  VVtx  : array[ 0..MAXVTX-1 ] of T2DPoint;\r
+  Page  : word;\r
+  Status, Count, Delta1, Delta2, Morph1, Morph2: integer;\r
+\r
+procedure Swap( var A, B: longint );\r
+var\r
+  L: longint;\r
+begin\r
+  L := A; A := B; B := L;\r
+end;\r
+\r
+function Toggle( A: longint ): longint;\r
+begin\r
+  Toggle := A;\r
+  if( Random(2) = 0 ) then Toggle := -A;\r
+end;\r
+\r
+procedure Init;\r
+label Retry;\r
+var\r
+  I: integer;\r
+begin\r
+  New( CubeVtx );\r
+  New( SphereVtx );\r
+  New( Vtx );\r
+  New( XVtx );\r
+  (* Build vertexes (yes, I know this piece of code is terrible) *)\r
+  Randomize;\r
+  for I:=0 to MAXVTX-1 do begin\r
+    with CubeVtx^[I] do begin\r
+      (* Build cube *)\r
+      X := (longint(Random(2*EDGE))-EDGE)*$10000;\r
+      Y := (longint(Random(2*EDGE))-EDGE)*$10000;\r
+      Z := Toggle( EDGE*$10000 );\r
+      case Random(3) of\r
+        0: Swap( X, Z );\r
+        1: Swap( Y, Z );\r
+      end;\r
+    end;\r
+    with SphereVtx^[I] do begin\r
+      (* Build sphere *)\r
+Retry:\r
+      X := (longint(Random(2*RADIUS))-RADIUS);\r
+      Y := (longint(Random(2*RADIUS))-RADIUS);\r
+      if( X*X+Y*Y > RADIUS*RADIUS ) then goto Retry;\r
+      Z := Toggle( Round( Sqrt( Abs( RADIUS*RADIUS-X*X-Y*Y ) ) ) );\r
+      case Random(3) of\r
+        0: Swap( X, Z );\r
+        1: Swap( Y, Z );\r
+      end;\r
+      X := X * $10000; Y := Y * $10000; Z := Z * $10000;\r
+    end;\r
+  end;\r
+  (* Initialize morphing *)\r
+  Move( CubeVtx^, Vtx^, SizeOf(Vtx^) );\r
+  Status := 0;\r
+  Count := WAITCOUNT;\r
+end;\r
+\r
+procedure Morph;\r
+var\r
+  I: integer;\r
+begin\r
+  (* Fully unoptimized, slowest loop I could think of! *)\r
+  for I:=0 to MAXVTX-1 do begin\r
+    Vtx^[I].X := ((CubeVtx^[I].X * Morph1)+(SphereVtx^[I].X * Morph2)) div MS;\r
+    Vtx^[I].Y := ((CubeVtx^[I].Y * Morph1)+(SphereVtx^[I].Y * Morph2)) div MS;\r
+    Vtx^[I].Z := ((CubeVtx^[I].Z * Morph1)+(SphereVtx^[I].Z * Morph2)) div MS;\r
+  end;\r
+end;\r
+\r
+var\r
+  AX, AY, AZ: byte;\r
+  I: word;\r
+  C: char;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;          (* Start with hidden page *)\r
+\r
+  AX := 0;\r
+  AY := 0;\r
+  AZ := 0;\r
+  (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+  tdSetTranslation( Trans );\r
+  tdSetPerspective( 400*$10000, $10000, $10000 );\r
+  C := #0;\r
+  repeat\r
+    tdSetRotation( AX, AY, AZ );                (* Set new angles *)\r
+    tdTransform( Vtx^, XVtx^, MAXVTX );         (* 3D transform points *)\r
+    tdTransformToImage( XVtx^, VVtx, MAXVTX, 160, 120+Page );\r
+    Inc( AX, 1 );                               (* Bump angles *)\r
+    Inc( AY, 1 );\r
+    Inc( AZ, 2 );\r
+    mxSetClipRegion( 0, Page, 320, 240 );       (* Set clip to new page *)\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+    (* Draw points *)\r
+    for I:=0 to MAXVTX-1 do\r
+      mxPutPixel( VVtx[I].X, VVtx[I].Y, 128 + XVtx^[I].Z shr 18 );\r
+    mxStartLine( Page );                        (* Flip pages *)\r
+    Page := 240-Page;\r
+    (* Morph *)\r
+    if( Odd(Status) ) then begin\r
+      Morph;\r
+      Inc( Morph1, Delta1 );\r
+      Inc( Morph2, Delta2 );\r
+      if( Morph1 < 0 )or( Morph2 < 0 ) then Inc( Status );\r
+      if( Status = 4 ) then Status := 0;\r
+    end\r
+    else begin\r
+      Dec( Count );\r
+      if( Count < 0 ) then begin\r
+        Inc( Status );\r
+        Count :=  WAITCOUNT;\r
+        Morph1 := InitMorph1[Status];\r
+        Morph2 := InitMorph2[Status];\r
+        Delta1 := InitDelta1[Status];\r
+        Delta2 := InitDelta2[Status];\r
+      end;\r
+    end;\r
+  until( KeyPressed );\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/x/modex/DEMO04.DAT b/16/x/modex/DEMO04.DAT
new file mode 100755 (executable)
index 0000000..72aaad0
Binary files /dev/null and b/16/x/modex/DEMO04.DAT differ
diff --git a/16/x/modex/DEMO04.EXE b/16/x/modex/DEMO04.EXE
new file mode 100755 (executable)
index 0000000..1fec5e8
Binary files /dev/null and b/16/x/modex/DEMO04.EXE differ
diff --git a/16/x/modex/DEMO04.PAS b/16/x/modex/DEMO04.PAS
new file mode 100755 (executable)
index 0000000..1a94631
--- /dev/null
@@ -0,0 +1,198 @@
+(*\r
+    DEMO04 - Multiple textures and triple buffering (3 pages)\r
+    (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+const\r
+  MAXVTX = 256;\r
+  MAXCUB = 2;\r
+  MAXTXT = 2;\r
+  Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+  TxtSunDial: array[ 0..7 ] of word = (\r
+    $7F80,$0080, $0080,$0080, $0080,$7E80, $7F80,$7E80 );\r
+  TxtSapphire : array[ 0..7 ] of word = (\r
+    $0080,$0080, $0080,$1F80, $1F80,$1F80, $1F80,$0080 );\r
+  TxtMarble: array[ 0..7 ] of word = (\r
+    $0080,$8080, $0080,$FD80, $7F80,$FD80, $7F80,$8080 );\r
+type\r
+  T2DPoint = record\r
+    X, Y: integer;\r
+  end;\r
+  TTexture = record\r
+    Desc   : array[ 0..3 ] of record X, Y: word end;\r
+    Width  : word;\r
+    Data   : pointer;\r
+  end;\r
+  TQuad = record\r
+    Vtx    : array[ 0..3 ] of word;\r
+    Texture: word;\r
+  end;\r
+  TCube    = record\r
+    Face   : array[ 0..5 ] of TQuad;\r
+    Base   : integer;\r
+  end;\r
+var\r
+  Vtx, XVtx: array[ 0..MAXVTX ] of TPoint;\r
+  VVtx     : array[ 0..MAXVTX ] of T2DPoint;\r
+  Cube     : array[ 0..MAXCUB ] of TCube;\r
+  ZList    : array[ 0..MAXCUB ] of integer;\r
+  VtxCnt   : word;\r
+  Txts     : array[ 0..MAXTXT ] of TTexture;\r
+  Page     : word;\r
+  Palette  : array[ byte ] of record R, G, B: byte; end;\r
+  TxtDat1, TxtDat2: pointer;\r
+\r
+(* Add a new entry to the vertex array *)\r
+procedure AddVtx( PX, PY, PZ: longint );\r
+begin\r
+  with Vtx[VtxCnt] do begin X:=PX*$10000; Y:=PY*$10000; Z:=PZ*$10000; end;\r
+  Inc( VtxCnt );\r
+end;\r
+\r
+procedure MakeCube( var C: TCube; X1,Y1,Z1, X2,Y2,Z2, TX,TY,TZ, Texture: integer );\r
+const\r
+  FaceIdx: array[ 0..23 ] of integer = (\r
+    0,1,2,3, 0,4,5,1, 1,5,6,2, 2,6,7,3, 3,7,4,0, 6,5,4,7 );\r
+var\r
+  I, VC: integer;\r
+begin\r
+  VC := VtxCnt;\r
+  C.Base := VC;\r
+  AddVtx( X1+TX, Y1+TY, Z1+TZ );\r
+  AddVtx( X2+TX, Y1+TY, Z1+TZ );\r
+  AddVtx( X2+TX, Y2+TY, Z1+TZ );\r
+  AddVtx( X1+TX, Y2+TY, Z1+TZ );\r
+  AddVtx( X1+TX, Y1+TY, Z2+TZ );\r
+  AddVtx( X2+TX, Y1+TY, Z2+TZ );\r
+  AddVtx( X2+TX, Y2+TY, Z2+TZ );\r
+  AddVtx( X1+TX, Y2+TY, Z2+TZ );\r
+  for I:=0 to 23 do C.Face[I shr 2].Vtx[I and 3] := VC+FaceIdx[I];\r
+  for I:=0 to 5 do C.Face[I].Texture := Texture;\r
+end;\r
+\r
+procedure MakeTexture( Idx: integer; var VtxData );\r
+var\r
+  P: ^word;\r
+  I: integer;\r
+begin\r
+  P := @VtxData;\r
+  with Txts[Idx] do begin\r
+    for I:=0 to 3 do begin\r
+      Desc[I].X := P^; Inc( P );\r
+      Desc[I].Y := P^; Inc( P );\r
+    end;\r
+    Width := 129;\r
+    Data := TxtDat1;\r
+  end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+  I: integer;\r
+  V: integer;\r
+  F: file;\r
+  P: array[ 1..768 ] of byte;\r
+begin\r
+  (* Initialize objects *)\r
+  VtxCnt := 0;\r
+  MakeCube( Cube[0], -64,-64,8, 64,64,-8, 0,0,0, 1 );   (* Sundial *)\r
+  Cube[0].Face[0].Texture := 0;\r
+  V := VtxCnt;\r
+  MakeCube( Cube[1], -16,-16,16, 16,16,-16, 0,0,0, 2 ); (* Sapphire *)\r
+  tdSetTranslation( Trans );\r
+  tdSetRotation( 32, 32, 00 );\r
+  tdRotate( Vtx[V], XVtx[V], 8 );       (* Got to rotate this cube *)\r
+  for I:=V to V+7 do begin\r
+    Vtx[I].X := XVtx[I].X;\r
+    Vtx[I].Y := XVtx[I].Y;\r
+    Vtx[I].Z := XVtx[I].Z + 100*$10000;\r
+  end;\r
+  MakeCube( Cube[2], -64,-4,48, 64,4,-48, 0,68,56, 1 ); (* Marble *)\r
+  (* Load texture and palette *)\r
+  Assign( F, 'DEMO04.DAT' );\r
+  Reset( F, 1 );\r
+  BlockRead( F, P, SizeOf(P) );\r
+  mxSetPalette( @P, 0, 256 );\r
+  GetMem( TxtDat1, 63*1024 );\r
+  BlockRead( F, TxtDat1^, 129*286 );\r
+  Close( F );\r
+  TxtDat2 := Ptr( Seg(TxtDat1^), Ofs(TxtDat1^)+129*254 );\r
+  (* Init textures *)\r
+  MakeTexture( 0, TxtSundial );\r
+  MakeTexture( 1, TxtMarble );\r
+  MakeTexture( 2, TxtSapphire );\r
+  Txts[2].Data := TxtDat2;\r
+end;\r
+\r
+(* Sort procedure, not worth optimizing with only a few objects *)\r
+procedure SortObjects;\r
+var\r
+  I, J, K: integer;\r
+  ZMax: array[ 0..MAXCUB ] of longint;\r
+  ZI: integer;\r
+  L: longint;\r
+begin\r
+  for I:=0 to MAXCUB do begin\r
+    L := XVtx[Cube[I].Base].Z;\r
+    for J:=1 to 7 do\r
+      if( L > XVtx[Cube[I].Base+J].Z ) then L := XVtx[Cube[I].Base+J].Z;\r
+    ZMax[I] := L;\r
+    ZList[I] := I;\r
+  end;\r
+  for I:=0 to MAXCUB-1 do begin\r
+    ZI := I;\r
+    for J:=I+1 to MAXCUB do\r
+      if( ZMax[ZList[J]] > ZMax[ZList[ZI]] ) then ZI := J;\r
+    if( ZI <> I ) then begin\r
+      K := ZList[I];\r
+      ZList[I] := ZList[ZI];\r
+      ZList[ZI] := K;\r
+    end;\r
+  end;\r
+end;\r
+\r
+var\r
+  AX, AY, AZ: byte;\r
+  I, J, K: word;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;          (* Start with hidden page *)\r
+\r
+  (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+  AX := 0; AY := 0; AZ := 0;\r
+  tdSetTranslation( Trans );\r
+  tdSetPerspective( 600*$10000, $10000, $10000 );\r
+  (* Main loop, all magic here! *)\r
+  while( not KeyPressed ) do begin\r
+    tdSetRotation( AX, AY, AZ );                (* Set new angles *)\r
+    tdTransform( Vtx, XVtx, VtxCnt );           (* 3D transform points *)\r
+    tdTransformToImage( XVtx, VVtx, VtxCnt, 160, 120+Page );\r
+    Inc( AX, 1 );                               (* Bump angles *)\r
+    Inc( AY, 2 );\r
+    Inc( AZ, 1 );\r
+    mxSetClipRegion( 0, Page, 320, 240 );       (* Set clip to new page *)\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+    (* Draw objects *)\r
+    SortObjects;\r
+    for I:=0 to MAXCUB do with Cube[ZList[I]] do begin\r
+      for J:=0 to 5 do begin\r
+        K := Face[J].Texture;\r
+        mxTexturePoly( 4, Face[J].Vtx, VVtx, Txts[K].Desc, Txts[K].Data^, Txts[K].Width );\r
+      end;\r
+    end;\r
+    (* Flip page: at 320x240 the Start Address Register Low is always zero *)\r
+    case Page of\r
+      0  : begin PortW[$3D4] := $000C; Page := 240; end;\r
+      240: begin PortW[$3D4] := $4B0C; Page := 480; end;\r
+      480: begin PortW[$3D4] := $960C; Page := 0; end;\r
+    end;\r
+    mxWaitRetrace; (* If the frame rate seems low, try to remove this line *)\r
+  end;\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/x/modex/DEMO05.EXE b/16/x/modex/DEMO05.EXE
new file mode 100755 (executable)
index 0000000..21a7c20
Binary files /dev/null and b/16/x/modex/DEMO05.EXE differ
diff --git a/16/x/modex/DEMO05.PAS b/16/x/modex/DEMO05.PAS
new file mode 100755 (executable)
index 0000000..819c5cf
--- /dev/null
@@ -0,0 +1,131 @@
+(*\r
+   DEMO05 - A Gouraud-shaded rotating torus\r
+   (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+(* Define ALTPAL for alternate palette *)\r
+{$define ALTPAL}\r
+\r
+const\r
+  MAXVTX1 = 15; RADIUS1 = 70;   (* MAXVTX1+1 must be multiple of 4 *)\r
+  MAXVTX2 = 15; RADIUS2 = 30;\r
+  MAXVTX  = (MAXVTX1+1)*(MAXVTX2+1)-1;\r
+  MAXFACE = MAXVTX;\r
+  Trans : TPoint = ( X:0; Y:0; Z:0 );           (* Object translation *)\r
+  Light : TPoint = ( X:0; Y:0; Z:-63*$10000 );  (* Light direction *)\r
+type\r
+  TQuad   = record\r
+    QVtx  : array[ 0..3 ] of integer;\r
+  end;\r
+var\r
+  Vtx, XVtx : array[ 0..MAXVTX ] of TPoint;     (* Points *)\r
+  VVtx      : array[ 0..MAXVTX ] of record X, Y: integer end;\r
+  Face      : array[ 0..MAXFACE ] of TQuad;     (* Polys *)\r
+  Culled    : array[ 0..MAXFACE ] of integer;\r
+  GNrm,XGNrm: array[ 0..MAXVTX ] of TVector;    (* Gouraud normals *)\r
+  VtxLight  : array[ 0..MAXVTX ] of integer;    (* Points brightness *)\r
+  Page      : word;\r
+\r
+function GetVtx( I1, I2: integer ): integer;\r
+begin\r
+  GetVtx := (I1 mod (MAXVTX1+1))*(MAXVTX2+1) + I2 mod (MAXVTX2+1);\r
+end;\r
+\r
+procedure Init;\r
+var\r
+  R, N, X, Y, Z: real;\r
+  I, J, K, V: integer;\r
+begin\r
+  (* Build vertexes *)\r
+  for I:=0 to MAXVTX1 do begin\r
+    K := (I + (MAXVTX1+1) shr 2) mod (MAXVTX1+1);\r
+    R := RADIUS1 + RADIUS2*Cos( 2*K*Pi / (MAXVTX1+1) );\r
+    for J:=0 to MAXVTX2 do begin\r
+      V := I*(MAXVTX2+1)+J;                     (* Index of current vertex *)\r
+      (* Compute coordinates of current vertex *)\r
+      X := R*Cos(2*J*Pi / (MAXVTX2+1));         (* Get coordinates *)\r
+      Y := R*Sin(2*J*Pi / (MAXVTX2+1));\r
+      Z := RADIUS2*Sin(2*K*Pi / (MAXVTX1+1));\r
+      Vtx[V].X := Round( X )*$10000;            (* Save coordinates *)\r
+      Vtx[V].Y := Round( Y )*$10000;\r
+      Vtx[V].Z := Round( Z )*$10000;\r
+      (* Compute direction of Gouraud normal thru current vertex *)\r
+      X := X - RADIUS1*Cos(2*J*Pi / (MAXVTX2+1));\r
+      Y := Y - RADIUS1*Sin(2*J*Pi / (MAXVTX2+1));\r
+      N := Sqrt( X*X + Y*Y + Z*Z );             (* Get vector length *)\r
+      GNrm[V].X := Trunc( X*$10000/N );         (* Save normal vector *)\r
+      GNrm[V].Y := Trunc( Y*$10000/N );\r
+      GNrm[V].Z := Trunc( Z*$10000/N );\r
+    end;\r
+  end;\r
+  (* Generate faces so that depth-sorting is not needed: there are still *)\r
+  (* some *very* little errors, but this is the best I could devise *)\r
+  J := 0;\r
+  K := 0;\r
+  for I:=0 to MAXFACE do with Face[I] do begin\r
+    QVtx[0] := GetVtx( J, K );\r
+    QVtx[1] := GetVtx( J, K+1 );\r
+    QVtx[2] := GetVtx( J+1, K+1 );\r
+    QVtx[3] := GetVtx( J+1, K );\r
+    Inc( K );\r
+    if( K > MAXVTX2 ) then begin\r
+      K := 0;\r
+      Inc( J );\r
+    end;\r
+  end;\r
+{$ifndef ALTPAL}\r
+  for I:=0 to 63 do mxSetColor( I+64, 0, 0, I );     (* Blue palette *)\r
+{$else}\r
+  for I:=0 to 31 do mxSetColor(I+64, 0, I shl 1, 0); (* Green neon palette *)\r
+  for I:=32 to 63 do mxSetColor ( I+64, (I-32) shl 1, 63, (I-32) shl 1 );\r
+{$endif}\r
+end;\r
+\r
+var\r
+  AX, AY, AZ: byte;\r
+  I: word;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;          (* Start with hidden page *)\r
+\r
+  AX := 0;\r
+  AY := 0;\r
+  AZ := 0;\r
+  (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+  tdSetTranslation( Trans );\r
+  tdSetLight( Light );\r
+  tdSetPerspective( 400*$10000, $10000, $10000 );\r
+  (* Main loop, all magic here! *)\r
+  while( not KeyPressed ) do begin\r
+    tdSetRotation( AX, AY, AZ );                (* Set new angles *)\r
+    tdTransform( Vtx, XVtx, MAXVTX+1 );         (* 3D transform points *)\r
+    tdTransformToImage( XVtx, VVtx, MAXVTX+1, 160, 120+Page );\r
+    tdRotate( GNrm, XGNrm, MAXVTX+1 );          (* Rotate Gouraud normals *)\r
+    tdTransformLight( XGNrm, VtxLight, MAXVTX+1 );\r
+    (* Backplane culling is not really needed here! *)\r
+    FillChar( Culled, SizeOf(Culled), 0 );\r
+    tdBackPlaneCull( Face, XVtx, Culled, MAXFACE+1, SizeOf(TQuad) );\r
+    Inc( AX, 1 );                               (* Bump angles *)\r
+    Inc( AY, 2 );\r
+    Inc( AZ, 3 );\r
+    mxSetClipRegion( 0, Page, 320, 240 );       (* Set clip to new page *)\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+    (* Draw polygons *)\r
+    for I:=0 to MAXFACE do with Face[I] do\r
+      if( Culled[I] >= 0 ) then mxGouraudPoly( 4, QVtx, VVtx, VtxLight, 64 );\r
+    (* Flip page: at 320x240 the Start Address Register Low is always zero *)\r
+    case Page of\r
+      0  : begin PortW[$3D4] := $000C; Page := 240; end;\r
+      240: begin PortW[$3D4] := $4B0C; Page := 480; end;\r
+      480: begin PortW[$3D4] := $960C; Page := 0; end;\r
+    end;\r
+    mxWaitRetrace; (* Uncomment this instruction if screen flickers *)\r
+  end;\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/x/modex/DEMO06.DAT b/16/x/modex/DEMO06.DAT
new file mode 100755 (executable)
index 0000000..1ac2c2b
Binary files /dev/null and b/16/x/modex/DEMO06.DAT differ
diff --git a/16/x/modex/DEMO06.EXE b/16/x/modex/DEMO06.EXE
new file mode 100755 (executable)
index 0000000..f1308e8
Binary files /dev/null and b/16/x/modex/DEMO06.EXE differ
diff --git a/16/x/modex/DEMO06.PAS b/16/x/modex/DEMO06.PAS
new file mode 100755 (executable)
index 0000000..f26af06
--- /dev/null
@@ -0,0 +1,135 @@
+(*\r
+    DEMO06 - Magnifying glass\r
+    (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+  R = 40;               (* Lens radius *)\r
+  K : real = 1.8;       (* Magnifying factor, less makes a stronger lens *)\r
+type\r
+  TLine   = array[ 0..319 ] of byte;\r
+  PLine   = ^TLine;\r
+  TScreen = array[ 0..239 ] of PLine;\r
+var\r
+  VScreen: TScreen;                             (* Virtual screen *)\r
+  BallX  : array[ 0..R, 0..R ] of integer;\r
+  BallY  : array[ 0..R, 0..R ] of integer;\r
+  Sprite : array[ -R..R, -R..R ] of byte;\r
+  Page   : word;\r
+\r
+(* Returns "lens-view" coordinates of X,Y *)\r
+procedure GetCoords( var X, Y: integer );\r
+var\r
+  LR, Z, SinA, SinB, TgB, Q: real;\r
+begin\r
+  LR := Sqrt( X*X + Y*Y );\r
+  if( LR = 0 ) then Exit;\r
+  if( LR < R ) then begin\r
+    Z := Sqrt( R*R - LR*LR );\r
+    SinA := LR / R;\r
+    SinB := SinA / K;\r
+    TgB := SinB / Sqrt( 1-SinB*SinB );\r
+    Q := LR - TgB*Z;\r
+    X := Round( X * ( Q/LR ) );\r
+    Y := Round( Y * ( Q/LR ) );\r
+  end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+  F      : file;\r
+  Palette: array[ 0..767 ] of record R, G, B: byte; end;\r
+  X, Y,\r
+  X2, Y2 : integer;\r
+begin\r
+  (* Load background image *)\r
+  Assign( F, 'demo06.dat' );\r
+  Reset( F, 1 );\r
+  BlockRead( F, Palette, 768 );\r
+  mxSetPalette( @Palette, 0, 256 );\r
+  for Y:=0 to 239 do begin\r
+    New( VScreen[Y] );\r
+    BlockRead( F, VScreen[Y]^, 320 );\r
+    mxPutImage( VScreen[Y], 0, 480+Y, 320, 1, OP_MOVE );\r
+  end;\r
+  Close( F );\r
+  (* Build lens *)\r
+  for X:=0 to R do begin\r
+    for Y:=0 to R do begin\r
+      X2 := X;\r
+      Y2 := Y;\r
+      GetCoords( X2, Y2 );\r
+      BallX[X, Y] := X2;\r
+      BallY[X, Y] := Y2;\r
+    end;\r
+  end;\r
+end;\r
+\r
+procedure PutLens( OX, OY: integer );\r
+var\r
+  X, Y: integer;\r
+begin\r
+  for X:=0 to R do begin\r
+    for Y:=0 to R do begin\r
+      Sprite[Y][X] := VScreen[ OY+BallY[X,Y] ]^[ OX+BallX[X,Y] ];\r
+      Sprite[Y][-X] := VScreen[ OY+BallY[X,Y] ]^[ OX-BallX[X,Y] ];\r
+      Sprite[-Y][X] := VScreen[ OY-BallY[X,Y] ]^[ OX+BallX[X,Y] ];\r
+      Sprite[-Y][-X] := VScreen[ OY-BallY[X,Y] ]^[ OX-BallX[X,Y] ];\r
+    end;\r
+  end;\r
+  (* Draw the sprite *)\r
+  mxPutImage( @Sprite, OX-R, OY-R+Page, 2*R+1, 2*R+1, OP_MOVE );\r
+end;\r
+\r
+function Delta: integer;\r
+begin\r
+  Delta := Random(3)+2;\r
+end;\r
+\r
+procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer );\r
+begin\r
+  if( Cond ) then begin\r
+    Coord := NewCoord;\r
+    DeltaC := Sign*Delta;\r
+  end;\r
+end;\r
+\r
+var\r
+  X, Y, DX, DY: integer;\r
+  C: char;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;\r
+  X := R;\r
+  Y := R;\r
+  Randomize;\r
+  DX := Delta;\r
+  DY := Delta;\r
+\r
+  (* Main loop *)\r
+  repeat\r
+    (* Update video *)\r
+    mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+    PutLens( X, Y );\r
+    mxCircle( X, Page+Y, R, 0 );\r
+    (* Update lens coordinates *)\r
+    Inc( X, DX );\r
+    Check( X+R >= 319, X, DX, 319-R, -1 );\r
+    Check( X <= R, X, DX, R, +1 );\r
+    Inc( Y, DY );\r
+    Check( Y+R >= 239, Y, DY, 239-R, -1 );\r
+    Check( Y <= R, Y, DY, R, +1 );\r
+    (* Flip pages: double buffering, avoid wait for display *)\r
+    case Page of\r
+      0  : begin PortW[$3D4] := $000C; Page := 240; end;\r
+      240: begin PortW[$3D4] := $4B0C; Page := 0; end;\r
+    end;\r
+    mxWaitRetrace; (* Wait for hidden page to show *)\r
+  until( KeyPressed );\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/x/modex/DEMO07.EXE b/16/x/modex/DEMO07.EXE
new file mode 100755 (executable)
index 0000000..8a40116
Binary files /dev/null and b/16/x/modex/DEMO07.EXE differ
diff --git a/16/x/modex/DEMO07.PAS b/16/x/modex/DEMO07.PAS
new file mode 100755 (executable)
index 0000000..04fff79
--- /dev/null
@@ -0,0 +1,68 @@
+(*\r
+    DEMO07 - Hardware scrolling\r
+    Copyright (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+  (* Change this if scrolling seems jerky (this simple program does *)\r
+  (* not handle vertical retrace/display very well) *)\r
+  STEPS = 5;\r
+\r
+procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer );\r
+begin\r
+  if( Cond ) then begin\r
+    Coord := NewCoord;\r
+    DeltaC := Sign*(Random(3)+2);\r
+  end;\r
+end;\r
+\r
+var\r
+  I, X, Y, DX, DY: integer;\r
+begin\r
+  (* Initialize library and graphics mode *)\r
+  mxInit;\r
+  mxSetMode( MX_320x200 );\r
+  (* Set a 640x400 virtual screen *)\r
+  mxSetVirtualScreen( 640, 400 );\r
+  mxSetClip( TRUE );\r
+\r
+  X := 0;\r
+  Y := 0;\r
+  DX := 1;\r
+  DY := 1;\r
+\r
+  (* Main loop: draw lines, circles, points and rectangles in separate *)\r
+  (* 320x200 windows, while smoothly panning virtual screen *)\r
+  while( not KeyPressed ) do begin\r
+    (* Points *)\r
+    mxSetClipRegion( 0, 0, 320, 200 );\r
+    for I:=1 to STEPS do\r
+      mxPutPixel( Random(320), Random(200), Random(16) );\r
+    (* Lines *)\r
+    mxSetClipRegion( 0, 200, 320, 200 );\r
+    for I:=1 to STEPS do\r
+      mxLine( Random(320), Random(200)+200, Random(320), Random(200)+200, Random(16), OP_SET );\r
+    (* Circles *)\r
+    mxSetClipRegion( 320, 0, 320, 200 );\r
+    for I:=1 to STEPS do\r
+      mxCircle( Random(320)+320, Random(200), Random(100), Random(16) );\r
+    (* Boxes *)\r
+    mxSetClipRegion( 320, 200, 320, 200 );\r
+    for I:=1 to STEPS do\r
+      mxFillBox( Random(320)+320, Random(200)+200, Random(100)+1, Random(100)+1, Random(16), OP_SET );\r
+    (* Pan *)\r
+    Inc( X, DX );\r
+    Check( X+320 >= 639, X, DX, 319, -1 );\r
+    Check( X < 0, X, DX, 0, +1 );\r
+    Inc( Y, DY );\r
+    Check( Y+200 >= 399, Y, DY, 199, -1 );\r
+    Check( Y < 0, Y, DY, 0, +1 );\r
+    mxPan( X, Y );\r
+    mxWaitRetrace;\r
+  end;\r
+\r
+  (* Shutdown *)\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/x/modex/MATH.INC b/16/x/modex/MATH.INC
new file mode 100755 (executable)
index 0000000..742af41
--- /dev/null
@@ -0,0 +1,34 @@
+;\r
+; MATH.INC - Include file for THREED.ASM\r
+;\r
+\r
+; 3-dimensional point, coordinates in fixed format (16:16)\r
+;\r
+TPOINT  STRUC\r
+        X       DD      ?\r
+        Y       DD      ?\r
+        Z       DD      ?\r
+TPOINT  ENDS\r
+\r
+; 2-dimensional point, coordinates in integer format\r
+;\r
+TIMAGEPOINT     STRUC\r
+        IX      DW      ?\r
+        IY      DW      ?\r
+TIMAGEPOINT     ENDS\r
+\r
+; Fixed-point divide: EAX = EAX / arg\r
+;\r
+.xdiv   MACRO   arg\r
+        xor     edx, edx\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    arg\r
+ENDM\r
+\r
+; Fixed-point multiply: EAX = EAX * arg\r
+;\r
+.xmul   MACRO   arg\r
+        imul    arg\r
+        shrd    eax, edx, 16\r
+ENDM\r
diff --git a/16/x/modex/PLASMA.PAS b/16/x/modex/PLASMA.PAS
new file mode 100755 (executable)
index 0000000..237e292
--- /dev/null
@@ -0,0 +1,103 @@
+unit Plasma;\r
+interface\r
+\r
+const\r
+  PAL_RGB       = 0;\r
+  PAL_CLOUDS    = 1;\r
+  PAL_LANDSCAPE = 2;\r
+\r
+procedure MakePlasma( X, Y: integer; W, H: word; C1, C2, C3, C4: byte );\r
+procedure MakePlasmaPalette( var Palette; What: word );\r
+\r
+implementation uses Modex;\r
+\r
+procedure NewColor( XA, YA, X, Y, XB, YB: integer );\r
+var\r
+  Color: longint;\r
+begin\r
+  Color := Abs( XA-XB )+Abs( YA-YB );\r
+  Color := Random( Color shl 1 )-Color;\r
+  Color := (Color+mxGetPixel( XA, YA )+mxGetPixel( XB, YB )+1) shr 1;\r
+  if( Color < 1 ) then Color := 1;\r
+  if( Color > 192 ) then Color := 192;\r
+  if( mxGetPixel( X, Y ) = 0 ) then\r
+    mxPutPixel( X, Y, Lo(Color) );\r
+end;\r
+\r
+procedure Divide( X1, Y1, X2, Y2: integer );\r
+var\r
+  X, Y, Color: integer;\r
+begin\r
+  if not( (X2-X1<2)and(Y2-Y1<2) ) then begin\r
+    X := (X1+X2) shr 1;\r
+    Y := (Y1+Y2) shr 1;\r
+    NewColor( X1, Y1, X, Y1, X2, Y1 );\r
+    NewColor( X2, Y1, X2, Y, X2, Y2 );\r
+    NewColor( X1, Y2, X, Y2, X2, Y2 );\r
+    NewColor( X1, Y1, X1, Y, X1, Y2 );\r
+    Color := (mxGetPixel( X1, Y1 )+mxGetPixel( X2, Y1 )+\r
+              mxGetPixel( X2, Y2 )+mxGetPixel( X1, Y2 )) shr 2;\r
+    mxPutPixel( X, Y, Color );\r
+    Divide( X1, Y1, X, Y );\r
+    Divide( X, Y1, X2, Y );\r
+    Divide( X, Y, X2, Y2 );\r
+    Divide( X1, Y, X, Y2 );\r
+  end;\r
+end;\r
+\r
+procedure MakePlasma;\r
+begin\r
+  Dec( W );\r
+  Dec( H );\r
+  mxPutPixel( X, Y, C1 );\r
+  mxPutPixel( X, Y+H, C2 );\r
+  mxPutPixel( X+W, Y+H, C3 );\r
+  mxPutPixel( X+W, Y, C4 );\r
+  Divide( X, Y, X+W, Y+H );\r
+end;\r
+\r
+procedure MakePlasmaPalette;\r
+type\r
+  TPal = array[ byte ] of record R, G, B: byte end;\r
+var\r
+  I: word;\r
+begin\r
+  FillChar( TPal(Palette)[1], 192*3, 0 );\r
+  case What of\r
+    PAL_CLOUDS:\r
+      for I:=1 to 192 do begin\r
+        TPal(Palette)[I].R := Abs( I-96 )*63 div 96;\r
+        TPal(Palette)[I].G := Abs( I-96 )*63 div 96;\r
+        TPal(Palette)[I].B := 63;\r
+      end;\r
+    PAL_LANDSCAPE:\r
+      begin\r
+        for I:=0 to 31 do begin\r
+          TPal(Palette)[I+1].R := I;\r
+          TPal(Palette)[I+1].G := I;\r
+          TPal(Palette)[I+1].B := I + I shr 1+15;\r
+        end;\r
+        for I:=32 to 63 do begin\r
+          TPal(Palette)[I+1].R := 0;\r
+          TPal(Palette)[I+1].G := I;\r
+          TPal(Palette)[I+1].B := 0;\r
+        end;\r
+        for I:=64 to 191 do begin\r
+          TPal(Palette)[I+1].R := (I-64) div 3 + 15;\r
+          TPal(Palette)[I+1].G := (I-64) div 3 + 15;\r
+          TPal(Palette)[I+1].B := (I-64) div 3 + 15;\r
+        end;\r
+      end;\r
+    else\r
+      for I:=1 to 64 do begin\r
+        TPal(Palette)[I].G := I-1;\r
+        TPal(Palette)[I].B := 64-I;\r
+        TPal(Palette)[I+64].R := I-1;\r
+        TPal(Palette)[I+64].G := 64-I;\r
+        TPal(Palette)[I+128].B := I-1;\r
+        TPal(Palette)[I+128].R := 64-I;\r
+      end;\r
+  end;\r
+end;\r
+\r
+end.
\ No newline at end of file
diff --git a/16/x/modex/QIX2.EXE b/16/x/modex/QIX2.EXE
new file mode 100755 (executable)
index 0000000..a10d7db
Binary files /dev/null and b/16/x/modex/QIX2.EXE differ
diff --git a/16/x/modex/QIX2.PAS b/16/x/modex/QIX2.PAS
new file mode 100755 (executable)
index 0000000..d1b5979
--- /dev/null
@@ -0,0 +1,210 @@
+{$E-,N+}\r
+uses Crt, Modex;\r
+\r
+const\r
+  DEFVERT = 12;         (* Vertex count *)\r
+  DEFREPL = 3;          (* Repetition count *)\r
+  DEFQIXS = 2;          (* Qixs *)\r
+  FADESPEED = 48;\r
+type\r
+  TPoint = record\r
+    X, Y : integer;\r
+  end;\r
+  TRGB = record\r
+    R, G, B: byte;\r
+  end;\r
+  TQix = record\r
+    Color: integer;\r
+    Vert : array[ 0..DEFVERT-1, 0..DEFREPL-1 ] of TPoint;\r
+    Delta: array[ 0..DEFVERT-1 ] of TPoint;\r
+  end;\r
+var\r
+  Page : integer;\r
+  MaxX,\r
+  MaxY : word;\r
+  Qix  : array[ 0..DEFQIXS-1 ] of TQix;\r
+  Pal  : array[ byte ] of TRGB;\r
+\r
+type\r
+  TReal = double;\r
+  TRPoint = record\r
+    X, Y: TReal;\r
+  end;\r
+  TMatrix = array[ 0..3, 0..3 ] of TReal;\r
+var\r
+  M: TMatrix;\r
+  G: array[ 0..DEFVERT-1 ] of TRPoint;\r
+  C: array[ 0..DEFVERT-1 ] of TRPoint;\r
+\r
+procedure BumpPal( Idx, DR, DG, DB, Steps: integer );\r
+var\r
+  I: integer;\r
+begin\r
+  for I:=1 to Steps do begin\r
+    Pal[Idx+1].R := Pal[Idx].R + DR;\r
+    Pal[Idx+1].G := Pal[Idx].G + DG;\r
+    Pal[Idx+1].B := Pal[Idx].B + DB;\r
+    Inc( Idx );\r
+  end;\r
+end;\r
+\r
+procedure InitPalette;\r
+begin\r
+  with Pal[0] do begin R:=0; G:=0; B:=0; end;\r
+  with Pal[1] do begin R:=0; G:=0; B:=62; end;\r
+  BumpPal( 1,   0, 2, -2,  31 );\r
+  BumpPal( 32,  2, -2, 0,  31 );\r
+  BumpPal( 63,  -2, 2, 2,  31 );\r
+  BumpPal( 94,  2, 0, -2,  31 );\r
+  BumpPal( 125, -2, -2, 2, 31 );\r
+end;\r
+\r
+procedure Init( var Qix: TQix; Color: integer );\r
+var\r
+  I: integer;\r
+begin\r
+  FillChar( Qix.Vert, SizeOf(Qix.Vert), 0 );\r
+  for I:=0 to DEFVERT-1 do begin\r
+    Qix.Vert[I, DEFREPL-1].X := Random( MaxX );\r
+    Qix.Vert[I, DEFREPL-1].Y := Random( MaxY );\r
+    Qix.Delta[I].X := Random(5)+1;\r
+    Qix.Delta[I].Y := Random(5)+1;\r
+  end;\r
+  Qix.Color := Color;\r
+\r
+  (* Initialize matrix (Catmull-Rom) *)\r
+  M[0,0] := -1/2; M[0,1] := 3/2; M[0,2] := -3/2; M[0,3] := 1/2;\r
+  M[1,0] := 1; M[1,1] := -5/2; M[1,2] := 2; M[1,3] := -1/2;\r
+  M[2,0] := -1/2; M[2,1] := 0; M[2,2] := 1/2; M[2,3] := 0;\r
+  M[3,0] := 0; M[3,1] := 1; M[3,2] := 0; M[3,3] := 0;\r
+end;\r
+\r
+procedure mxBezier( var Qix: TQix; I0, Idx, N: integer );\r
+var\r
+  I, J: integer;\r
+  T, T2, T3: TReal;\r
+  X0, Y0, X, Y: TReal;\r
+  Delta: TReal;\r
+begin\r
+  (* Compute coefficients *)\r
+  for I:=0 to 3 do begin\r
+    C[I].X := 0;\r
+    for J:=0 to 3 do C[I].X := C[I].X + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].X;\r
+    C[I].Y := 0;\r
+    for J:=0 to 3 do C[I].Y := C[I].Y + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].Y;\r
+  end;\r
+  X0 := C[3].X;\r
+  Y0 := C[3].Y;\r
+  Delta := 1 / N;\r
+  T := 0;\r
+  for I:=1 to N do begin\r
+    T := T + Delta;\r
+    T2 := T*T;\r
+    T3 := T*T2;\r
+    X := C[0].X*T3 + C[1].X*T2 + C[2].X*T + C[3].X;\r
+    Y := C[0].Y*T3 + C[1].Y*T2 + C[2].Y*T + C[3].Y;\r
+    mxLine( Round(X0), Page+Round(Y0), Round(X), Page+Round(Y), Qix.Color, OP_SET );\r
+    X0 := X;\r
+    Y0 := Y;\r
+  end;\r
+end;\r
+\r
+procedure Plot( var Qix: TQix; Idx: integer );\r
+var\r
+  I, J: integer;\r
+begin\r
+  for I:=0 to DEFVERT-1 do begin\r
+    mxBezier( Qix, I, Idx, 12 );\r
+  end;\r
+end;\r
+\r
+procedure Update( var Qix: TQix; Idx: integer );\r
+var\r
+  I: integer;\r
+begin\r
+  for I:=0 to DEFVERT-1 do with Qix do begin\r
+    Inc( Vert[I,Idx].X, Delta[I].X );\r
+    if( Vert[I,Idx].X < 0 ) then begin\r
+      Vert[I,Idx].X := 0;\r
+      Delta[I].X := Random( 5 )+1;\r
+    end;\r
+    if( Vert[I,Idx].X > MaxX ) then begin\r
+      Vert[I,Idx].X := MaxX;\r
+      Delta[I].X := -Random( 5 )-1;\r
+    end;\r
+    Inc( Vert[I,Idx].Y, Delta[I].Y );\r
+    if( Vert[I,Idx].Y < 0 ) then begin\r
+      Vert[I,Idx].Y := 0;\r
+      Delta[I].Y := Random( 5 )+1;\r
+    end;\r
+    if( Vert[I,Idx].Y > MaxY ) then begin\r
+      Vert[I,Idx].Y := MaxY;\r
+      Delta[I].Y := -Random( 5 )-1;\r
+    end;\r
+  end;\r
+end;\r
+\r
+procedure Copy( var Qix: TQix; Dest, Src: integer );\r
+var\r
+  I: integer;\r
+begin\r
+  for I:=0 to DEFVERT-1 do with Qix do begin\r
+    Vert[I,Dest].X := Vert[I,Src].X;\r
+    Vert[I,Dest].Y := Vert[I,Src].Y;\r
+  end;\r
+end;\r
+\r
+procedure AnimateQix;\r
+var\r
+  Q, Idx, I, J, P, Count: integer;\r
+begin\r
+  Count := 0;\r
+  P := DEFREPL-1;\r
+  I := 0;\r
+  J := 1;\r
+  repeat\r
+    mxSetClipRegion( 0, Page, MaxX+1, MaxY+1 );\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, MaxX+1, MaxY+1, 0, OP_SET );\r
+    for Q:=0 to DEFQIXS-1 do begin\r
+      Copy( Qix[Q], I, P );\r
+      Update( Qix[Q], I );\r
+      for Idx:=0 to DEFREPL-1 do begin\r
+        Plot( Qix[Q], Idx );\r
+      end;\r
+    end;\r
+    I := (I+1) mod DEFREPL;\r
+    J := (J+1) mod DEFREPL;\r
+    P := (P+1) mod DEFREPL;\r
+    Inc( Count );\r
+    mxStartLine( Page );\r
+    if( Count >= FADESPEED ) then begin\r
+      for Q:=0 to DEFQIXS-1 do begin\r
+        Inc( Qix[Q].Color );\r
+        if( Qix[Q].Color > 156 ) then\r
+          Qix[Q].Color := 1;\r
+      end;\r
+      Count := 0;\r
+    end;\r
+    Page := 240-Page;\r
+  until( KeyPressed );\r
+end;\r
+\r
+var\r
+  I: integer;\r
+begin\r
+  Randomize;\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  mxGetScreenSize( MaxX, MaxY );\r
+  for I:=0 to DEFQIXS-1 do\r
+    Init( Qix[I], (I*(155 div DEFQIXS)) mod 155 + 1 );\r
+  InitPalette;\r
+  mxSetPalette( @Pal, 0, 157 );\r
+  Page := 240;\r
+  Dec( MaxX );\r
+  Dec( MaxY );\r
+  AnimateQix;\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/x/modex/README.TXT b/16/x/modex/README.TXT
new file mode 100755 (executable)
index 0000000..306e8b9
--- /dev/null
@@ -0,0 +1,8 @@
+ModeX - A graphical library for DOS programs\r
+Copyright (c) 1993-1994 Alessandro Scotti\r
+http://www.ascotti.org/\r
+\r
+Please look at the above site in the "Art of..." and\r
+then in the "Old programs" section for more information.\r
+\r
+\r
diff --git a/16/x/modex/SINCOS.INC b/16/x/modex/SINCOS.INC
new file mode 100755 (executable)
index 0000000..6986eee
--- /dev/null
@@ -0,0 +1,518 @@
+;\r
+; SINCOS.INC - Sin/cos tables for THREED.ASM\r
+;\r
+\r
+tblSin  LABEL DWORD\r
+  DD    0\r
+  DD    411733\r
+  DD    823219\r
+  DD    1234209\r
+  DD    1644455\r
+  DD    2053710\r
+  DD    2461729\r
+  DD    2868265\r
+  DD    3273072\r
+  DD    3675909\r
+  DD    4076531\r
+  DD    4474698\r
+  DD    4870169\r
+  DD    5262706\r
+  DD    5652074\r
+  DD    6038037\r
+  DD    6420363\r
+  DD    6798821\r
+  DD    7173184\r
+  DD    7543226\r
+  DD    7908725\r
+  DD    8269459\r
+  DD    8625213\r
+  DD    8975771\r
+  DD    9320922\r
+  DD    9660458\r
+  DD    9994176\r
+  DD    10321873\r
+  DD    10643353\r
+  DD    10958422\r
+  DD    11266890\r
+  DD    11568571\r
+  DD    11863283\r
+  DD    12150850\r
+  DD    12431097\r
+  DD    12703856\r
+  DD    12968963\r
+  DD    13226258\r
+  DD    13475586\r
+  DD    13716797\r
+  DD    13949745\r
+  DD    14174291\r
+  DD    14390298\r
+  DD    14597637\r
+  DD    14796184\r
+  DD    14985817\r
+  DD    15166424\r
+  DD    15337895\r
+  DD    15500126\r
+  DD    15653022\r
+  DD    15796488\r
+  DD    15930439\r
+  DD    16054795\r
+  DD    16169479\r
+  DD    16274424\r
+  DD    16369565\r
+  DD    16454846\r
+  DD    16530216\r
+  DD    16595628\r
+  DD    16651044\r
+  DD    16696429\r
+  DD    16731757\r
+  DD    16757007\r
+  DD    16772163\r
+  DD    16777216\r
+  DD    16772163\r
+  DD    16757007\r
+  DD    16731757\r
+  DD    16696429\r
+  DD    16651044\r
+  DD    16595628\r
+  DD    16530216\r
+  DD    16454846\r
+  DD    16369565\r
+  DD    16274424\r
+  DD    16169479\r
+  DD    16054795\r
+  DD    15930439\r
+  DD    15796488\r
+  DD    15653022\r
+  DD    15500126\r
+  DD    15337895\r
+  DD    15166424\r
+  DD    14985817\r
+  DD    14796184\r
+  DD    14597637\r
+  DD    14390298\r
+  DD    14174291\r
+  DD    13949745\r
+  DD    13716797\r
+  DD    13475586\r
+  DD    13226258\r
+  DD    12968963\r
+  DD    12703856\r
+  DD    12431097\r
+  DD    12150850\r
+  DD    11863283\r
+  DD    11568571\r
+  DD    11266890\r
+  DD    10958422\r
+  DD    10643353\r
+  DD    10321873\r
+  DD    9994176\r
+  DD    9660458\r
+  DD    9320922\r
+  DD    8975771\r
+  DD    8625213\r
+  DD    8269459\r
+  DD    7908725\r
+  DD    7543226\r
+  DD    7173184\r
+  DD    6798821\r
+  DD    6420363\r
+  DD    6038037\r
+  DD    5652074\r
+  DD    5262706\r
+  DD    4870169\r
+  DD    4474698\r
+  DD    4076531\r
+  DD    3675909\r
+  DD    3273072\r
+  DD    2868265\r
+  DD    2461729\r
+  DD    2053710\r
+  DD    1644455\r
+  DD    1234209\r
+  DD    823219\r
+  DD    411733\r
+  DD    0\r
+  DD    -411733\r
+  DD    -823219\r
+  DD    -1234209\r
+  DD    -1644455\r
+  DD    -2053710\r
+  DD    -2461729\r
+  DD    -2868265\r
+  DD    -3273072\r
+  DD    -3675909\r
+  DD    -4076531\r
+  DD    -4474698\r
+  DD    -4870169\r
+  DD    -5262706\r
+  DD    -5652074\r
+  DD    -6038037\r
+  DD    -6420363\r
+  DD    -6798821\r
+  DD    -7173184\r
+  DD    -7543226\r
+  DD    -7908725\r
+  DD    -8269459\r
+  DD    -8625213\r
+  DD    -8975771\r
+  DD    -9320922\r
+  DD    -9660458\r
+  DD    -9994176\r
+  DD    -10321873\r
+  DD    -10643353\r
+  DD    -10958422\r
+  DD    -11266890\r
+  DD    -11568571\r
+  DD    -11863283\r
+  DD    -12150850\r
+  DD    -12431097\r
+  DD    -12703856\r
+  DD    -12968963\r
+  DD    -13226258\r
+  DD    -13475586\r
+  DD    -13716797\r
+  DD    -13949745\r
+  DD    -14174291\r
+  DD    -14390298\r
+  DD    -14597637\r
+  DD    -14796184\r
+  DD    -14985817\r
+  DD    -15166424\r
+  DD    -15337895\r
+  DD    -15500126\r
+  DD    -15653022\r
+  DD    -15796488\r
+  DD    -15930439\r
+  DD    -16054795\r
+  DD    -16169479\r
+  DD    -16274424\r
+  DD    -16369565\r
+  DD    -16454846\r
+  DD    -16530216\r
+  DD    -16595628\r
+  DD    -16651044\r
+  DD    -16696429\r
+  DD    -16731757\r
+  DD    -16757007\r
+  DD    -16772163\r
+  DD    -16777216\r
+  DD    -16772163\r
+  DD    -16757007\r
+  DD    -16731757\r
+  DD    -16696429\r
+  DD    -16651044\r
+  DD    -16595628\r
+  DD    -16530216\r
+  DD    -16454846\r
+  DD    -16369565\r
+  DD    -16274424\r
+  DD    -16169479\r
+  DD    -16054795\r
+  DD    -15930439\r
+  DD    -15796488\r
+  DD    -15653022\r
+  DD    -15500126\r
+  DD    -15337895\r
+  DD    -15166424\r
+  DD    -14985817\r
+  DD    -14796184\r
+  DD    -14597637\r
+  DD    -14390298\r
+  DD    -14174291\r
+  DD    -13949745\r
+  DD    -13716797\r
+  DD    -13475586\r
+  DD    -13226258\r
+  DD    -12968963\r
+  DD    -12703856\r
+  DD    -12431097\r
+  DD    -12150850\r
+  DD    -11863283\r
+  DD    -11568571\r
+  DD    -11266890\r
+  DD    -10958422\r
+  DD    -10643353\r
+  DD    -10321873\r
+  DD    -9994176\r
+  DD    -9660458\r
+  DD    -9320922\r
+  DD    -8975771\r
+  DD    -8625213\r
+  DD    -8269459\r
+  DD    -7908725\r
+  DD    -7543226\r
+  DD    -7173184\r
+  DD    -6798821\r
+  DD    -6420363\r
+  DD    -6038037\r
+  DD    -5652074\r
+  DD    -5262706\r
+  DD    -4870169\r
+  DD    -4474698\r
+  DD    -4076531\r
+  DD    -3675909\r
+  DD    -3273072\r
+  DD    -2868265\r
+  DD    -2461729\r
+  DD    -2053710\r
+  DD    -1644455\r
+  DD    -1234209\r
+  DD    -823219\r
+  DD    -411733\r
+tblCos  LABEL DWORD\r
+  DD    16777216\r
+  DD    16772163\r
+  DD    16757007\r
+  DD    16731757\r
+  DD    16696429\r
+  DD    16651044\r
+  DD    16595628\r
+  DD    16530216\r
+  DD    16454846\r
+  DD    16369565\r
+  DD    16274424\r
+  DD    16169479\r
+  DD    16054795\r
+  DD    15930439\r
+  DD    15796488\r
+  DD    15653022\r
+  DD    15500126\r
+  DD    15337895\r
+  DD    15166424\r
+  DD    14985817\r
+  DD    14796184\r
+  DD    14597637\r
+  DD    14390298\r
+  DD    14174291\r
+  DD    13949745\r
+  DD    13716797\r
+  DD    13475586\r
+  DD    13226258\r
+  DD    12968963\r
+  DD    12703856\r
+  DD    12431097\r
+  DD    12150850\r
+  DD    11863283\r
+  DD    11568571\r
+  DD    11266890\r
+  DD    10958422\r
+  DD    10643353\r
+  DD    10321873\r
+  DD    9994176\r
+  DD    9660458\r
+  DD    9320922\r
+  DD    8975771\r
+  DD    8625213\r
+  DD    8269459\r
+  DD    7908725\r
+  DD    7543226\r
+  DD    7173184\r
+  DD    6798821\r
+  DD    6420363\r
+  DD    6038037\r
+  DD    5652074\r
+  DD    5262706\r
+  DD    4870169\r
+  DD    4474698\r
+  DD    4076531\r
+  DD    3675909\r
+  DD    3273072\r
+  DD    2868265\r
+  DD    2461729\r
+  DD    2053710\r
+  DD    1644455\r
+  DD    1234209\r
+  DD    823219\r
+  DD    411733\r
+  DD    0\r
+  DD    -411733\r
+  DD    -823219\r
+  DD    -1234209\r
+  DD    -1644455\r
+  DD    -2053710\r
+  DD    -2461729\r
+  DD    -2868265\r
+  DD    -3273072\r
+  DD    -3675909\r
+  DD    -4076531\r
+  DD    -4474698\r
+  DD    -4870169\r
+  DD    -5262706\r
+  DD    -5652074\r
+  DD    -6038037\r
+  DD    -6420363\r
+  DD    -6798821\r
+  DD    -7173184\r
+  DD    -7543226\r
+  DD    -7908725\r
+  DD    -8269459\r
+  DD    -8625213\r
+  DD    -8975771\r
+  DD    -9320922\r
+  DD    -9660458\r
+  DD    -9994176\r
+  DD    -10321873\r
+  DD    -10643353\r
+  DD    -10958422\r
+  DD    -11266890\r
+  DD    -11568571\r
+  DD    -11863283\r
+  DD    -12150850\r
+  DD    -12431097\r
+  DD    -12703856\r
+  DD    -12968963\r
+  DD    -13226258\r
+  DD    -13475586\r
+  DD    -13716797\r
+  DD    -13949745\r
+  DD    -14174291\r
+  DD    -14390298\r
+  DD    -14597637\r
+  DD    -14796184\r
+  DD    -14985817\r
+  DD    -15166424\r
+  DD    -15337895\r
+  DD    -15500126\r
+  DD    -15653022\r
+  DD    -15796488\r
+  DD    -15930439\r
+  DD    -16054795\r
+  DD    -16169479\r
+  DD    -16274424\r
+  DD    -16369565\r
+  DD    -16454846\r
+  DD    -16530216\r
+  DD    -16595628\r
+  DD    -16651044\r
+  DD    -16696429\r
+  DD    -16731757\r
+  DD    -16757007\r
+  DD    -16772163\r
+  DD    -16777216\r
+  DD    -16772163\r
+  DD    -16757007\r
+  DD    -16731757\r
+  DD    -16696429\r
+  DD    -16651044\r
+  DD    -16595628\r
+  DD    -16530216\r
+  DD    -16454846\r
+  DD    -16369565\r
+  DD    -16274424\r
+  DD    -16169479\r
+  DD    -16054795\r
+  DD    -15930439\r
+  DD    -15796488\r
+  DD    -15653022\r
+  DD    -15500126\r
+  DD    -15337895\r
+  DD    -15166424\r
+  DD    -14985817\r
+  DD    -14796184\r
+  DD    -14597637\r
+  DD    -14390298\r
+  DD    -14174291\r
+  DD    -13949745\r
+  DD    -13716797\r
+  DD    -13475586\r
+  DD    -13226258\r
+  DD    -12968963\r
+  DD    -12703856\r
+  DD    -12431097\r
+  DD    -12150850\r
+  DD    -11863283\r
+  DD    -11568571\r
+  DD    -11266890\r
+  DD    -10958422\r
+  DD    -10643353\r
+  DD    -10321873\r
+  DD    -9994176\r
+  DD    -9660458\r
+  DD    -9320922\r
+  DD    -8975771\r
+  DD    -8625213\r
+  DD    -8269459\r
+  DD    -7908725\r
+  DD    -7543226\r
+  DD    -7173184\r
+  DD    -6798821\r
+  DD    -6420363\r
+  DD    -6038037\r
+  DD    -5652074\r
+  DD    -5262706\r
+  DD    -4870169\r
+  DD    -4474698\r
+  DD    -4076531\r
+  DD    -3675909\r
+  DD    -3273072\r
+  DD    -2868265\r
+  DD    -2461729\r
+  DD    -2053710\r
+  DD    -1644455\r
+  DD    -1234209\r
+  DD    -823219\r
+  DD    -411733\r
+  DD    0\r
+  DD    411733\r
+  DD    823219\r
+  DD    1234209\r
+  DD    1644455\r
+  DD    2053710\r
+  DD    2461729\r
+  DD    2868265\r
+  DD    3273072\r
+  DD    3675909\r
+  DD    4076531\r
+  DD    4474698\r
+  DD    4870169\r
+  DD    5262706\r
+  DD    5652074\r
+  DD    6038037\r
+  DD    6420363\r
+  DD    6798821\r
+  DD    7173184\r
+  DD    7543226\r
+  DD    7908725\r
+  DD    8269459\r
+  DD    8625213\r
+  DD    8975771\r
+  DD    9320922\r
+  DD    9660458\r
+  DD    9994176\r
+  DD    10321873\r
+  DD    10643353\r
+  DD    10958422\r
+  DD    11266890\r
+  DD    11568571\r
+  DD    11863283\r
+  DD    12150850\r
+  DD    12431097\r
+  DD    12703856\r
+  DD    12968963\r
+  DD    13226258\r
+  DD    13475586\r
+  DD    13716797\r
+  DD    13949745\r
+  DD    14174291\r
+  DD    14390298\r
+  DD    14597637\r
+  DD    14796184\r
+  DD    14985817\r
+  DD    15166424\r
+  DD    15337895\r
+  DD    15500126\r
+  DD    15653022\r
+  DD    15796488\r
+  DD    15930439\r
+  DD    16054795\r
+  DD    16169479\r
+  DD    16274424\r
+  DD    16369565\r
+  DD    16454846\r
+  DD    16530216\r
+  DD    16595628\r
+  DD    16651044\r
+  DD    16696429\r
+  DD    16731757\r
+  DD    16757007\r
+  DD    16772163\r
diff --git a/16/x/modex/THREED.ASM b/16/x/modex/THREED.ASM
new file mode 100755 (executable)
index 0000000..5ecd3ba
--- /dev/null
@@ -0,0 +1,872 @@
+COMMENT /\r
+        Fixed-point math functions and 3D transforms\r
+        Copyright (c) 1993,94 by Alessandro Scotti\r
+/\r
+WARN    PRO\r
+P386\r
+JUMPS\r
+LOCALS\r
+\r
+INCLUDE MATH.INC\r
+\r
+PUBLIC  tdFixedMul\r
+PUBLIC  tdGetNormal\r
+PUBLIC  tdRotate\r
+PUBLIC  tdGetSurfaceLight\r
+PUBLIC  tdSetLight\r
+PUBLIC  tdSetRotation\r
+PUBLIC  tdSetTranslation\r
+PUBLIC  tdTransform\r
+PUBLIC  tdTransformToImage\r
+PUBLIC  tdTransformLight\r
+PUBLIC  tdBackPlaneCull\r
+PUBLIC  tdSetPerspective\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Data segment\r
+;\r
+MATH_DATA       SEGMENT USE16 PARA PUBLIC 'DATA'\r
+                ASSUME ds:MATH_DATA\r
+\r
+INCLUDE         SINCOS.INC              ; Fixed 8:24 sin/cos table\r
+\r
+XRotation       TPOINT  <>              ; 3x3 rotation matrix\r
+YRotation       TPOINT  <>\r
+ZRotation       TPOINT  <>\r
+\r
+Translation     TPOINT  <>              ; Translation vector\r
+\r
+Light           TPOINT  <>              ; Light vector\r
+AmbientLight    DW      00              ; Ambient light\r
+\r
+XScale                  DD      10000h  ; Scaling factor for X coordinate\r
+YScale                  DD      10000h  ; Scaling factor for Y coordinate\r
+PerspectiveDistance     DD      20000000h\r
+\r
+MATH_DATA       ENDS\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Code segment\r
+;\r
+MATH_TEXT       SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MATH_TEXT, es:NOTHING, fs:NOTHING\r
+\r
+tdSetPerspective        PROC PASCAL FAR\r
+        ARG     Perspective:DWORD,      \\r
+                ScaleX:DWORD,           \\r
+                ScaleY:DWORD\r
+        USES    ds\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        mov     eax, [Perspective]\r
+        mov     [PerspectiveDistance], eax\r
+        mov     eax, [ScaleX]\r
+        mov     [XScale], eax\r
+        mov     eax, [ScaleY]\r
+        mov     [YScale], eax\r
+\r
+        ret\r
+tdSetPerspective        ENDP\r
+\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the rotation matrix.\r
+;\r
+; Input:\r
+;       RX      = X-axis rotation angle\r
+;       RY      = X-axis rotation angle\r
+;       RZ      = X-axis rotation angle\r
+; Output:\r
+;       none\r
+;\r
+tdSetRotation   PROC PASCAL FAR\r
+        ARG     RX:WORD,        \\r
+                RY:WORD,        \\r
+                RZ:WORD\r
+        USES    ds, si, di\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        mov     bx, [RZ]\r
+        mov     si, [RY]\r
+        mov     di, [RX]\r
+        shl     bx, 2\r
+        shl     si, 2\r
+        shl     di, 2\r
+\r
+        push    ebp                     ; We use EBP as a scratch register\r
+\r
+; Set X rotation\r
+        mov     eax, tblCos[bx]\r
+        imul    tblCos[si]\r
+        mov     [XRotation.X], edx\r
+\r
+        mov     eax, tblSin[bx]\r
+        imul    tblCos[si]\r
+        mov     [XRotation.Y], edx\r
+\r
+        mov     eax, tblSin[si]\r
+        sar     eax, 8                  ; Convert fixed 8:24 to fixed 16:16\r
+        mov     [XRotation.Z], eax\r
+\r
+; Set Y rotation\r
+        mov     eax, tblCos[bx]\r
+        imul    tblSin[si]              ; EDX:EAX = fixed 16:48\r
+        shrd    eax, edx, 24            ; EAX = fixed 8:24\r
+        imul    tblSin[di]              ; EDX:EAX = fixed 16:48\r
+        mov     ebp, eax\r
+        mov     ecx, edx\r
+        mov     eax, tblSin[bx]\r
+        imul    tblCos[di]\r
+        add     eax, ebp\r
+        adc     edx, ecx                ; EDX:EAX = fixed 16:48\r
+        neg     edx\r
+        mov     [YRotation.X], edx\r
+\r
+        mov     eax, tblSin[bx]\r
+        imul    tblSin[si]\r
+        shrd    eax, edx, 24\r
+        imul    tblSin[di]\r
+        mov     ebp, eax\r
+        mov     ecx, edx\r
+        mov     eax, tblCos[bx]\r
+        imul    tblCos[di]\r
+        sub     eax, ebp\r
+        sbb     edx, ecx\r
+        mov     [YRotation.Y], edx\r
+\r
+        mov     eax, tblCos[si]\r
+        imul    tblSin[di]\r
+        mov     [YRotation.Z], edx\r
+\r
+; Set Z rotation\r
+        mov     eax, tblCos[bx]\r
+        imul    tblSin[si]\r
+        shrd    eax, edx, 24\r
+        imul    tblCos[di]\r
+        mov     ebp, eax\r
+        mov     ecx, edx\r
+        mov     eax, tblSin[bx]\r
+        imul    tblSin[di]\r
+        sub     eax, ebp\r
+        sbb     edx, ecx\r
+        mov     [ZRotation.X], edx\r
+\r
+        mov     eax, tblSin[bx]\r
+        imul    tblSin[si]\r
+        shrd    eax, edx, 24\r
+        imul    tblCos[di]\r
+        mov     ebp, eax\r
+        mov     ecx, edx\r
+        mov     eax, tblCos[bx]\r
+        imul    tblSin[di]\r
+        add     eax, ebp\r
+        add     edx, ecx\r
+        neg     edx\r
+        mov     [ZRotation.Y], edx\r
+\r
+        mov     eax, tblCos[si]\r
+        imul    tblCos[di]\r
+        mov     [ZRotation.Z], edx\r
+\r
+        pop     ebp                     ; Restore EBP\r
+\r
+        ret\r
+tdSetRotation   ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the translation vector.\r
+;\r
+; Input:\r
+;       TV      = pointer to translation vector\r
+; Output:\r
+;       none\r
+;\r
+tdSetTranslation        PROC PASCAL FAR\r
+        ARG     TV:DWORD\r
+        USES    ds, es, di\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        les     di, [TV]\r
+        mov     eax, es:[di].X\r
+        mov     [Translation.X], eax\r
+        mov     eax, es:[di].Y\r
+        mov     [Translation.Y], eax\r
+        mov     eax, es:[di].Z\r
+        mov     [Translation.Z], eax\r
+\r
+        ret\r
+tdSetTranslation        ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Transforms an array of TPOINT.\r
+;\r
+; Input:\r
+;       Source  = pointer to source array of TPOINT\r
+;       Dest    = pointer to destination array of TPOINT\r
+;       Count   = number of entries to transform\r
+; Output:\r
+;       none\r
+;\r
+tdTransform     PROC PASCAL FAR\r
+        ARG     Source:DWORD,   \\r
+                Dest:DWORD,     \\r
+                Count:WORD\r
+        LOCAL   Adjust:DWORD\r
+        USES    ds, si, es, di, fs\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        lfs     si, [Source]\r
+        les     di, [Dest]\r
+\r
+        ALIGN   DWORD\r
+@@Loop:\r
+; Transform Z coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [ZRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [ZRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [ZRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        mov     ebx, eax\r
+        shrd    eax, edx, 16\r
+        add     eax, [Translation.Z]    ; EAX = new Z coord (fixed 16:16)\r
+        mov     es:[di].Z, eax\r
+; Get perspective factor\r
+        mov     ebx, [PerspectiveDistance]\r
+        sub     eax, ebx\r
+        neg     eax                     ; EAX = PD - Z\r
+        xor     edx, edx\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    ebx                     ; EAX = fixed 16:16 result\r
+        mov     [Adjust], eax\r
+\r
+; Transform X coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [XRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [XRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [XRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        add     eax, [Translation.X]\r
+        imul    [Adjust]\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].X, eax\r
+\r
+; Transform Y coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [YRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [YRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [YRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        add     eax, [Translation.Y]\r
+        imul    [Adjust]\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].Y, eax\r
+\r
+        add     si, SIZE TPOINT\r
+        add     di, SIZE TPOINT\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        ret\r
+tdTransform     ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Transforms an array of TPOINT into an array of TIMAGEPOINT.\r
+;\r
+; Input:\r
+;       Source  = pointer to source array of TPOINT\r
+;       Dest    = pointer to destination array of TIMAGEPOINT\r
+;       Count   = number of entries to transform\r
+;       DeltaX  = translation distance for the X coordinate\r
+;       DeltaY  = translation distance for the Y coordinate\r
+; Output:\r
+;       the maximum Z value\r
+;\r
+tdTransformToImage      PROC PASCAL FAR\r
+        ARG     Source:DWORD,   \\r
+                Dest:DWORD,     \\r
+                Count:WORD,     \\r
+                DeltaX:WORD,    \\r
+                DeltaY:WORD\r
+        LOCAL   Adjust:DWORD,   \\r
+                Max:DWORD\r
+        USES    ds, si, es, di, fs\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        lfs     si, [Source]\r
+        les     di, [Dest]\r
+        mov     [Max], 80000000h\r
+\r
+@@Loop:\r
+; Check max Z\r
+        mov     eax, fs:[si].Z\r
+        cmp     eax, [Max]\r
+        jle     @@1\r
+        mov     [Max], eax\r
+@@1:\r
+\r
+; Transform X coordinate\r
+        mov     ax, WORD PTR fs:[si].X[2]\r
+        add     ax, [DeltaX]\r
+        mov     es:[di].IX, ax\r
+\r
+; Transform Y coordinate\r
+        mov     ax, WORD PTR fs:[si].Y[2]\r
+        add     ax, [DeltaY]\r
+        mov     es:[di].IY, ax\r
+\r
+        add     si, SIZE TPOINT\r
+        add     di, SIZE TIMAGEPOINT\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        mov     eax, [Max]\r
+        shld    edx, eax, 16\r
+        ret\r
+tdTransformToImage      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the light source.\r
+;\r
+; Input:\r
+;       Light   = pointer to light vector\r
+; Output:\r
+;       none\r
+;\r
+tdSetLight      PROC PASCAL FAR\r
+        ARG     L:DWORD\r
+        USES    ds, es, di\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        les     di, [L]\r
+        mov     eax, es:[di].X\r
+        mov     [Light.X], eax\r
+        mov     eax, es:[di].Y\r
+        mov     [Light.Y], eax\r
+        mov     eax, es:[di].Z\r
+        mov     [Light.Z], eax\r
+\r
+        ret\r
+tdSetLight      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Computes light intensity for an array of surfaces.\r
+;\r
+; Input:\r
+;       Normals = pointer to an array of surface normals\r
+;       Lights  = pointer to an array of integer to be filled with\r
+;                 light intensity\r
+;       Count   = number of elements to transform\r
+; Output:\r
+;       none\r
+;\r
+tdTransformLight        PROC PASCAL FAR\r
+        ARG     Normals:DWORD,  \\r
+                Lights:DWORD,   \\r
+                Count:WORD\r
+        USES    ds, si, es, di, fs\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     fs, ax\r
+        ASSUME  fs:MATH_DATA\r
+\r
+        lds     si, [Normals]\r
+        les     di, [Lights]\r
+        ASSUME  ds:NOTHING\r
+\r
+; Intensity is given by the dot product between the Light vector and\r
+; the surface normal\r
+@@Loop:\r
+        mov     eax, ds:[si].Z\r
+        imul    [Light.Z]\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, ds:[si].Y\r
+        imul    [Light.Y]\r
+        add     ebx, eax\r
+        adc     ecx, edx\r
+        mov     eax, ds:[si].X\r
+        imul    [Light.X]\r
+        add     eax, ebx\r
+        adc     edx, ecx                ; EDX:EAX = fixed 32:32 intensity\r
+        add     dx, [AmbientLight]\r
+        test    dx, dx\r
+        jg      @@1\r
+        xor     dx, dx                  ; Return 0 for no light\r
+@@1:\r
+        mov     es:[di], dx\r
+        inc     di\r
+        inc     di\r
+        add     si, SIZE TPOINT\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        ASSUME  fs:NOTHING\r
+        ret\r
+tdTransformLight        ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the light value given the normal to a surface.\r
+;\r
+; Input:\r
+;       Normal  = pointer to TPOINT surface normal vector\r
+; Output:\r
+;       AX      = light intensity (>=0)\r
+; Notes:\r
+;       the normal is rotated according to the current setting.\r
+;\r
+tdGetSurfaceLight       PROC PASCAL FAR\r
+        ARG     Normal:DWORD\r
+        USES    ds, esi, es, di\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        les     di, [Normal]\r
+\r
+; Transform Z coordinate\r
+        mov     eax, es:[di].X\r
+        imul    [ZRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, es:[di].Y\r
+        imul    [ZRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, es:[di].Z\r
+        imul    [ZRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        imul    [Light.Z]\r
+        shrd    eax, edx, 16\r
+        mov     esi, eax\r
+\r
+; Transform X coordinate\r
+        mov     eax, es:[di].X\r
+        imul    [XRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, es:[di].Y\r
+        imul    [XRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, es:[di].Z\r
+        imul    [XRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        imul    [Light.X]\r
+        shrd    eax, edx, 16\r
+        add     esi, eax\r
+\r
+; Transform Y coordinate\r
+        mov     eax, es:[di].X\r
+        imul    [YRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, es:[di].Y\r
+        imul    [YRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, es:[di].Z\r
+        imul    [YRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        imul    [Light.X]\r
+        shrd    eax, edx, 16\r
+        add     eax, esi\r
+        shr     eax, 16\r
+\r
+; Add ambient light\r
+        add     ax, [AmbientLight]\r
+        test    ax, ax\r
+        jge     @@Exit\r
+        xor     ax, ax\r
+\r
+@@Exit:\r
+        ret\r
+tdGetSurfaceLight       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Rotates an array of TPOINT.\r
+;\r
+; Input:\r
+;       Source  = pointer to source array of TPOINT\r
+;       Dest    = pointer to destination array of TPOINT\r
+;       Count   = number of entries to transform\r
+; Output:\r
+;       none\r
+;\r
+tdRotate        PROC PASCAL FAR\r
+        ARG     Source:DWORD,   \\r
+                Dest:DWORD,     \\r
+                Count:WORD\r
+        USES    ds, si, es, di, fs\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        lfs     si, [Source]\r
+        les     di, [Dest]\r
+\r
+@@Loop:\r
+; Transform Z coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [ZRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [ZRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [ZRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].Z, eax\r
+\r
+; Transform X coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [XRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [XRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [XRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].X, eax\r
+\r
+; Transform Y coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [YRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [YRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [YRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].Y, eax\r
+\r
+        add     si, SIZE TPOINT\r
+        add     di, SIZE TPOINT\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        ret\r
+tdRotate        ENDP\r
+\r
+tdFixedMul      PROC PASCAL FAR\r
+        ARG     F1:DWORD,       \\r
+                F2:DWORD\r
+\r
+        mov     eax, [F1]\r
+        imul    [F2]\r
+        shr     eax, 16\r
+\r
+        ret\r
+tdFixedMul      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns in EAX the square root of EDX:EAX.\r
+;\r
+subSqrt PROC NEAR\r
+        push    esi\r
+        push    edi\r
+\r
+        add     eax, eax\r
+        adc     edx, 0\r
+        mov     eax, edx                ; Just discard the low bits\r
+\r
+        mov     esi, eax\r
+        xor     edi, edi\r
+        shld    edi, esi, 16\r
+        shl     esi, 16\r
+@@Loop:\r
+        mov     ebx, eax\r
+        mul     eax\r
+        add     eax, esi\r
+        adc     edx, edi\r
+        shrd    eax, edx, 1\r
+        shr     edx, 1\r
+        div     ebx\r
+        cmp     eax, ebx\r
+        jne     @@Loop\r
+\r
+; Adjust EAX\r
+        shl     eax, 8\r
+\r
+        pop     edi\r
+        pop     esi\r
+        ret\r
+subSqrt ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Finds the unitary normal to a given surface.\r
+;\r
+; Input:\r
+;       Dest            = pointer to TPOINT (vector) result\r
+;       P1, P2, P3      = pointer to TPOINT points on surface\r
+; Output:\r
+;       none\r
+; Notes:\r
+;       the normal is given by the cross-product between (P3-P1) and\r
+;       (P2-P1), so its orientation depends on the parameters order.\r
+;\r
+tdGetNormal     PROC PASCAL FAR\r
+        ARG     Dest:DWORD,     \\r
+                P1:DWORD,       \\r
+                P2:DWORD,       \\r
+                P3:DWORD\r
+        LOCAL   V1:TPOINT,      \\r
+                V2:TPOINT,      \\r
+                N:TPOINT\r
+        USES    ds, si, es, di\r
+\r
+; Get vector V1\r
+        lds     si, [P1]\r
+        les     di, [P3]\r
+        mov     eax, es:[di].X\r
+        sub     eax, ds:[si].X\r
+        mov     [V1.X], eax\r
+        mov     eax, es:[di].Y\r
+        sub     eax, ds:[si].Y\r
+        mov     [V1.Y], eax\r
+        mov     eax, es:[di].Z\r
+        sub     eax, ds:[si].Z\r
+        mov     [V1.Z], eax\r
+\r
+; Get vector V2\r
+        les     di, [P2]\r
+        mov     eax, es:[di].X\r
+        sub     eax, ds:[si].X\r
+        mov     [V2.X], eax\r
+        mov     eax, es:[di].Y\r
+        sub     eax, ds:[si].Y\r
+        mov     [V2.Y], eax\r
+        mov     eax, es:[di].Z\r
+        sub     eax, ds:[si].Z\r
+        mov     [V2.Z], eax\r
+\r
+; Get normal vector (V1 x V2)\r
+        mov     eax, [V1.Z]\r
+        imul    [V2.Y]\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, [V1.Y]\r
+        imul    [V2.Z]\r
+        sub     eax, ebx\r
+        sbb     edx, ecx\r
+        shrd    eax, edx, 16\r
+        mov     [N.X], eax\r
+\r
+        mov     eax, [V1.X]\r
+        imul    [V2.Z]\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, [V1.Z]\r
+        imul    [V2.X]\r
+        sub     eax, ebx\r
+        sbb     edx, ecx\r
+        shrd    eax, edx, 16\r
+        mov     [N.Y], eax\r
+\r
+        mov     eax, [V1.Y]\r
+        imul    [V2.X]\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, [V1.X]\r
+        imul    [V2.Y]\r
+        sub     eax, ebx\r
+        sbb     edx, ecx\r
+        shrd    eax, edx, 16\r
+        mov     [N.Z], eax\r
+\r
+; Get normal length\r
+        mov     eax, [N.X]\r
+        imul    eax\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, [N.Y]\r
+        imul    eax\r
+        add     ebx, eax\r
+        adc     ecx, edx\r
+        mov     eax, [N.Z]\r
+        imul    eax\r
+        add     eax, ebx\r
+        adc     edx, ecx                ; EDX:EAX = N.X*N.X + N.Y*N.Y + N.Z*N.Z\r
+        call    subSqrt                 ; EAX = normal length\r
+        mov     ebx, eax\r
+\r
+; Adjust vector and save it\r
+        les     di, [Dest]\r
+        mov     eax, [N.X]\r
+        cdq\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    ebx\r
+        mov     es:[di].X, eax\r
+        mov     eax, [N.Y]\r
+        cdq\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    ebx\r
+        mov     es:[di].Y, eax\r
+        mov     eax, [N.Z]\r
+        cdq\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    ebx\r
+        mov     es:[di].Z, eax\r
+\r
+        ret\r
+tdGetNormal     ENDP\r
+\r
+TPOLY   STRUC\r
+        Vtx     DW      4 DUP(?)\r
+TPOLY   ENDS\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Performs surface removal on an array of polygons.\r
+;\r
+; Input:\r
+;       Poly    = pointer to an array of TPOLY\r
+;       Vertex  = pointer to an array of TPOINT\r
+;       Dest    = pointer to an array of integer\r
+;       Count   = number of polygons to check\r
+;       Step    = size of TPOLY structure\r
+; Output:\r
+;       if the n-th polygon is invisible the n-th entry of the\r
+;       Dest array is set to -1, other entries are not modified\r
+;       (so it's possible to use the Light array for Dest, because\r
+;       the light intensity is always >= 0)\r
+;\r
+tdBackPlaneCull PROC PASCAL FAR\r
+        ARG     Step:WORD,      \\r
+                Poly:DWORD,     \\r
+                Vertex:DWORD,   \\r
+                Dest:DWORD,     \\r
+                Count:WORD\r
+        USES    ds, si, es, di, fs\r
+        ASSUME  ds:NOTHING\r
+\r
+        mov     ds, WORD PTR Vertex[2]\r
+        les     di, [Poly]\r
+        mov     fs, WORD PTR Dest[2]\r
+\r
+@@Loop:\r
+        mov     ax, es:[di].Vtx[2]      ; Index of 2nd vertex\r
+        shl     ax, 2\r
+        mov     bx, ax\r
+        shl     ax, 1\r
+        add     bx, ax                  ; BX = index*SIZE TPOINT\r
+        add     bx, WORD PTR [Vertex]   ; BX = offset of 2nd vertex\r
+        mov     ax, es:[di].Vtx[4]      ; Index of 3rd vertex\r
+        shl     ax, 2\r
+        mov     si, ax\r
+        shl     ax, 1\r
+        add     si, ax\r
+        add     si, WORD PTR [Vertex]   ; SI = offset of 3rd vertex\r
+        mov     ecx, ds:[si].X\r
+        sub     ecx, ds:[bx].X          ; ECX = V3.X-V2.X\r
+        mov     edx, ds:[si].Y\r
+        sub     edx, ds:[bx].Y          ; EDX = V3.Y-V2.Y\r
+        mov     ax, es:[di].Vtx[0]      ; Index of 1st vertex\r
+        shl     ax, 2\r
+        mov     si, ax\r
+        shl     ax, 1\r
+        add     si, ax\r
+        add     si, WORD PTR [Vertex]   ; SI = offset of 1st vertex\r
+        mov     eax, ds:[si].X\r
+        sub     eax, ds:[bx].X          ; EAX = V1.X-V2.X\r
+        mov     esi, ds:[si].Y\r
+        sub     esi, ds:[bx].Y          ; ESI = V1.Y-V2.Y\r
+        imul    edx\r
+        mov     ebx, eax\r
+        xchg    ecx, edx                ; ECX:EBX = (V1.X-V2.X)*(V3.Y-V2.Y)\r
+        mov     eax, esi\r
+        imul    edx                     ; EDX:EAX = (V1.Y-V2.Y)*(V3.X-V2.X)\r
+        sub     eax, ebx\r
+        sbb     edx, ecx\r
+        jl      @@Next                  ; Polygon is visible\r
+        mov     bx, WORD PTR [Dest]     ; FS:BX -> current Dest entry\r
+        mov     WORD PTR fs:[bx], -1    ; Remove polygon\r
+@@Next:\r
+        add     WORD PTR [Dest], 2      ; Next entry for dest\r
+        add     di, [Step]              ; Next polygon\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        ret\r
+tdBackPlaneCull ENDP\r
+\r
+MATH_TEXT       ENDS\r
+END\r
diff --git a/16/x/modex/THREED.H b/16/x/modex/THREED.H
new file mode 100755 (executable)
index 0000000..b993ef8
--- /dev/null
@@ -0,0 +1,32 @@
+typedef struct {\r
+    long    x, y, z;\r
+} TVECTOR;\r
+\r
+#define PVECTOR TVECTOR far *\r
+\r
+#define TPOINT  TVECTOR\r
+#define PPOINT  PVECTOR\r
+\r
+#define VPTR    void far *\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+long far pascal tdFixedMul( long, long );\r
+int  far pascal tdGetSurfaceLight( PPOINT );\r
+long far pascal tdTransformToImage( VPTR, VPTR, short, short, short );\r
+\r
+void far pascal tdBackPlaneCull( VPTR, VPTR, VPTR, short, short );\r
+void far pascal tdGetNormal( VPTR, PPOINT, PPOINT, PPOINT );\r
+void far pascal tdRotate( VPTR, VPTR, short );\r
+void far pascal tdSetLight( PVECTOR );\r
+void far pascal tdSetRotation( short, short, short );\r
+void far pascal tdSetTranslation( PVECTOR );\r
+void far pascal tdSetPerspective( long, long, long );\r
+void far pascal tdTransform( VPTR, VPTR, short );\r
+void far pascal tdTransformLight( VPTR, VPTR, short );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
diff --git a/16/x/modex/THREED.PAS b/16/x/modex/THREED.PAS
new file mode 100755 (executable)
index 0000000..8b712c9
--- /dev/null
@@ -0,0 +1,40 @@
+unit ThreeD;\r
+interface\r
+\r
+type\r
+  TVector       = record\r
+    X, Y, Z     : longint;\r
+  end;\r
+  TPoint        = TVector;\r
+\r
+function tdFixedMul( F1, F2: longint ): longint;\r
+function tdGetSurfaceLight( var Normal: TPoint ): integer;\r
+function tdTransformToImage( var Source, Dest; Count, DeltaX, DeltaY: integer ): longint;\r
+\r
+procedure tdBackPlaneCull( var Poly, Vertex, Dest; Count, Step: word );\r
+procedure tdGetNormal( var Dest, P1, P2, P3: TVector );\r
+procedure tdRotate( var Source, Dest; Count: word );\r
+procedure tdSetLight( var Light: TVector );\r
+procedure tdSetRotation( RX, RY, RZ: word );\r
+procedure tdSetTranslation( var TV: TVector );\r
+procedure tdSetPerspective( PD, XF, YF: longint );\r
+procedure tdTransform( var Source, Dest; Count: word );\r
+procedure tdTransformLight( var Source, Dest; Count: word );\r
+\r
+implementation\r
+\r
+function tdGetSurfaceLight;                             external;\r
+procedure tdSetRotation( RX, RY, RZ: word );            external;\r
+procedure tdGetNormal;                                  external;\r
+procedure tdSetTranslation( var TV: TVector );          external;\r
+procedure tdTransform( var Source, Dest; Count: word ); external;\r
+procedure tdRotate;                                     external;\r
+function  tdTransformToImage;                           external;\r
+procedure tdSetLight( var Light: TVector );             external;\r
+procedure tdSetPerspective;                             external;\r
+procedure tdTransformLight;                             external;\r
+function tdFixedMul( F1, F2: longint ): longint;        external;\r
+procedure tdBackPlaneCull;                              external;\r
+{$L THREED}\r
+\r
+end.\r
diff --git a/16/x/mxbb.asm b/16/x/mxbb.asm
new file mode 100755 (executable)
index 0000000..ac6668c
--- /dev/null
@@ -0,0 +1,278 @@
+;-----------------------------------------------------------\r
+;\r
+; MXBB.ASM - Bit block transfer\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxBitBlt\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   subHorizontalLineInfo   : NEAR\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Moves a block of video memory.\r
+;\r
+; Input:\r
+;       SX, SY  = source coordinates\r
+;       Width   = source width\r
+;       Height  = source height\r
+;       DX, DY  = destination coordinates\r
+; Output:\r
+;       none\r
+;\r
+; Note: overlapping regions are not allowed.\r
+;\r
+mxBitBlt        PROC    FAR\r
+        ARG     DestY:WORD,             \\r
+                DestX:WORD,             \\r
+                Height:WORD,            \\r
+                Width:WORD,             \\r
+                SY:WORD,                \\r
+                SX:WORD                 = ARG_SIZE\r
+        LOCAL   PlaneWidth:WORD:4,      \\r
+                SourceOffset:WORD,      \\r
+                DestOffset:WORD,        \\r
+                Count:BYTE,             \\r
+                ReadPlane:BYTE,         \\r
+                WritePlane:BYTE,        \\r
+                LeftMask:BYTE,          \\r
+                RightMask:BYTE          = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+\r
+; Exit now if null width\r
+        cmp     [Width], 0\r
+        je      @@Exit\r
+\r
+; Calls the proper procedure to handle transfer\r
+        mov     ax, [SX]\r
+        and     al, 03h                 ; AL = source plane\r
+        mov     dx, [DestX]\r
+        and     dl, 03h                 ; DL = destination plane\r
+        mov     bx, OFFSET subPlaneBlt\r
+        cmp     al, dl                  ; Same source and destination plane?\r
+        jne     @@BitBlt                ; No, use slow procedure\r
+        mov     bx, OFFSET subMoveBlt\r
+@@BitBlt:\r
+        call    bx\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+\r
+;-----------------------------------------------------------\r
+; Uses write mode 1 for maximum speed. Only works if source\r
+; and destination are plane-aligned.\r
+;\r
+subMoveBlt      PROC    NEAR\r
+; Get horizontal line info and address of destination\r
+        mov     bx, [DestX]\r
+        mov     ax, [DestY]\r
+        mov     cx, [Width]\r
+        call    subHorizontalLineInfo\r
+        mov     [LeftMask], al\r
+        mov     [RightMask], ah\r
+        mov     [Width], cx\r
+\r
+; Setup segments\r
+        mov     ax, [mx_VideoSegment]\r
+        mov     ds, ax\r
+        mov     es, ax\r
+\r
+; Get address of source pixel\r
+        mov     ax, [SY]\r
+        mul     [mx_BytesPerLine]\r
+        mov     si, [SX]\r
+        .shr    si, 2\r
+        add     si, ax\r
+\r
+; Set write mode 1\r
+        mov     dx, GDC\r
+        mov     ax, 4105h\r
+        out     dx, ax\r
+        cld\r
+\r
+; Move left block\r
+@@L0:\r
+        mov     ah, [LeftMask]\r
+        or      ah, ah\r
+        jz      @@C0\r
+        mov     dx, TS\r
+        mov     al, 02h\r
+        out     dx, ax                  ; Set write plane mask\r
+        mov     ax, [mx_BytesPerLine]\r
+        dec     ax\r
+        mov     cx, [Height]\r
+        .push   si, di\r
+@@L1:\r
+        movsb\r
+        add     si, ax\r
+        add     di, ax\r
+        dec     cx\r
+        jnz     @@L1\r
+        .pop    si, di\r
+        inc     si\r
+        inc     di\r
+\r
+; Move center block\r
+@@C0:\r
+        mov     bx, [Width]\r
+        test    bx, bx\r
+        jz      @@R0\r
+        mov     dx, TS\r
+        mov     ax, 0F02h\r
+        out     dx, ax                  ; Enable all planes\r
+        mov     ax, [mx_BytesPerLine]\r
+        sub     ax, bx\r
+        mov     dx, [Height]\r
+        .push   si, di\r
+@@C1:\r
+        mov     cx, bx                  ; CX = image width\r
+        rep     movsb                   ; Cannot use "movsw" here!\r
+        add     si, ax                  ; Next scan line\r
+        add     di, ax                  ; Next scan line\r
+        dec     dx                      ; All lines processed?\r
+        jnz     @@C1                    ; No, continue\r
+        .pop    si, di\r
+        add     si, bx\r
+        add     di, bx\r
+\r
+; Move right block\r
+@@R0:\r
+        mov     ah, [RightMask]\r
+        or      ah, ah\r
+        jz      @@Done\r
+        mov     dx, TS\r
+        mov     al, 02h\r
+        out     dx, ax                  ; Set write plane mask\r
+        mov     ax, [mx_BytesPerLine]\r
+        dec     ax\r
+        mov     cx, [Height]\r
+@@R1:\r
+        movsb\r
+        add     si, ax\r
+        add     di, ax\r
+        dec     cx\r
+        jnz     @@R1\r
+\r
+@@Done:\r
+        mov     dx, GDC\r
+        mov     ax, 4005h\r
+        out     dx, ax                  ; Restore write mode 0\r
+\r
+@@Exit:\r
+        ret\r
+subMoveBlt      ENDP\r
+\r
+;-----------------------------------------------------------\r
+; Moves one plane at a time.\r
+;\r
+subPlaneBlt     PROC    NEAR\r
+; Compute extra bytes and width count for each plane\r
+        mov     cx, [Width]\r
+        mov     bx, cx\r
+        shr     bx, 1\r
+        shr     bx, 1                   ; Width for each plane\r
+        and     cl, 03h\r
+        mov     al, 00001000b\r
+        shr     al, cl\r
+        mov     si, 3 SHL 1\r
+@@PatchLoop:\r
+        mov     PlaneWidth[si], bx\r
+        shr     al, 1\r
+        adc     bx, 0\r
+        dec     si\r
+        dec     si\r
+        jge     @@PatchLoop\r
+\r
+; Get pixel addresses\r
+        mov     ax, [mx_VideoSegment]\r
+        mov     ds, ax\r
+        mov     es, ax\r
+        mov     ax, [SY]\r
+        mul     [mx_BytesPerLine]\r
+        mov     si, [SX]\r
+        shr     si, 1\r
+        shr     si, 1\r
+        add     si, ax                  ; DS:SI points to source\r
+        mov     [SourceOffset], si\r
+        mov     ax, [DestY]\r
+        mul     [mx_BytesPerLine]\r
+        mov     di, [DestX]\r
+        shr     di, 1\r
+        shr     di, 1\r
+        add     di, ax                  ; ES:DI points to destination\r
+        mov     [DestOffset], di\r
+\r
+; Adjust plane for output to VGA registers\r
+        mov     ax, [SX]\r
+        and     al, 03h\r
+        mov     [ReadPlane], al\r
+        mov     cx, [DestX]\r
+        and     cl, 03h\r
+        mov     al, 00010001b\r
+        shl     al, cl\r
+        mov     [WritePlane], al\r
+\r
+; Ready to move now\r
+        cld\r
+        mov     [Count], 4              ; Four planes\r
+        lea     bx, PlaneWidth          ; SS:[BX] = width in bytes for plane\r
+@@PlaneLoop:\r
+        cmp     WORD PTR ss:[bx], 0\r
+        je      @@Done\r
+        mov     ah, [WritePlane]\r
+        and     ah, 0Fh\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax                  ; Select write plane\r
+        mov     ah, [ReadPlane]\r
+        mov     al, 04h\r
+        mov     dx, GDC\r
+        out     dx, ax                  ; Select read plane\r
+        mov     dx, [Height]\r
+        mov     ax, [mx_BytesPerLine]\r
+        sub     ax, ss:[bx]             ; AX = extra bytes per line\r
+@@Loop:\r
+        mov     cx, ss:[bx]\r
+        shr     cx, 1\r
+        rep     movsw\r
+        rcl     cx, 1\r
+        rep     movsb\r
+        add     si, ax\r
+        add     di, ax\r
+        dec     dx\r
+        jnz     @@Loop                  ; Repeat for all lines\r
+        inc     bx\r
+        inc     bx                      ; Select width for next plane\r
+        inc     [ReadPlane]\r
+        and     [ReadPlane], 03h        ; Should be faster on 386 using\r
+        jnz     @@ReadPlaneOk           ; BTR and ADC...\r
+        inc     [SourceOffset]\r
+@@ReadPlaneOk:\r
+        rol     [WritePlane], 1\r
+        adc     [DestOffset], 0\r
+        mov     si, [SourceOffset]\r
+        mov     di, [DestOffset]\r
+        dec     [Count]\r
+        jnz     @@PlaneLoop             ; Repeat for all planes\r
+\r
+@@Done:\r
+        ret\r
+subPlaneBlt     ENDP\r
+\r
+mxBitBlt        ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxcc.asm b/16/x/mxcc.asm
new file mode 100755 (executable)
index 0000000..4f78adb
--- /dev/null
@@ -0,0 +1,644 @@
+;-----------------------------------------------------------\r
+;\r
+; MXCC.ASM - Fast clip line function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  xsubClipLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+        ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_VideoSegment : WORD\r
+\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+\r
+tblGroups       LABEL WORD\r
+        DW      10,     tbl00\r
+        DW      10,     tbl10\r
+        DW      9,      tbl20\r
+        DW      -1,     0\r
+        DW      10,     tbl40\r
+        DW      10,     tbl50\r
+        DW      9,      tbl60\r
+        DW      -1,     0\r
+        DW      6,      tbl80\r
+        DW      6,      tbl90\r
+        DW      5,      tblA0\r
+        DW      -1,     0\r
+        DW      -1,     0\r
+        DW      -1,     0\r
+        DW      -1,     0\r
+        DW      -1,     0\r
+tbl00   DW cc00, cc01, cc02, ccFF, cc04, cc05, cc06, ccFF, cc08, cc09, cc0A\r
+tbl10   DW cc10, ccFF, cc12, ccFF, cc14, ccFF, cc16, ccFF, cc18, ccFF, cc1A\r
+tbl20   DW cc20, cc21, ccFF, ccFF, cc24, cc25, ccFF, ccFF, cc28, cc29\r
+tbl40   DW cc40, cc41, cc42, ccFF, ccFF, ccFF, ccFF, ccFF, cc48, cc49, cc4A\r
+tbl50   DW cc50, ccFF, cc52, ccFF, ccFF, ccFF, ccFF, ccFF, cc58, ccFF, cc5A\r
+tbl60   DW cc60, cc61, ccFF, ccFF, ccFF, ccFF, ccFF, ccFF, cc68, cc69\r
+tbl80   DW cc80, cc81, cc82, ccFF, cc84, cc85, cc86\r
+tbl90   DW cc90, ccFF, cc92, ccFF, cc94, ccFF, cc96\r
+tblA0   DW ccA0, ccA1, ccFF, ccFF, ccA4, ccA5\r
+\r
+ccTT:   clc\r
+        ret\r
+ccFF:   stc\r
+        ret\r
+\r
+; Group 00 -------------------------------------------------\r
+;\r
+cc00:\r
+        clc\r
+        ret\r
+cc01:\r
+        jmp     ClipQLeft\r
+cc02:\r
+        jmp     ClipQRight\r
+cc04:\r
+        jmp     ClipQTop\r
+cc05:\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY1]\r
+        jge     ccTT\r
+        jmp     ClipQTop\r
+cc06:\r
+        call    ClipQRight\r
+        cmp     si, [mx_ClipY1]\r
+        jge     ccTT\r
+        jmp     ClipQTop\r
+cc08:\r
+        jmp     ClipQBottom\r
+cc09:\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY2]\r
+        jle     ccTT\r
+        jmp     ClipQBottom\r
+cc0A:\r
+        call    ClipQRight\r
+        cmp     si, [mx_ClipY2]\r
+        jle     ccTT\r
+        jmp     ClipQBottom\r
+\r
+; Group 10 -------------------------------------------------\r
+;\r
+cc10FF:\r
+        stc\r
+        ret\r
+cc10TT:\r
+        clc\r
+        ret\r
+cc10:\r
+        jmp     ClipPLeft\r
+cc12:\r
+        call    ClipPLeft\r
+        jmp     ClipQRight\r
+cc14:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      cc10FF\r
+        jmp     ClipQTop\r
+cc16:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      cc10FF\r
+        call    ClipQTop\r
+        cmp     cx, [mx_ClipX2]\r
+        jle     cc10TT\r
+        jmp     ClipQRight\r
+cc18:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      cc10FF\r
+        jmp     ClipQBottom\r
+cc1A:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      cc10FF\r
+        call    ClipQBottom\r
+        cmp     cx, [mx_ClipX2]\r
+        jle     cc10TT\r
+        jmp     ClipQRight\r
+\r
+; Group 20 -------------------------------------------------\r
+;\r
+cc20TT:\r
+        clc\r
+        ret\r
+cc20FF:\r
+        stc\r
+        ret\r
+cc20:\r
+        jmp     ClipPRight\r
+cc21:\r
+        call    ClipPRight\r
+        jmp     ClipQLeft\r
+cc24:\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      cc20FF\r
+        jmp     ClipQTop\r
+cc25:\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      cc20FF\r
+        call    ClipQTop\r
+        cmp     cx, [mx_ClipX1]\r
+        jge     cc20TT\r
+        jmp     ClipQLeft\r
+cc28:\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      cc20FF\r
+        jmp     ClipQBottom\r
+cc29:\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      cc20FF\r
+        call    ClipQBottom\r
+        cmp     cx, [mx_ClipX1]\r
+        jge     cc20TT\r
+        jmp     ClipQLeft\r
+\r
+; Group 40 -------------------------------------------------\r
+;\r
+cc40TT:\r
+        clc\r
+        ret\r
+cc40FF:\r
+        stc\r
+        ret\r
+cc40:\r
+        jmp     ClipPTop\r
+cc41:\r
+        call    ClipPTop\r
+        cmp     di, [mx_ClipX1]\r
+        jl      cc40FF\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY1]\r
+        jge     cc40TT\r
+        jmp     ClipQTop\r
+cc42:\r
+        call    ClipPTop\r
+        cmp     di, [mx_ClipX2]\r
+        jg      cc40FF\r
+        jmp     ClipQRight\r
+cc48:\r
+        call    ClipPTop\r
+        jmp     ClipQBottom\r
+cc49:\r
+        call    ClipPTop\r
+        cmp     di, [mx_ClipX1]\r
+        jl      cc40FF\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY2]\r
+        jle     cc40TT\r
+        jmp     ClipQBottom\r
+cc4A:\r
+        call    ClipPTop\r
+        cmp     di, [mx_ClipX2]\r
+        jg      cc40FF\r
+        call    ClipQRight\r
+        cmp     si, [mx_ClipY2]\r
+        jle     cc40TT\r
+        jmp     ClipQBottom\r
+\r
+\r
+; Group 50 -------------------------------------------------\r
+;\r
+cc50TT:\r
+        clc\r
+        ret\r
+cc50FF:\r
+        stc\r
+        ret\r
+cc50:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY1]\r
+        jge     cc50TT\r
+        jmp     ClipPTop\r
+cc52:\r
+        call    ClipQRight\r
+        cmp     si, [mx_ClipY1]\r
+        jl      cc50FF\r
+        call    ClipPTop\r
+        cmp     di, [mx_ClipX1]\r
+        jge     cc50TT\r
+        jmp     ClipPLeft\r
+cc58:\r
+        call    ClipQBottom\r
+        cmp     cx, [mx_ClipX1]\r
+        jl      cc50FF\r
+        call    ClipPTop\r
+        cmp     di, [mx_ClipX1]\r
+        jge     cc50TT\r
+        jmp     ClipPLeft\r
+cc5A:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      cc50FF\r
+        call    ClipQRight\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      cc50FF\r
+        cmp     si, [mx_ClipY2]\r
+        jle     cc50TT\r
+        jmp     ClipQBottom\r
+\r
+; Group 60 -------------------------------------------------\r
+;\r
+cc60TT:\r
+        clc\r
+        ret\r
+cc60FF:\r
+        stc\r
+        ret\r
+cc60:\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY1]\r
+        jge     cc60TT\r
+        jmp     ClipPTop\r
+cc61:\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY2]\r
+        jl      cc60FF\r
+        call    ClipPTop\r
+        cmp     di, [mx_ClipX2]\r
+        jle     cc60TT\r
+        jmp     ClipPRight\r
+cc68:\r
+        call    ClipQBottom\r
+        cmp     cx, [mx_ClipX2]\r
+        jg      cc60FF\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY1]\r
+        jge     cc60TT\r
+        jmp     ClipPTop\r
+cc69:\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY1]\r
+        jl      cc60FF\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      cc60FF\r
+        cmp     si, [mx_ClipY2]\r
+        jle     cc69_1\r
+        call    ClipQBottom\r
+cc69_1:\r
+        cmp     bx, [mx_ClipY1]\r
+        jge     cc60TT\r
+        jmp     ClipPTop\r
+\r
+; Group 80 -------------------------------------------------\r
+;\r
+cc80TT:\r
+        clc\r
+        ret\r
+cc80FF:\r
+        stc\r
+        ret\r
+cc80:\r
+        jmp     ClipPBottom\r
+cc81:\r
+        call    ClipPBottom\r
+        cmp     di, [mx_ClipX1]\r
+        jl      cc80FF\r
+        jmp     ClipQLeft\r
+cc82:\r
+        call    ClipPBottom\r
+        cmp     di, [mx_ClipX2]\r
+        jg      cc80FF\r
+        jmp     ClipQRight\r
+cc84:\r
+        call    ClipPBottom\r
+        jmp     ClipQTop\r
+cc85:\r
+        call    ClipPBottom\r
+        cmp     di, [mx_ClipX1]\r
+        jl      cc80FF\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY1]\r
+        jge     cc80FF\r
+        jmp     ClipQTop\r
+cc86:\r
+        call    ClipPBottom\r
+        cmp     di, [mx_ClipX2]\r
+        jg      cc80FF\r
+        call    ClipQRight\r
+        cmp     si, [mx_ClipY1]\r
+        jge     cc80TT\r
+        jmp     ClipQTop\r
+\r
+; Group 90 -------------------------------------------------\r
+;\r
+cc90TT:\r
+        clc\r
+        ret\r
+cc90FF:\r
+        stc\r
+        ret\r
+cc90:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY2]\r
+        jle     cc90TT\r
+        jmp     ClipPBottom\r
+cc92:\r
+        call    ClipQRight\r
+        cmp     si, [mx_ClipY2]\r
+        jg      cc90FF\r
+        call    ClipPBottom\r
+        cmp     di, [mx_ClipX1]\r
+        jge     cc90TT\r
+        jmp     ClipPLeft\r
+cc94:\r
+        call    ClipQTop\r
+        cmp     cx, [mx_ClipX1]\r
+        jl      cc90FF\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY2]\r
+        jle     cc90TT\r
+        jmp     ClipPBottom\r
+cc96:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      cc90FF\r
+        call    ClipQRight\r
+        cmp     si, [mx_ClipY2]\r
+        jg      cc90FF\r
+        cmp     bx, [mx_ClipY2]\r
+        jle     cc96_1\r
+        call    ClipPBottom\r
+cc96_1:\r
+        cmp     si, [mx_ClipY1]\r
+        jge     cc90TT\r
+        jmp     ClipQTop\r
+\r
+; Group A0 -------------------------------------------------\r
+;\r
+ccA0TT:\r
+        clc\r
+        ret\r
+ccA0FF:\r
+        stc\r
+        ret\r
+ccA0:\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY2]\r
+        jle     ccA0TT\r
+        jmp     ClipPBottom\r
+ccA1:\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY2]\r
+        jg      ccA0FF\r
+        call    ClipPBottom\r
+        cmp     di, [mx_ClipX2]\r
+        jle     ccA0TT\r
+        jmp     ClipPRight\r
+ccA4:\r
+        call    ClipQTop\r
+        cmp     cx, [mx_ClipX2]\r
+        jg      ccA0FF\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY2]\r
+        jle     ccA0TT\r
+        jmp     ClipPBottom\r
+ccA5:\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY2]\r
+        jg      ccA0FF\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      ccA0FF\r
+        cmp     si, [mx_ClipY1]\r
+        jge     ccA5_1\r
+        call    ClipQTop\r
+ccA5_1:\r
+        cmp     bx, [mx_ClipY2]\r
+        jle     ccA0TT\r
+        jmp     ClipPBottom\r
+\r
+; Y1 = (Y2-Y1)*(mx_ClipX1-X1)/(X2-X1)+Y1 = (SI-BX)*(mx_ClipX1-DI)/(CX-DI)+BX\r
+; X1 = mx_ClipX1\r
+ClipPLeft:\r
+        mov     ax, si\r
+        sub     ax, bx\r
+        mov     dx, [mx_ClipX1]\r
+        sub     dx, di\r
+        imul    dx\r
+        mov     bp, cx\r
+        sub     bp, di\r
+        idiv    bp\r
+        add     bx, ax\r
+        mov     di, [mx_ClipX1]\r
+        clc\r
+        ret\r
+\r
+; Y1 = (Y2-Y1)*(mx_ClipX2-X1)/(X2-X1)+Y1 = (SI-BX)*(mx_ClipX2-DI)/(CX-DI)+BX\r
+; X1 = mx_ClipX2\r
+ClipPRight:\r
+        mov     ax, si\r
+        sub     ax, bx\r
+        mov     dx, [mx_ClipX2]\r
+        sub     dx, di\r
+        imul    dx\r
+        mov     bp, cx\r
+        sub     bp, di\r
+        idiv    bp\r
+        add     bx, ax\r
+        mov     di, [mx_ClipX2]\r
+        clc\r
+        ret\r
+\r
+; X1 = (X2-X1)*(mx_ClipY2-Y1)/(Y2-Y1)+X1 = (CX-DI)*(mx_ClipY2-BX)/(SI-BX)+DI\r
+; Y1 = mx_ClipY2\r
+ClipPBottom:\r
+        mov     ax, cx\r
+        sub     ax, di\r
+        mov     dx, [mx_ClipY2]\r
+        sub     dx, bx\r
+        imul    dx\r
+        mov     bp, si\r
+        sub     bp, bx\r
+        idiv    bp\r
+        add     di, ax\r
+        mov     bx, [mx_ClipY2]\r
+        clc\r
+        ret\r
+\r
+; X1 = (X2-X1)*(mx_ClipY1-Y1)/(Y2-Y1)+X1 = (CX-DI)*(mx_ClipY1-BX)/(SI-BX)+DI\r
+; Y1 = mx_ClipY1\r
+ClipPTop:\r
+        mov     ax, cx\r
+        sub     ax, di\r
+        mov     dx, [mx_ClipY1]\r
+        sub     dx, bx\r
+        imul    dx\r
+        mov     bp, si\r
+        sub     bp, bx\r
+        idiv    bp\r
+        add     di, ax\r
+        mov     bx, [mx_ClipY1]\r
+        clc\r
+        ret\r
+\r
+; Y2 = (Y1-Y2)*(mx_ClipX1-X2)/(X1-X2)+Y2 = (BX-SI)*(mx_ClipX1-CX)/(DI-CX)+SI\r
+; X2 = mx_ClipX1\r
+ClipQLeft:\r
+        mov     ax, bx\r
+        sub     ax, si\r
+        mov     dx, [mx_ClipX1]\r
+        sub     dx, cx\r
+        imul    dx\r
+        mov     bp, di\r
+        sub     bp, cx\r
+        idiv    bp\r
+        add     si, ax\r
+        mov     cx, [mx_ClipX1]\r
+        clc\r
+        ret\r
+\r
+; Y2 = (Y1-Y2)*(mx_ClipX2-X2)/(X1-X2)+Y2 = (BX-SI)*(mx_ClipX2-CX)/(DI-CX)+SI\r
+; X2 = mx_ClipX1\r
+ClipQRight:\r
+        mov     ax, bx\r
+        sub     ax, si\r
+        mov     dx, [mx_ClipX2]\r
+        sub     dx, cx\r
+        imul    dx\r
+        mov     bp, di\r
+        sub     bp, cx\r
+        idiv    bp\r
+        add     si, ax\r
+        mov     cx, [mx_ClipX2]\r
+        clc\r
+        ret\r
+\r
+; X2 = (X1-X2)*(mx_ClipY2-Y2)/(Y1-Y2)+X2 = (DI-CX)*(mx_ClipY2-SI)/(BX-SI)+CX\r
+; Y2 = mx_ClipY1\r
+ClipQBottom:\r
+        mov     ax, di\r
+        sub     ax, cx\r
+        mov     dx, [mx_ClipY2]\r
+        sub     dx, si\r
+        imul    dx\r
+        mov     bp, bx\r
+        sub     bp, si\r
+        idiv    bp\r
+        add     cx, ax\r
+        mov     si, [mx_ClipY2]\r
+        clc\r
+        ret\r
+\r
+; X2 = (X1-X2)*(mx_ClipY1-Y2)/(Y1-Y2)+X2 = (DI-CX)*(mx_ClipY1-SI)/(BX-SI)+CX\r
+; Y2 = mx_ClipY1\r
+ClipQTop:\r
+        mov     ax, di\r
+        sub     ax, cx\r
+        mov     dx, [mx_ClipY1]\r
+        sub     dx, si\r
+        imul    dx\r
+        mov     bp, bx\r
+        sub     bp, si\r
+        idiv    bp\r
+        add     cx, ax\r
+        mov     si, [mx_ClipY1]\r
+        clc\r
+        ret\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Checks the coordinates of a line against the active\r
+; clip region.\r
+; Uses the Sobkow-Pospisil-Yang (SPY) algorithm: this was\r
+; supposed to be twice as fast as Cohen-Sutherland, but my\r
+; tests show only a very small increase in speed and a noticeable\r
+; increase of the program size! Maybe this is caused by the\r
+; slow speed of VGA cards, so probably a better test should\r
+; be performed with lines drawn in RAM.\r
+;\r
+; Input:\r
+;       AX, BX  = X1, Y1\r
+;       CX, DX  = X2, Y2\r
+; Output:\r
+;       CF      = set if line is full clipped\r
+;       AX, BX  = clipped X1, Y1\r
+;       CX, DX  = clipped X2, Y2\r
+; Note:\r
+;       destroys SI, DI\r
+;\r
+xsubClipLine     PROC    NEAR\r
+        push    bp\r
+        xor     si, si                  ; SPY code\r
+\r
+        cmp     dx, [mx_ClipY2]\r
+        jle     @@1\r
+        or      si, 08h\r
+        jmp     @@2\r
+@@1:\r
+        cmp     dx, [mx_ClipY1]\r
+        jge     @@2\r
+        or      si, 04h\r
+@@2:\r
+\r
+        cmp     cx, [mx_ClipX2]\r
+        jle     @@3\r
+        or      si, 02h\r
+        jmp     @@4\r
+@@3:\r
+        cmp     cx, [mx_ClipX1]\r
+        jge     @@4\r
+        or      si, 01h\r
+@@4:\r
+\r
+        cmp     bx, [mx_ClipY2]\r
+        jle     @@5\r
+        or      si, 80h\r
+        jmp     @@6\r
+@@5:\r
+        cmp     bx, [mx_ClipY1]\r
+        jge     @@6\r
+        or      si, 40h\r
+@@6:\r
+\r
+        cmp     ax, [mx_ClipX2]\r
+        jle     @@7\r
+        or      si, 20h\r
+        jmp     @@8\r
+@@7:\r
+        cmp     ax, [mx_ClipX1]\r
+        jge     @@8\r
+        or      si, 10h\r
+@@8:\r
+\r
+        mov     di, si\r
+        and     di, 000Fh               ; Index of procedure\r
+        and     si, 00F0h\r
+        .shr    si, 2                   ; Index of group (times 4)\r
+        cmp     di, cs:tblGroups[si]    ; Is index within range?\r
+        jg      @@Exit                  ; No, line is full clipped\r
+        mov     si, cs:tblGroups[si+2]  ; Get offset of group table\r
+        shl     di, 1                   ; We must index word elements\r
+        add     si, di                  ; Make full offset\r
+        mov     di, ax                  ; Move X1 to DI and free AX\r
+        mov     si, cs:[si]             ; Get subroutine address\r
+        xchg    dx, si                  ; Move Y2 to SI and free DX\r
+        call    dx                      ; Call the proper subroutine\r
+        mov     ax, di                  ; Restore AX to X1\r
+        mov     dx, si                  ; Restore DX to Y2\r
+        pop     bp\r
+        ret\r
+\r
+@@Exit:\r
+        pop     bp\r
+        stc\r
+        ret\r
+xsubClipLine     ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxcg.asm b/16/x/mxcg.asm
new file mode 100755 (executable)
index 0000000..42163d7
--- /dev/null
@@ -0,0 +1,69 @@
+;-----------------------------------------------------------\r
+;\r
+; MXCG.ASM - Color to gray conversion\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxColorToGray\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Converts RGB colors to gray shades.\r
+;\r
+; Input:\r
+;       CPal    = pointer to color palette\r
+;       GPal    = pointer to destination (gray) palette\r
+;       Count   = number of colors to convert\r
+; Output:\r
+;       none\r
+;\r
+; Note: CPal and GPal may point to the same buffer.\r
+;\r
+mxColorToGray   PROC    FAR\r
+        ARG     Count:WORD,     \\r
+                DPal:DWORD,     \\r
+                SPal:DWORD      = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si, es, di\r
+\r
+        mov     cx, [Count]\r
+        jcxz    @@Exit\r
+        lds     si, [SPal]\r
+        les     di, [DPal]\r
+        cld\r
+; We use the standard formula\r
+;       gray=(red*30 + green*59 + blue*11)/100\r
+; in the equivalent form\r
+;       gray=(red*77 + green*151 + blue*28)/256\r
+; which doesn't need the last divide.\r
+        mov     bx, 77 SHL 8 + 151\r
+@@Loop:\r
+        lodsb                           ; Red\r
+        mul     bh\r
+        mov     dx, ax\r
+        lodsb                           ; Green\r
+        mul     bl\r
+        add     dx, ax\r
+        lodsb                           ; Blue\r
+        mov     ah, 28\r
+        mul     ah\r
+        add     ax, dx\r
+        mov     al, ah\r
+        stosw                           ; Save new RGB\r
+        stosb\r
+        loop    @@Loop\r
+\r
+@@Exit:\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxColorToGray   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxcl.asm b/16/x/mxcl.asm
new file mode 100755 (executable)
index 0000000..aaa0bac
--- /dev/null
@@ -0,0 +1,151 @@
+;-----------------------------------------------------------\r
+;\r
+; MXCL.ASM - Bresenham circle\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxCircle\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Draws a circle using the Bresenham algorithm.\r
+;\r
+; Input:\r
+;       XC, YC  = center coordinates\r
+;       Radius  = circle radius\r
+;       Color   = circle color\r
+; Output:\r
+;       none\r
+; Note:\r
+;       computes only points in the first octant, all other\r
+;       points are obtained by symmetry.\r
+;\r
+mxCircle        PROC FAR\r
+        ARG     Color:BYTE:2,           \\r
+                Radius:WORD,            \\r
+                YC:WORD,                \\r
+                XC:WORD                 = ARG_SIZE\r
+        LOCAL   Delta:WORD              = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, di\r
+\r
+        xor     si, si                  ; X\r
+        mov     di, [Radius]            ; Y\r
+        mov     ax, 3\r
+        sub     ax, di\r
+        sub     ax, di\r
+        mov     [Delta], ax             ; Delta = 3-R*2\r
+\r
+        mov     ds, [mx_VideoSegment]\r
+\r
+@@Loop:\r
+        cmp     si, di                  ;\r
+        jg      @@Done                  ; Exit when X > Y\r
+; Draw points\r
+        mov     ax, si\r
+        mov     bx, di\r
+        call    @@subPutPixel\r
+        mov     ax, si\r
+        neg     ax\r
+        mov     bx, di\r
+        call    @@subPutPixel\r
+        mov     ax, si\r
+        mov     bx, di\r
+        neg     bx\r
+        call    @@subPutPixel\r
+        mov     ax, si\r
+        neg     ax\r
+        mov     bx, di\r
+        neg     bx\r
+        call    @@subPutPixel\r
+        mov     ax, di\r
+        mov     bx, si\r
+        call    @@subPutPixel\r
+        mov     ax, di\r
+        neg     ax\r
+        mov     bx, si\r
+        call    @@subPutPixel\r
+        mov     ax, di\r
+        mov     bx, si\r
+        neg     bx\r
+        call    @@subPutPixel\r
+        mov     ax, di\r
+        neg     ax\r
+        mov     bx, si\r
+        neg     bx\r
+        call    @@subPutPixel\r
+; Moves coordinates to next point\r
+        mov     ax, [Delta]\r
+        test    ax, ax\r
+        jl      @@Next\r
+        mov     ax, di\r
+        .shl    ax, 2\r
+        sub     ax, 4\r
+        sub     [Delta], ax\r
+        dec     di\r
+@@Next:\r
+        mov     ax, si\r
+        .shl    ax, 2\r
+        add     ax, 6\r
+        add     [Delta], ax\r
+        inc     si\r
+        jmp     @@Loop\r
+\r
+@@Done:\r
+        xor     ax, ax\r
+        .pop    ds, si, di\r
+        .leave  ARG_SIZE\r
+\r
+;---------------------------------------\r
+; Put pixel function.\r
+; Input:\r
+;       BX      = X coordinate (relative to center)\r
+;       AX      = Y coordinate (relative to center)\r
+;       DS      = video segment\r
+@@subPutPixel:\r
+        add     bx, [XC]                ; Get absolute coordinates\r
+        add     ax, [YC]\r
+\r
+        cmp     bx, [mx_ClipX1]         ; Clip pixel\r
+        jl      @@subExit\r
+        cmp     bx, [mx_ClipX2]\r
+        jg      @@subExit\r
+        cmp     ax, [mx_ClipY1]\r
+        jl      @@subExit\r
+        cmp     ax, [mx_ClipY2]\r
+        jg      @@subExit\r
+\r
+        mul     [mx_BytesPerLine]       ; Get pixel offset\r
+        mov     cx, bx                  ; Save X coordinate\r
+        .shr    bx, 2\r
+        add     bx, ax                  ; DS:BX = pixel offset\r
+\r
+        and     cl, 3                   ; Set write plane\r
+        mov     ax, 0102h\r
+        shl     ah, cl\r
+        mov     dx, TS\r
+        out     dx, ax\r
+\r
+        mov     al, [Color]             ; Write pixel\r
+        mov     ds:[bx], al\r
+\r
+@@subExit:\r
+        retn\r
+mxCircle        ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxcr.asm b/16/x/mxcr.asm
new file mode 100755 (executable)
index 0000000..ca1fa7b
--- /dev/null
@@ -0,0 +1,380 @@
+;-----------------------------------------------------------\r
+;\r
+; MXCR.ASM - Clip functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxSetSysClipRegion\r
+PUBLIC  mxGetClipRegion\r
+PUBLIC  mxSetClipRegion\r
+PUBLIC  mxSetClip\r
+PUBLIC  mxGetClip\r
+\r
+PUBLIC  subClipBox\r
+PUBLIC  subClipImage\r
+\r
+PUBLIC  mx_ClipX1\r
+PUBLIC  mx_ClipY1\r
+PUBLIC  mx_ClipX2\r
+PUBLIC  mx_ClipY2\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_CodeSegment  : WORD\r
+\r
+mx_ClipX1       DW      ?               ; Clip coordinates\r
+mx_ClipY1       DW      ?\r
+mx_ClipX2       DW      ?\r
+mx_ClipY2       DW      ?\r
+\r
+mx_SysClipX1    DW      ?               ; System clip coordinates\r
+mx_SysClipY1    DW      ?               ; (active when mx_ClipStatus is FALSE)\r
+mx_SysClipX2    DW      ?\r
+mx_SysClipY2    DW      ?\r
+\r
+mx_UserClipX1   DW      ?               ; User clip coordinates\r
+mx_UserClipY1   DW      ?               ; (active when mx_ClipStatus is TRUE)\r
+mx_UserClipX2   DW      ?\r
+mx_UserClipY2   DW      ?\r
+\r
+mx_ClipStatus   DB      ?\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Toggles clipping between user and system regions.\r
+;\r
+; Input:\r
+;       ClipStatus      = TRUE (FALSE) to enable (disable) clipping\r
+; Output:\r
+;       AX      = old clip status\r
+;\r
+mxSetClip       PROC    FAR\r
+        ARG     ClipStatus:BYTE:2       = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, [mx_UserClipX1]\r
+        mov     bx, [mx_UserClipY1]\r
+        mov     cx, [mx_UserClipX2]\r
+        mov     dx, [mx_UserClipY2]\r
+        cmp     [ClipStatus], TRUE\r
+        je      @@Done\r
+        mov     ax, [mx_SysClipX1]\r
+        mov     bx, [mx_SysClipY1]\r
+        mov     cx, [mx_SysClipX2]\r
+        mov     dx, [mx_SysClipY2]\r
+@@Done:\r
+        mov     [mx_ClipX1], ax\r
+        mov     [mx_ClipY1], bx\r
+        mov     [mx_ClipX2], cx\r
+        mov     [mx_ClipY2], dx\r
+\r
+        mov     al, [ClipStatus]\r
+        xchg    al, [mx_ClipStatus]\r
+        xor     ah, ah\r
+\r
+        .pop    ds\r
+        .leave  ARG_SIZE\r
+mxSetClip       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current clipping status.\r
+;\r
+; Input:\r
+;       none\r
+; Output:\r
+;       TRUE (FALSE) if clipping enabled (disabled)\r
+;\r
+mxGetClip       PROC    FAR\r
+        ASSUME  ds:NOTHING\r
+        mov     al, [mx_ClipStatus]\r
+        xor     ah, ah\r
+        ret\r
+mxGetClip       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the system clip region and disables user clipping.\r
+;\r
+; Input:\r
+;       Width   = width in pixels of clip region\r
+;       Height  = height in pixels of clip region\r
+; Output:\r
+;       old clip status.\r
+;\r
+mxSetSysClipRegion      PROC    FAR\r
+        ARG     Height:WORD,            \\r
+                Width:WORD              = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        xor     ax, ax                  ; Sys clip region always starts at (0,0)\r
+        mov     [mx_SysClipX1], ax\r
+        mov     [mx_SysClipY1], ax\r
+        mov     ax, [Width]\r
+        dec     ax\r
+        mov     [mx_SysClipX2], ax\r
+        mov     ax, [Height]\r
+        dec     ax\r
+        mov     [mx_SysClipY2], ax\r
+\r
+    IF USE286 EQ TRUE\r
+        push    FALSE\r
+    ELSE\r
+        mov     ax, FALSE\r
+        push    ax\r
+    ENDIF\r
+        call    mxSetClip\r
+\r
+        .pop    ds\r
+        .leave  ARG_SIZE\r
+mxSetSysClipRegion      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the clip region.\r
+;\r
+; Input:\r
+;       X, Y    = coordinates of top left corner of clip region\r
+;       Width   = width in pixels of clip region\r
+;       Height  = height in pixels of clip region\r
+; Output:\r
+;       none (no checking on parameters)\r
+;\r
+mxSetClipRegion PROC    FAR\r
+        ARG     Height:WORD,            \\r
+                Width:WORD,             \\r
+                Y:WORD,                 \\r
+                X:WORD                  = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, [X]\r
+        mov     [mx_UserClipX1], ax\r
+        mov     ax, [Y]\r
+        mov     [mx_UserClipY1], ax\r
+        mov     ax, [Width]\r
+        add     ax, [X]\r
+        dec     ax\r
+        mov     [mx_UserClipX2], ax\r
+        mov     ax, [Height]\r
+        add     ax, [Y]\r
+        dec     ax\r
+        mov     [mx_UserClipY2], ax\r
+\r
+        mov     al, [mx_ClipStatus]\r
+        cmp     al, TRUE\r
+        jne     @@Exit\r
+        push    ax\r
+        call    mxSetClip\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds\r
+        .leave  ARG_SIZE\r
+mxSetClipRegion ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current user clip region.\r
+;\r
+; Input:\r
+;       X, Y    = pointers to integer coordinates of top left corner\r
+;       Width   = pointer to word width of clip region\r
+;       Height  = pointer to word height of clip region\r
+; Output:\r
+;       AX      = current clip status\r
+;\r
+mxGetClipRegion PROC    FAR\r
+        ARG     Height:DWORD,           \\r
+                Width:DWORD,            \\r
+                Y:DWORD,                \\r
+                X:DWORD                 = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   es, di\r
+\r
+        mov     ax, [mx_UserClipX1]\r
+        les     di, [X]\r
+        mov     es:[di], ax\r
+        mov     ax, [mx_UserClipY1]\r
+        les     di, [Y]\r
+        mov     es:[di], ax\r
+\r
+        mov     ax, [mx_UserClipX2]\r
+        sub     ax, [mx_UserClipX1]\r
+        inc     ax\r
+        les     di, [Width]\r
+        mov     es:[di], ax\r
+        mov     ax, [mx_UserClipY2]\r
+        sub     ax, [mx_UserClipY1]\r
+        inc     ax\r
+        les     di, [Height]\r
+        mov     es:[di], ax\r
+\r
+        mov     al, [mx_ClipStatus]\r
+        xor     ah, ah\r
+        .pop    es, di\r
+        .leave  ARG_SIZE\r
+mxGetClipRegion ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Internal use: checks the coordinates of a rectangle against\r
+; the active clip region.\r
+; This function assumes that a "raw" image has to be clipped,\r
+; so it returns in SI the number of "raw" bytes to skip if\r
+; X, Y were clipped.\r
+;\r
+; Input:\r
+;       BX, AX  = X, Y coordinates of rectangle (signed)\r
+;       CX      = box width\r
+;       DX      = box height\r
+; Output:\r
+;       CF      = set if rectangle is full clipped\r
+;       BX, AX  = new X, Y coordinates of rectangle\r
+;       CX, DX  = clipped width and height\r
+;       SI      = number of bytes to skip before copying a buffer\r
+;       DI destroyed\r
+;\r
+subClipImage    PROC    NEAR\r
+        ASSUME  ds:NOTHING\r
+        xor     si, si\r
+\r
+; Check clip height\r
+        mov     di, [mx_ClipY1]\r
+        cmp     ax, di\r
+        jge     @@CheckBottom\r
+        sub     di, ax                  ; Number of lines to clip\r
+        sub     dx, di                  ; New box height\r
+        jle     @@Exit\r
+        mov     ax, di\r
+        mov     di, dx                  ; Save box height into DI\r
+        mul     cx                      ; DX:AX = number of bytes to skip\r
+        mov     si, ax\r
+        mov     dx, di                  ; Restore box height\r
+        mov     ax, [mx_ClipY1]\r
+@@CheckBottom:\r
+        mov     di, [mx_ClipY2]\r
+        cmp     ax, di\r
+        jg      @@Exit\r
+        inc     di\r
+        sub     di, dx\r
+        sub     di, ax\r
+        jge     @@DoneHeight            ; None, continue\r
+        add     dx, di                  ; Clip lines\r
+@@DoneHeight:\r
+\r
+; Check clip width\r
+@@CheckLeft:\r
+        mov     di, [mx_ClipX1]\r
+        cmp     bx, di\r
+        jge     @@CheckRight\r
+        sub     di, bx                  ; Number of columns to clip left\r
+        sub     cx, di\r
+        jle     @@Exit\r
+        add     si, di                  ; Update skip count\r
+        mov     bx, [mx_ClipX1]\r
+@@CheckRight:\r
+        mov     di, [mx_ClipX2]\r
+        cmp     bx, di\r
+        jg      @@Exit\r
+        inc     di\r
+        sub     di, bx\r
+        sub     di, cx\r
+        jge     @@DoneWidth             ; None, exit\r
+        add     cx, di                  ; New box width\r
+@@DoneWidth:\r
+\r
+; Set return flag and exit\r
+@@Done:\r
+        clc\r
+        ret\r
+@@Exit:\r
+        stc\r
+        ret\r
+subClipImage    ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Internal use: checks the coordinates of a rectangle against\r
+; the active clip region.\r
+;\r
+; Input:\r
+;       BX, AX  = X, Y coordinates of rectangle (signed)\r
+;       CX      = box width\r
+;       DX      = box height\r
+; Output:\r
+;       CF      = set if rectangle is full clipped\r
+;       BX, AX  = new X, Y coordinates of rectangle\r
+;       CX, DX  = clipped width and height\r
+;       DI destroyed\r
+;\r
+subClipBox      PROC    NEAR\r
+        ASSUME  ds:NOTHING\r
+\r
+; Check clip height\r
+        mov     di, [mx_ClipY1]\r
+        cmp     ax, di\r
+        jge     @@CheckBottom\r
+        sub     di, ax                  ; Number of lines to clip\r
+        sub     dx, di                  ; New box height\r
+        jle     @@Exit\r
+        mov     ax, [mx_ClipY1]\r
+@@CheckBottom:\r
+        mov     di, [mx_ClipY2]\r
+        cmp     ax, di\r
+        jg      @@Exit\r
+        inc     di\r
+        sub     di, dx\r
+        sub     di, ax                  ; Clipped some point?\r
+        jge     @@DoneHeight            ; No, continue\r
+        add     dx, di                  ; Clip lines (DI is negative)\r
+@@DoneHeight:\r
+\r
+; Check clip width\r
+@@CheckLeft:\r
+        mov     di, [mx_ClipX1]\r
+        cmp     bx, di\r
+        jge     @@CheckRight\r
+        sub     di, bx                  ; Number of columns to clip left\r
+        sub     cx, di\r
+        jle     @@Exit\r
+        mov     bx, [mx_ClipX1]\r
+@@CheckRight:\r
+        mov     di, [mx_ClipX2]\r
+        cmp     bx, di\r
+        jg      @@Exit\r
+        inc     di\r
+        sub     di, bx\r
+        sub     di, cx                  ; Clipped some point?\r
+        jge     @@DoneWidth             ; No, exit\r
+        add     cx, di                  ; New box width (DI is negative)\r
+@@DoneWidth:\r
+\r
+; Set return flag and exit\r
+@@Done:\r
+        clc\r
+        ret\r
+@@Exit:\r
+        stc\r
+        ret\r
+subClipBox      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxel.asm b/16/x/mxel.asm
new file mode 100755 (executable)
index 0000000..2c9dda2
--- /dev/null
@@ -0,0 +1,167 @@
+;-----------------------------------------------------------\r
+;\r
+; MXEL.ASM - Mid-point ellipse\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxEllipse\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Draws an ellipse using the mid-point algorithm.\r
+;\r
+; Input:\r
+;       XC, YC  = center coordinates\r
+;       A       = horizontal radius\r
+;       B       = vertical radius\r
+;       Color   = ellipse color\r
+; Output:\r
+;       none\r
+; Note:\r
+;       computes only points in the first quadrant, all other\r
+;       points are obtained by symmetry.\r
+;\r
+mxEllipse       PROC FAR\r
+        ARG     Color:BYTE:2,   \\r
+                B:WORD,         \\r
+                A:WORD,         \\r
+                YC:WORD,        \\r
+                XC:WORD         = ARG_SIZE\r
+        LOCAL   A2:DWORD,       \\r
+                B2:DWORD,       \\r
+                CC:DWORD,       \\r
+                DD:DWORD,       \\r
+                X:DWORD,        \\r
+                Y:DWORD         = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, di\r
+\r
+        .chk386 mxEllipse, @@Exit\r
+\r
+; Initialize variables\r
+        xor     eax, eax\r
+        mov     [X], ax         ; X = 0\r
+        mov     ax, [A]\r
+        mul     eax             ; EAX = A*A\r
+        mov     [DD], eax       ; DD = A*A\r
+        shl     eax, 1\r
+        mov     [CC], eax       ; CC = 2*A*A\r
+        shl     eax, 1\r
+        mov     [A2], eax       ; A2 = 4*A*A\r
+        movzx   edx, [B]\r
+        mov     [Y], edx\r
+        mul     edx             ; EAX = 4*A*A*B\r
+        sub     [DD], eax       ; DD = A*A - 4*A*A*B\r
+        movzx   eax, [B]\r
+        mul     eax             ; EAX = B*B\r
+        shl     eax, 2          ; EAX = 4*B*B\r
+        mov     [B2], eax       ; B2 = 4*B*B\r
+        add     [CC], eax       ; CC = 2*A*A + 4*B*B\r
+        add     [D1], eax       ; DD = A*A - 4*A*A*B + 4*B*B\r
+\r
+; Draw initial points\r
+        call    subPlot4\r
+\r
+; First loop\r
+@@Loop1:\r
+        mov     eax, [X]        ; Check slope\r
+        mul     [B2]\r
+        mov     ecx, eax\r
+        mov     eax, [Y]\r
+        mul     [A2]\r
+        sub     eax, ecx\r
+        sub     eax, [CC]       ; EAX = Y*A2 - X*B2 - CC\r
+        jle     @@Done1         ; Crossed critical point, jump to next loop\r
+\r
+        mov     ecx, [DD]       ; Get error\r
+        test    ecx, ecx        ; Positive?\r
+        jl      @@Draw1         ; No, use default step\r
+\r
+        mov     eax, 1\r
+        sub     eax, [Y]\r
+        mul     [A2]\r
+        shl     eax, 1\r
+        add     ecx, eax        ; Bump error\r
+        dec     WORD PTR [Y]    ; Decrement Y coordinate\r
+\r
+@@Draw1:\r
+        mov     eax, [X]\r
+        shl     eax, 1\r
+        add     eax, 3\r
+        mul     [B2]\r
+        add     ecx, eax        ; Bump error\r
+        mov     [DD], ecx       ; Save error\r
+        inc     WORD PTR [X]    ; Increment X coordinate\r
+\r
+        call    subPlot4        ; Draw points\r
+        jmp     @@Loop1\r
+@@Done1:\r
+\r
+; Initialize variables\r
+        shr     [B2], 2\r
+        mov     eax, [X]\r
+        mul     eax\r
+        add     [X]\r
+        shl     eax, 2\r
+        inc     eax\r
+        mul     [B2]\r
+        mov     [DD], eax\r
+        mov     eax, [Y]\r
+        mul     eax\r
+        add     [Y]\r
+        dec     eax\r
+        add     [Y]\r
+        sub     eax, [B2]\r
+        add     [DD], eax\r
+        shl     [B2], 3\r
+        inc     WORD PTR [X]\r
+\r
+; Second loop\r
+@@Loop2:\r
+        cmp     WORD PTR [Y], 0\r
+        ja      @@Done2\r
+\r
+        mov     ecx, [DD]\r
+        test    ecx, ecx\r
+        jge     @@Draw2\r
+\r
+        mov     eax, [X]\r
+        inc     eax\r
+        mul     [B2]\r
+        add     ecx, eax\r
+        inc     WORD PTR [X]\r
+\r
+@@Draw2:\r
+        mov     eax, [Y]\r
+        shl     eax, 1\r
+        sub     eax, 3\r
+        neg     eax\r
+        imul    [A2]\r
+        add     ecx, eax\r
+        dec     WORD PTR [Y]\r
+\r
+        call    subPlot4\r
+        jmp     @@Loop2\r
+@@Done2:\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .leave  ARG_SIZE\r
+mxEllipse       ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxfb.asm b/16/x/mxfb.asm
new file mode 100755 (executable)
index 0000000..41ea5de
--- /dev/null
@@ -0,0 +1,194 @@
+;-----------------------------------------------------------\r
+;\r
+; MXFB.ASM - Fill box function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxFillBox\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine         : WORD\r
+EXTRN   mx_VideoSegment         : WORD\r
+EXTRN   subClipBox              : NEAR\r
+EXTRN   subHorizontalLineInfo   : NEAR\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Raster op functions. Raster op is limited to OP_MOVE,\r
+; OP_AND, OP_OR and OP_XOR. The VGA hardware is used to\r
+; perform the selected logical functions on up to four\r
+; pixel at a time.\r
+;\r
+subRepFill      PROC    NEAR\r
+        mov     ah, al\r
+        shr     cx, 1\r
+        rep     stosw\r
+        rcl     cx, 1\r
+        rep     stosb\r
+        ret\r
+subRepFill      ENDP\r
+;\r
+subFill         PROC    NEAR\r
+@@Loop:\r
+        mov     ds:[bx], al\r
+        add     bx, dx\r
+        loop    @@Loop\r
+        ret\r
+subFill         ENDP\r
+;\r
+subRepMove      PROC    NEAR\r
+        mov     si, di\r
+@@Loop:\r
+        mov     ah, ds:[si]             ; Dummy read to latch the data\r
+        mov     ds:[si], al\r
+        inc     si\r
+        loop    @@Loop\r
+        ret\r
+subRepMove      ENDP\r
+;\r
+subMove         PROC    NEAR\r
+@@Loop:\r
+        mov     ah, ds:[bx]             ; Dummy read to latch the data\r
+        mov     ds:[bx], al\r
+        add     bx, dx\r
+        loop    @@Loop\r
+        ret\r
+subMove         ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a rectangle with a specified color.\r
+;\r
+; Input:\r
+;       X, Y            = X, Y coordinates of rectangle\r
+;       Width           = width of rectangle\r
+;       Height          = height of rectangle\r
+;       Color           = fill color\r
+;       Op              = raster operator\r
+; Output:\r
+;       none\r
+;\r
+; Note: raster op is limited to OP_MOVE, OP_AND, OP_OR and OP_XOR.\r
+;\r
+mxFillBox       PROC    FAR\r
+        ARG     Op:WORD,                \\r
+                Color:BYTE:2,           \\r
+                Height:WORD,            \\r
+                Width:WORD,             \\r
+                Y:WORD,                 \\r
+                X:WORD                  = ARG_SIZE\r
+        LOCAL   LeftMask:BYTE,          \\r
+                RightMask:BYTE,         \\r
+                FillFunction:WORD,      \\r
+                RepFillFunction:WORD    = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+        ASSUME  ds:NOTHING\r
+\r
+; Clip rectangle\r
+        mov     bx, [X]\r
+        mov     ax, [Y]\r
+        mov     cx, [Width]\r
+        mov     dx, [Height]\r
+        call    subClipBox\r
+        jc      @@Exit                  ; Full clipped\r
+\r
+        mov     [Height], dx            ; Save clipped height\r
+        call    subHorizontalLineInfo   ; Get additional info, init DI\r
+        mov     [Width], cx\r
+        mov     [LeftMask], al\r
+        mov     [RightMask], ah\r
+\r
+; Initialize segments\r
+        mov     ax, [mx_VideoSegment]\r
+        mov     es, ax                  ; ES:DI points to pixel\r
+        mov     ds, ax\r
+        cld                             ; Clear direction flag\r
+\r
+; Select fill functions\r
+        mov     [FillFunction], OFFSET subFill\r
+        mov     [RepFillFunction], OFFSET subRepFill\r
+        mov     ax, [Op]                ; Get raster op\r
+        cmp     al, OP_XOR\r
+        ja      @@1                     ; Assume it's a fill\r
+        cmp     al, OP_MOVE\r
+        je      @@1\r
+        .shl    al, 3\r
+        mov     ah, al\r
+        mov     al, 03h\r
+        mov     dx, GDC\r
+        out     dx, ax                  ; Set GDC logical function\r
+        mov     [FillFunction], OFFSET subMove\r
+        mov     [RepFillFunction], OFFSET subRepMove\r
+@@1:\r
+\r
+; Fill left block\r
+@@L0:\r
+        mov     ah, [LeftMask]\r
+        or      ah, ah\r
+        jz      @@C0                    ; Nothing to do, go to center block\r
+        mov     dx, TS\r
+        mov     al, 02h\r
+        out     dx, ax                  ; Set write plane mask\r
+        mov     dx, [mx_BytesPerLine]\r
+        mov     cx, [Height]\r
+        mov     bx, di\r
+        mov     al, [Color]\r
+        call    [FillFunction]          ; Fill this column\r
+        inc     di                      ; Update starting video offset\r
+\r
+; Fill center block\r
+@@C0:\r
+        mov     cx, [Width]\r
+        jcxz    @@R0                    ; Nothing to do, go to right block\r
+        mov     dx, TS\r
+        mov     ax, 0F02h\r
+        out     dx, ax                  ; Write to all planes\r
+        mov     al, [Color]\r
+        mov     bx, di\r
+        mov     dx, [Height]\r
+        push    di                      ; Save pixel address\r
+@@C1:\r
+        mov     di, bx                  ; Update video offset\r
+        call    [RepFillFunction]       ; Fill current scan line\r
+        mov     cx, [Width]             ; Restore byte count\r
+        add     bx, [mx_BytesPerLine]   ; Bump to next scan line\r
+        dec     dx                      ; Done all lines?\r
+        jnz     @@C1                    ; No, continue\r
+        pop     di                      ; Restore pixel address\r
+        add     di, [Width]             ; Go to right block\r
+\r
+; Fill right block\r
+@@R0:\r
+        mov     ah, [RightMask]\r
+        or      ah, ah\r
+        jz      @@Done                  ; Nothing to do, exit\r
+        mov     dx, TS\r
+        mov     al, 02h\r
+        out     dx, ax                  ; Set write plane mask\r
+        mov     dx, [mx_BytesPerLine]\r
+        mov     cx, [Height]\r
+        mov     bx, di\r
+        mov     al, [Color]\r
+        call    [FillFunction]          ; Fill this column\r
+\r
+; Restore VGA registers\r
+@@Done:\r
+        mov     dx, GDC\r
+        mov     ax, 0003h\r
+        out     dx, ax                  ; Set logical function to "move"\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxFillBox       ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxfp.asm b/16/x/mxfp.asm
new file mode 100755 (executable)
index 0000000..8eea25b
--- /dev/null
@@ -0,0 +1,326 @@
+;-----------------------------------------------------------\r
+;\r
+; MXFP.ASM - Fade palette function\r
+; Copyright (c) 1992-1994 ARTIS s.r.l.\r
+; Author: Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxFadePalette\r
+\r
+MAXCOLOR        EQU     256\r
+FADE_IN         EQU     0\r
+FADE_OUT        EQU     1\r
+\r
+; The actual speed of fading depends on the number of passes (FADE_SPEED) and\r
+; the delay between two consecutive passes (FADE_DELAY). Below are the\r
+; default values, used when no parameters are specified.\r
+;\r
+FADE_DELAY      EQU     1               ; Vert. retraces between video updates\r
+FADE_SPEED      EQU     48              ; Speed of effect (max 127)\r
+\r
+; Bit field record for fade commands\r
+;\r
+FADE_COMMAND    RECORD  fpDELAY:8,fpSPEED:7,fpDIRECTION:1\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+DB      'Copyright (c) 1992-1994 ARTIS s.r.l. All rights reserved.'\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fades a VGA palette.\r
+;\r
+; Input:\r
+;       Buffer          = pointer to source/destination palette\r
+;       Command         = fading direction and optional parameters\r
+;       Start           = index of first color to fade\r
+;       Count           = number of color to fade\r
+;       Red             = destination red\r
+;       Green           = destination green\r
+;       Blue            = destination blue\r
+; Output:\r
+;       none\r
+; Notes:\r
+;    -  about 1.5 Kbytes of stack space are needed for internal buffers;\r
+;    -  the Command argument usually is 0 to fade in and 1 to fade out,\r
+;       however additional parameters may be specified. To set the effect\r
+;       speed, i.e. the number of iterations needed to completely fade a\r
+;       palette, shift the value one bit left and "or" it with the\r
+;       direction bit (range is 0..127). To set the delay between two\r
+;       consecutive passes, shift it eight bits left (range is 0..255).\r
+;\r
+mxFadePalette   PROC FAR\r
+        ARG     bBlue:WORD,                     \\r
+                bGreen:WORD,                    \\r
+                bRed:WORD,                      \\r
+                wCount:WORD,                    \\r
+                wStartIdx:WORD,                 \\r
+                wCommand:WORD,                  \\r
+                vfpPalette:DWORD = ARG_SIZE\r
+        LOCAL   bSPalette:BYTE:MAXCOLOR*3,      \\r
+                bDPalette:BYTE:MAXCOLOR*3,      \\r
+                bLoopIndex:BYTE,                \\r
+                bLoopStep:BYTE,                 \\r
+                bLoopCount:BYTE,                \\r
+                wDelay:WORD,                    \\r
+                wSpeed:WORD     = AUTO_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  AUTO_SIZE\r
+        .push   si, di, ds, es                  ; Save registers\r
+;\r
+; Check parameters and setup variables\r
+;\r
+@@GetDelay:\r
+        mov     [wDelay], FADE_DELAY            ; Set default delay\r
+        mov     ax, [wCommand]                  ; Get command word\r
+        and     ax, MASK fpDELAY                ; Mask delay command\r
+        jz      @@GetSpeed                      ; No command, get speed\r
+    IF USE286 EQ TRUE\r
+        shr     ax, fpDELAY\r
+    ELSE\r
+        mov     cl, fpDELAY                     ; Get size of delay field\r
+        shr     ax, cl                          ; Right justify the field\r
+    ENDIF\r
+        mov     [wDelay], ax                    ; Set new delay\r
+\r
+@@GetSpeed:\r
+        mov     ax, [wCommand]                  ; Get command\r
+        and     ax, MASK fpSPEED                ; Mask speed\r
+    IF USE286 EQ TRUE\r
+        shr     ax, fpSPEED\r
+    ELSE\r
+        mov     cl, fpSPEED                     ; Get size of speed field\r
+        shr     ax, cl                          ; Right justify the field\r
+    ENDIF\r
+        or      ax, ax                          ; Any speed specified?\r
+        jnz     @@SetVariables                  ; Yes, set variables\r
+        mov     ax, FADE_SPEED                  ; Set default speed\r
+\r
+@@SetVariables:\r
+        mov     [wSpeed], ax                    ; Set speed\r
+        inc     ax                              ; Number of iterations\r
+        mov     [bLoopCount], al                ; Set loop count\r
+        mov     [bLoopStep], 1                  ; Assume we're fading in\r
+        mov     [bLoopIndex], 0\r
+;\r
+; Check bounds for bad values\r
+;\r
+        mov     ax, [wStartIdx]                 ; Get first index\r
+        cmp     ax, MAXCOLOR                    ; Is in the valid range?\r
+        jae     @@Exit                          ; No, exit\r
+        add     ax, [wCount]                    ; Get last index\r
+        cmp     ax, MAXCOLOR                    ; Is in the valid range?\r
+        jbe     @@BoundsOk                      ; Yes, continue\r
+        mov     ax, MAXCOLOR\r
+        sub     ax, [wStartIdx]\r
+        mov     [wCount], ax                    ; Set count to maximum value\r
+        or      ax, ax\r
+        jz      @@Exit                          ; Nothing to do, exit\r
+@@BoundsOk:\r
+;\r
+; Copy the source palette in a local array: if we fade in it's ready to\r
+; use, otherwise we'll overwrite it later\r
+;\r
+        mov     cx, [wCount]\r
+        mov     ax, cx\r
+        shl     ax, 1\r
+        add     cx, ax                          ; CX = wCount * 3\r
+        mov     ax, ss\r
+        mov     es, ax\r
+        lea     di, [bSPalette]                 ; ES:DI points to local palette\r
+        mov     ax, [wStartIdx]\r
+        mov     si, ax\r
+        shl     ax, 1\r
+        add     ax, si\r
+        lds     si, [vfpPalette]                ; DS:SI points to user palette\r
+        add     si, ax                          ; Skip unused entries\r
+        cld\r
+        shr     cx, 1\r
+        rep     movsw\r
+        rcl     cx, 1\r
+        rep     movsb\r
+;\r
+; Check direction\r
+;\r
+        test    [wCommand], MASK fpDIRECTION    ; Are we fading in?\r
+        jz      @@Main                          ; Yes, ok to continue\r
+        mov     ax, [wSpeed]                    ; Get speed\r
+        mov     [bLoopIndex], al                ; Exchange first and last index\r
+        mov     [bLoopStep], -1                 ; Move backward\r
+        mov     ax, ss                          ; Overwrite our copy of\r
+        mov     ds, ax                          ; user palette with the\r
+        mov     es, ax                          ; current active palette\r
+        lea     di, [bSPalette]\r
+        mov     ax, [wStartIdx]\r
+        mov     cx, [wCount]\r
+        call    ReadPalette                     ; Read current palette\r
+;\r
+; Prepare variables and registers for fading\r
+;\r
+@@Main:\r
+        mov     bh, BYTE PTR [bRed]             ; Destination red\r
+        and     bh, 00111111b                   ; Be sure it's a valid VGA value\r
+        mov     bl, BYTE PTR [bGreen]           ; Destination green\r
+        and     bl, 00111111b                   ; Be sure it's a valid VGA value\r
+        mov     dh, BYTE PTR [bBlue]            ; Destination blue\r
+        and     dh, 00111111b                   ; Be sure it's a valid VGA value\r
+        mov     dl, [bLoopIndex]                ; Loop index\r
+        mov     ax, ss                          ; All tables are stored\r
+        mov     ds, ax                          ; in the stack segment,\r
+        mov     es, ax                          ; set DS and ES\r
+;\r
+; Main loop\r
+;\r
+@@Loop:\r
+        mov     ax, [wCount]                    ; Store count in AX\r
+        mov     cx, [wSpeed]                    ; Set maximum speed in CX\r
+        lea     si, [bSPalette]                 ; DS:SI points to source palette\r
+        lea     di, [bDPalette]                 ; ES:DI points to dest. palette\r
+        call    RecalcPalette                   ; Build a faded palette\r
+\r
+        .push   bx, dx                          ; Save registers we need\r
+        lea     si, [bDPalette]                 ; DS:SI points to palette\r
+        mov     ax, [wStartIdx]                 ; First index to write\r
+        mov     bx, [wCount]                    ; Total entries to write\r
+        mov     cx, [wDelay]                    ; Fade delay between updates\r
+        call    WritePalette                    ; Write palette\r
+        .pop    bx, dx                          ; Restore BX and DX\r
+\r
+        add     dl, [bLoopStep]                 ; Change fade intensity\r
+        dec     [bLoopCount]                    ; Done?\r
+        jnz     @@Loop                          ; No, loop again\r
+\r
+@@Exit:\r
+        .pop    si, di, ds, es                  ; Restore registers\r
+        .leave  ARG_SIZE\r
+mxFadePalette   ENDP\r
+\r
+;------- INTERNAL USE ONLY ------------------------------------------------\r
+;\r
+; Calculates a partially faded palette.\r
+;\r
+; Input:\r
+;       AX      = number of entries in palette\r
+;       CX      = maximum fade intensity (same as fade speed)\r
+;       DS:SI   = pointer to source palette\r
+;       ES:DI   = pointer to destination palette\r
+;       BH      = destination red\r
+;       BL      = destination green\r
+;       DH      = destination blue\r
+;       DL      = relative intensity of destination palette\r
+; Note:\r
+;       it's important that a new palette can be calculated in less\r
+;       than 1/70th of second. Fading to any RGB value requires use\r
+;       of "imul" instructions: "idiv" may be replaced with faster\r
+;       "sar", but only when the number of passes is a power of two,\r
+;       thus reducing the range of selectable speeds.\r
+;       In both cases an extimate of CPU cycles required by this\r
+;       procedure shows that it's too slow to run on a 4.77 Mhz 8086\r
+;       CPU and a 256 color palette, so we keep "idiv" and hope\r
+;       the target machine to be at least a 6 Mhz 80286 (that's not\r
+;       asking too much...).\r
+;\r
+RecalcPalette   PROC NEAR\r
+        cld\r
+        push    bp                              ; Save BP\r
+        mov     bp, ax                          ; Copy counter in BP\r
+@@Loop:\r
+        lodsb                                   ; Red: read value\r
+        sub     al, bh                          ; Subtract destination value\r
+        imul    dl                              ; Scale to desired weight\r
+        idiv    cl                              ; Put value in AL\r
+        add     al, bh                          ; Add destination value...\r
+        stosb                                   ; ...and store it\r
+        lodsb                                   ; Green: read value\r
+        sub     al, bl                          ; Subtract destination value\r
+        imul    dl                              ; Scale to desired weight\r
+        idiv    cl                              ; Put value in AL\r
+        add     al, bl                          ; Add destination value...\r
+        stosb                                   ; ...and store it\r
+        lodsb                                   ; Blue: read value\r
+        sub     al, dh                          ; Subtract destination value\r
+        imul    dl                              ; Scale to desired weight\r
+        idiv    cl                              ; Put value in AL\r
+        add     al, dh                          ; Add destination value...\r
+        stosb                                   ; ...and store it\r
+        dec     bp\r
+        jnz     @@Loop\r
+        pop     bp                              ; Restore BP\r
+        ret\r
+RecalcPalette   ENDP\r
+\r
+;------- INTERNAL USE ONLY ------------------------------------------------\r
+;\r
+; Writes a 256 color palette.\r
+;\r
+; Input:\r
+;       AX      = index of first color to write\r
+;       BX      = number of colors to write (each color is an RGB triplet)\r
+;       CX      = number of vertical retraces to wait before writing to DACs\r
+;       DS:SI   = pointer to first entry of palette\r
+;\r
+WritePalette    PROC NEAR\r
+        ASSUME  ds:NOTHING\r
+        mov     ah, al                          ; Save index\r
+        mov     dx, 03DAh                       ; Input status register\r
+@@Delay1:\r
+        in      al, dx\r
+        test    al, 08h\r
+        jnz     @@Delay1                        ; Wait for display mode\r
+@@Delay2:\r
+        in      al, dx\r
+        test    al, 08h\r
+        jz      @@Delay2                        ; Wait for vertical retrace mode\r
+        loop    @@Delay1                        ; Repeat CX times\r
+@@Write:\r
+        mov     cx, bx                          ; Get number of colors\r
+        mov     dx, 03C8h                       ; PEL write address register\r
+        mov     al, ah                          ; Restore index\r
+        out     dx, al                          ; Select index of first color\r
+        inc     dx                              ; PEL data register\r
+        cld                                     ; Move forward\r
+        cli                                     ; Disable interrupts\r
+@@Loop:\r
+        lodsb\r
+        out     dx, al                          ; Red\r
+        lodsb\r
+        out     dx, al                          ; Green\r
+        lodsb\r
+        out     dx, al                          ; Blue\r
+        loop    @@Loop                          ; Loop until done\r
+        sti                                     ; Enable interrupts\r
+        ret\r
+WritePalette    ENDP\r
+\r
+;------- INTERNAL USE ONLY ------------------------------------------------\r
+;\r
+; Reads the current palette.\r
+;\r
+; Input:\r
+;       AX      = index of first color to read\r
+;       CX      = number of colors\r
+;       ES:DI   = pointer to destination buffer\r
+;\r
+ReadPalette     PROC    NEAR\r
+        mov     dx, 03C7h\r
+        out     dx, al\r
+        inc     dx\r
+        inc     dx\r
+        cld\r
+@@Loop:\r
+        in      al, dx\r
+        stosb\r
+        in      al, dx\r
+        stosb\r
+        in      al, dx\r
+        stosb\r
+        loop    @@Loop\r
+        ret\r
+ReadPalette     ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxgc.asm b/16/x/mxgc.asm
new file mode 100755 (executable)
index 0000000..85edf7a
--- /dev/null
@@ -0,0 +1,54 @@
+;-----------------------------------------------------------\r
+;\r
+; MXGC.ASM - Get color function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxGetColor\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current setting of the selected DAC register.\r
+;\r
+; Input:\r
+;       Index   = color index (0-255)\r
+;       R, G, B = byte pointers to red, green and blue\r
+; Output:\r
+;       none\r
+;\r
+mxGetColor      PROC FAR\r
+        ARG     B:DWORD,        \\r
+                G:DWORD,        \\r
+                R:DWORD,        \\r
+                Index:WORD      = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+\r
+        mov     ax, [Index]\r
+        mov     dx, 3C7h                ; PEL read address register\r
+        out     dx, al\r
+        inc     dx\r
+        inc     dx\r
+\r
+        lds     si, [R]\r
+        in      al, dx\r
+        mov     ds:[si], al\r
+        lds     si, [G]\r
+        in      al, dx\r
+        mov     ds:[si], al\r
+        lds     si, [B]\r
+        in      al, dx\r
+        mov     ds:[si], al\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetColor      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxgi.asm b/16/x/mxgi.asm
new file mode 100755 (executable)
index 0000000..7037d41
--- /dev/null
@@ -0,0 +1,132 @@
+;-----------------------------------------------------------\r
+;\r
+; MXGI.ASM - Get image\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxGetImage\r
+\r
+EXTRN   subClipImage            : NEAR\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies an image from screen to memory.\r
+;\r
+; Input:\r
+;       Image   = pointer to buffer for image\r
+;       X, Y    = coordinates of image on screen\r
+;       Width   = width of image in pixels\r
+;       Height  = height of image in pixels\r
+; Output:\r
+;       none\r
+;\r
+mxGetImage      PROC    FAR\r
+        ARG     Height:WORD,            \\r
+                Width:WORD,             \\r
+                Y:WORD,                 \\r
+                X:WORD,                 \\r
+                Image:DWORD             = ARG_SIZE\r
+        LOCAL   PlaneWidth:WORD:4,      \\r
+                PixelOffset:WORD,       \\r
+                MoveFunction:WORD,      \\r
+                ReadPlane:BYTE,         \\r
+                Count:BYTE              = AUTO_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+\r
+; Clip image\r
+        mov     bx, [X]\r
+        mov     ax, [Y]\r
+        mov     cx, [Width]\r
+        mov     dx, [Height]\r
+        call    subClipImage\r
+        jc      @@Exit                  ; Full clipped\r
+        mov     [Height], dx\r
+        add     WORD PTR Image[0], si   ; Skip clipped pixels\r
+\r
+; Get pixel address\r
+        mul     [mx_BytesPerLine]\r
+        mov     si, bx\r
+        shr     si, 1\r
+        shr     si, 1\r
+        add     si, ax\r
+        mov     [PixelOffset], si\r
+        mov     ds, [mx_VideoSegment]   ; DS:SI points to pixel\r
+        and     bl, 03h\r
+        mov     [ReadPlane], bl\r
+\r
+; Compute extra bytes and width count for each plane\r
+        mov     bx, cx\r
+        shr     bx, 1\r
+        shr     bx, 1                   ; Width for each plane\r
+        and     cl, 03h\r
+        mov     al, 00001000b\r
+        shr     al, cl\r
+        mov     di, 3 SHL 1\r
+@@PatchLoop:\r
+        mov     PlaneWidth[di], bx\r
+        shr     al, 1\r
+        adc     bx, 0\r
+        dec     di\r
+        dec     di\r
+        jge     @@PatchLoop\r
+\r
+; Get image\r
+        cld\r
+        mov     [Count], 4              ; Four planes\r
+        lea     bx, PlaneWidth          ; SS:[BX] = width in bytes for plane\r
+        mov     es, WORD PTR Image[2]   ; ES:DI will point to image\r
+        mov     ah, [ReadPlane]\r
+@@PlaneLoop:\r
+        cmp     WORD PTR ss:[bx], 0     ; Exit if nothing more to do\r
+        je      @@Exit                  ; (also, never try to move zero bytes!)\r
+        mov     di, WORD PTR Image[0]\r
+        mov     al, 04h\r
+        mov     dx, GDC\r
+        out     dx, ax                  ; Select read plane\r
+        mov     dx, [Height]\r
+        mov     si, [PixelOffset]       ; DS:SI points to video memory\r
+@@Loop:\r
+        .push   si, di\r
+        mov     cx, WORD PTR ss:[bx]    ; Number of bytes to move\r
+@@MoveLoop:\r
+        movsb\r
+        add     di, 3\r
+        dec     cx\r
+        jnz     @@MoveLoop\r
+        .pop    si, di\r
+        add     di, [Width]             ; Go to next image line\r
+        add     si, [mx_BytesPerLine]   ; Go to next screen row\r
+        dec     dx\r
+        jnz     @@Loop                  ; Repeat for all lines\r
+        inc     bx\r
+        inc     bx                      ; Select width for next plane\r
+        inc     ah\r
+        test    ah, 04h                 ; Plane wraparound?\r
+        jz      @@PlaneOk               ; No\r
+        inc     [PixelOffset]           ; Yes, bump video pointer\r
+        and     ah, 03h\r
+@@PlaneOk:\r
+        inc     WORD PTR Image[0]\r
+        dec     [Count]\r
+        jnz     @@PlaneLoop             ; Repeat for all planes\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxGetImage      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxgm.asm b/16/x/mxgm.asm
new file mode 100755 (executable)
index 0000000..a67476a
--- /dev/null
@@ -0,0 +1,63 @@
+;-----------------------------------------------------------\r
+;\r
+; MXGM.ASM - Gamma correction\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxGammaCorrect\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+mx_tblGamma     LABEL BYTE\r
+    DB  00, 10, 14, 17, 19, 21, 23, 24, 26, 27, 28, 29, 31, 32, 33, 34\r
+    DB  35, 36, 37, 37, 38, 39, 40, 41, 41, 42, 43, 44, 44, 45, 46, 46\r
+    DB  47, 48, 48, 49, 49, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55\r
+    DB  56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Correct palette colors (gamma is 2.3).\r
+;\r
+; Input:\r
+;       CPal    = pointer to color palette\r
+;       GPal    = pointer to destination (gamma corrected) palette\r
+;       Count   = number of colors to convert\r
+; Output:\r
+;       none\r
+;\r
+; Note: CPal and GPal may point to the same buffer.\r
+;\r
+mxGammaCorrect  PROC    FAR\r
+        ARG     Count:WORD,     \\r
+                DPal:DWORD,     \\r
+                SPal:DWORD      = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si, es, di\r
+\r
+        mov     cx, [Count]\r
+        jcxz    @@Exit                  ; Exit now if nothing to do\r
+        lds     si, [SPal]\r
+        les     di, [DPal]\r
+        mov     bx, OFFSET mx_tblGamma  ; Setup BX for XLAT instruction\r
+        cld\r
+        mov     ax, cx                  ; AX = Count\r
+        add     cx, cx                  ; CX = Count*2\r
+        add     cx, ax                  ; CX = Count*3\r
+@@Loop:\r
+        lodsb\r
+        xlat    mx_tblGamma\r
+        stosb\r
+        loop    @@Loop\r
+\r
+@@Exit:\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxGammaCorrect  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxgp.asm b/16/x/mxgp.asm
new file mode 100755 (executable)
index 0000000..6c14317
--- /dev/null
@@ -0,0 +1,56 @@
+;-----------------------------------------------------------\r
+;\r
+; MXGP.ASM - Get palette function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxGetPalette\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current setting of the VGA palette.\r
+;\r
+; Input:\r
+;       Buffer          = pointer to palette data (R,G,B)\r
+;       Start           = index of first color to get\r
+;       Count           = number of color to get\r
+; Output:\r
+;       none\r
+;\r
+mxGetPalette    PROC    FAR\r
+        ARG     Count:WORD,             \\r
+                Start:WORD,             \\r
+                Buffer:DWORD            = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   es, di\r
+\r
+        les     di, [Buffer]\r
+        mov     cx, [Count]\r
+        mov     ax, [Start]\r
+        mov     dx, 3C7h                ; PEL read address register\r
+        out     dx, al\r
+        inc     dx\r
+        inc     dx\r
+        cld\r
+@@Loop:\r
+        in      al, dx\r
+        stosb\r
+        in      al, dx\r
+        stosb\r
+        in      al, dx\r
+        stosb\r
+        loop    @@Loop                  ; Loop until done\r
+\r
+        .pop    es, di\r
+        .leave  ARG_SIZE\r
+mxGetPalette    ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxgv.asm b/16/x/mxgv.asm
new file mode 100755 (executable)
index 0000000..2a54b1d
--- /dev/null
@@ -0,0 +1,25 @@
+;-----------------------------------------------------------\r
+;\r
+; MXGV.ASM - Get version function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxGetVersion\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the library version.\r
+;\r
+mxGetVersion    PROC    FAR\r
+        mov     ax, MXVERSION\r
+        ret\r
+mxGetVersion    ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxhl.asm b/16/x/mxhl.asm
new file mode 100755 (executable)
index 0000000..049a056
--- /dev/null
@@ -0,0 +1,76 @@
+;-----------------------------------------------------------\r
+;\r
+; MXHL.ASM - Horizontal line mask utility\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  subHorizontalLineInfo\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+tblLeftSize     DW      00h, 03h, 02h, 01h\r
+tblLeftMask     DB      00h, 0Eh, 0Ch, 08h\r
+tblRightMask    DB      00h, 01h, 03h, 07h\r
+tblPatchMask    DB      02h, 06h\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Prepares register for fast horizontal line drawing.\r
+;\r
+; Input:\r
+;       BX, AX  = X, Y address of left pixel\r
+;       CX      = line width\r
+; Output:\r
+;       DI      = left pixel offset in video memory\r
+;       AL      = left block write plane mask (0 = none)\r
+;       AH      = right block write plane mask (0 = none)\r
+;       CX      = center block width in 4-pixel blocks\r
+;\r
+subHorizontalLineInfo   PROC NEAR\r
+        ASSUME  ds:NOTHING\r
+\r
+        mul     [mx_BytesPerLine]\r
+        mov     di, bx\r
+        shr     di, 1\r
+        shr     di, 1\r
+        add     di, ax                  ; Offset of left pixel\r
+\r
+        and     bx, 03h\r
+        mov     al, tblLeftMask[bx]\r
+        shl     bx, 1\r
+        sub     cx, tblLeftSize[bx]\r
+        jge     @@1                     ; Ok to continue\r
+\r
+; Special case: start and end in the middle of a 4-pixel block.\r
+; There are only three cases:\r
+;    Pixels     Left mask       CX      CX+2    Patch mask      Result\r
+; 1)  ..o.        ..xx          -1      1       .xx.            ..x.\r
+; 2)  .oo.        .xxx          -1      1       .xx.            .xx.\r
+; 3)  .o..        .xxx          -2      0       .x..            .x..\r
+; All other cases are automatically handled with the standard masks.\r
+        mov     bx, cx\r
+        inc     bx\r
+        inc     bx\r
+        and     al, tblPatchMask[bx]    ; Combine masks\r
+        xor     ah, ah                  ; No right block\r
+        xor     cx, cx                  ; No center block\r
+        jmp     @@Exit\r
+\r
+@@1:\r
+        mov     bx, cx\r
+        and     bx, 03h\r
+        mov     ah, tblRightMask[bx]\r
+        shr     cx, 2\r
+\r
+@@Exit:\r
+        ret\r
+subHorizontalLineInfo   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxit.asm b/16/x/mxit.asm
new file mode 100755 (executable)
index 0000000..c0d9ced
--- /dev/null
@@ -0,0 +1,98 @@
+;-----------------------------------------------------------\r
+;\r
+; MXIT.ASM - Initialization/termination functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxInit\r
+PUBLIC  mxTerm\r
+\r
+PUBLIC  mx_VideoSegment\r
+PUBLIC  mx_CodeSegment\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+DB      'MODEX library - Copyright (c) 1992-1994 Alessandro Scotti'\r
+\r
+mx_VideoSegment DW      0A000h\r
+mx_CodeSegment  DW      SEG MX_TEXT\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Initialization.\r
+;\r
+; Input:\r
+;       none\r
+; Output:\r
+;       AX      = 0 on success\r
+;\r
+mxInit  PROC FAR\r
+        LOCAL   Result:WORD,            \\r
+                VideoSeg:WORD,          \\r
+                CStoDSalias:WORD        = AUTO_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+\r
+        mov     [Result], -1            ; Assume an error\r
+        mov     [VideoSeg], 0A000h      ; Real mode video segment\r
+        mov     [CStoDSalias], cs       ; Real mode data alias for CS\r
+\r
+; Check if running in protected mode under DPMI\r
+        mov     ax, 1686h\r
+        int     2Fh\r
+        or      ax, ax\r
+         jnz    @@1                     ; DPMI not found, continue in real mode\r
+\r
+; Get a data alias for CS\r
+        mov     ax, 000Ah               ; DMPI: create data alias\r
+        mov     bx, cs\r
+        int     31h\r
+         jc     @@Exit                  ; Exit if service failed\r
+        mov     [CStoDSalias], ax       ; Save data alias for CS\r
+; Get a protected-mode selector for the video segment\r
+        mov     ax, 0002h\r
+        mov     bx, 0A000h              ; Real mode segment of video\r
+        int     31h                     ; DPMI: get segment selector\r
+         jc     @@Exit                  ; Exit if service failed\r
+        mov     [VideoSeg], ax          ; Save protected mode video selector\r
+\r
+; Initialize variables\r
+@@1:\r
+        mov     ds, [CStoDSalias]\r
+        ASSUME  ds:MX_TEXT\r
+        mov     [mx_CodeSegment], ds\r
+        mov     ax, [VideoSeg]\r
+        mov     [mx_VideoSegment], ax\r
+\r
+; Don't bother with VGA check for now...\r
+\r
+        mov     [Result], 0\r
+\r
+@@Exit:\r
+        mov     ax, [Result]\r
+        .pop    ds, si, es, di\r
+        .leave\r
+mxInit  ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Termination.\r
+;\r
+; Input:\r
+;       none\r
+; Output:\r
+;       always 0.\r
+;\r
+mxTerm  PROC FAR\r
+        ASSUME  ds:NOTHING\r
+        xor     ax, ax\r
+        ret\r
+mxTerm  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxll.asm b/16/x/mxll.asm
new file mode 100755 (executable)
index 0000000..34fec04
--- /dev/null
@@ -0,0 +1,82 @@
+;-----------------------------------------------------------\r
+;\r
+; MXLL.ASM - Load latches\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxLoadLatches\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Loads the specified value into the VGA latches.\r
+;\r
+; Input:\r
+;       BL      = value to load into latches\r
+; Output:\r
+;       none\r
+; Changes:\r
+;       bit mask register to FFh;\r
+;       function select register to "move";\r
+;       write mode to 00h.\r
+; Note:\r
+;       this is for internal use only.\r
+;\r
+mxLoadLatches   PROC    NEAR\r
+        ASSUME  ds:NOTHING\r
+\r
+        .push   ds, si\r
+        mov     dx, GDC\r
+        mov     ax, 0FF08h\r
+        out     dx, ax                  ; Set bit mask to FFh\r
+        mov     ax, 0003h\r
+        out     dx, ax                  ; Set function to "move"\r
+        mov     ax, 0005h\r
+        out     dx, ax                  ; Set write mode\r
+        mov     ax, [mx_VideoSegment]\r
+        mov     ds, ax\r
+        mov     si, 0FFFFh\r
+        mov     bh, 8                   ; BH = write plane mask\r
+        mov     cx, 3                   ; CX = count = read plane\r
+; Saves old values and force BL into latches\r
+@@SetLoop:\r
+        mov     dx, GDC\r
+        mov     al, 04h\r
+        mov     ah, cl\r
+        out     dx, ax                  ; Select read plane\r
+        mov     dx, TS\r
+        mov     al, 02h\r
+        mov     ah, bh\r
+        out     dx, ax                  ; Select write plane\r
+        mov     al, ds:[si]\r
+        push    ax\r
+        mov     ds:[si], bl\r
+        mov     al, ds:[di]             ; Force value into latch\r
+        shr     bh, 1                   ; Next write plane\r
+        loop    @@SetLoop\r
+; Restore previous values\r
+        mov     cx, 3\r
+        mov     bh, 8\r
+        mov     dx, TS\r
+@@ResetLoop:\r
+        mov     al, 02h\r
+        mov     ah, bh\r
+        out     dx, ax                  ; Select write plane\r
+        pop     ax\r
+        mov     ds:[si], al\r
+        shr     bh, 1                   ; Next write plane\r
+        loop    @@ResetLoop\r
+; Exit\r
+        .pop    ds, si\r
+        ret\r
+mxLoadLatches   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxln.asm b/16/x/mxln.asm
new file mode 100755 (executable)
index 0000000..fbc4ab9
--- /dev/null
@@ -0,0 +1,414 @@
+;-----------------------------------------------------------\r
+;\r
+; MXLN.ASM - Line function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+        ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_VideoSegment : WORD\r
+\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+\r
+tblDrawFunc     LABEL   WORD\r
+        DW      subWidthMove\r
+        DW      subHeightMove\r
+        DW      subWidthOp\r
+        DW      subHeightOp\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Draws a line from (X1,Y1) to (X2,Y2) using the Bresenham\r
+; algorithm.\r
+;\r
+; Input:\r
+;       X1, Y1  = start point\r
+;       X2, Y2  = end point\r
+;       Color   = line color\r
+;       Op      = raster operator\r
+; Output:\r
+;       none\r
+;\r
+; Note: the end point (X2,Y2) *IS* drawed. I don't like this very much\r
+; but clipping is much simpler.\r
+;\r
+mxLine  PROC FAR\r
+        ARG     Op:WORD,        \\r
+                Color:WORD,     \\r
+                Y2:WORD,        \\r
+                X2:WORD,        \\r
+                Y1:WORD,        \\r
+                X1:WORD         = ARG_SIZE\r
+        LOCAL   Width:WORD,     \\r
+                Height:WORD,    \\r
+                ErrorAdd:WORD,  \\r
+                ErrorSub:WORD,  \\r
+                DeltaX:WORD,    \\r
+                DeltaY:WORD,    \\r
+                P1:BYTE,        \\r
+                P2:BYTE,        \\r
+                WritePlane:BYTE = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, di\r
+        ASSUME  ds:NOTHING\r
+\r
+        mov     ax, [X1]\r
+        mov     bx, [Y1]\r
+        mov     cx, [X2]\r
+        mov     dx, [Y2]\r
+        call    subClipLine\r
+        jc      @@Exit                  ; Line is full clipped\r
+\r
+; Get width\r
+        mov     si, cx\r
+        xchg    ax, si                  ; SI = X1, AX = X2\r
+        sub     ax, si\r
+        jge     @@1\r
+; Swap points, we want X1 < X2\r
+        xchg    si, cx                  ; Swap X1 and X2\r
+        xchg    bx, dx                  ; Swap Y1 and Y2\r
+        neg     ax\r
+@@1:\r
+        mov     [Width], ax\r
+\r
+; Get height\r
+        mov     cx, [mx_BytesPerLine]   ; We don't need X2 anymore\r
+        mov     ax, dx\r
+        sub     ax, bx\r
+        jge     @@2\r
+        neg     cx                      ; Move from bottom to top\r
+        neg     ax                      ; Get absolute value of AX\r
+@@2:\r
+        mov     [Height], ax\r
+        mov     [DeltaY], cx\r
+\r
+; Get pixel address and write plane\r
+        mov     ax, bx\r
+        mul     [mx_BytesPerLine]\r
+        mov     cx, si                  ; CX = X1\r
+        shr     si, 1\r
+        shr     si, 1\r
+        add     si, ax                  ; SI = pixel offset\r
+        and     cl, 03h\r
+        mov     ax, 1102h\r
+        shl     ah, cl\r
+        mov     [WritePlane], ah\r
+        mov     dx, TS\r
+        out     dx, ax                  ; Set write plane\r
+        mov     ax, [mx_VideoSegment]\r
+        mov     ds, ax                  ; DS:SI points to (X1,Y1)\r
+\r
+; Select the function to handle the drawing loop\r
+        xor     bx, bx\r
+        mov     al, BYTE PTR [Op]\r
+        cmp     al, OP_MOVE\r
+        je      @@3\r
+        and     al, 03h\r
+        shl     al, 1\r
+        shl     al, 1\r
+        shl     al, 1\r
+        mov     ah, al\r
+        mov     al, 03h\r
+        mov     dx, GDC\r
+        out     dx, ax                  ; Set logical function\r
+        inc     bx\r
+        inc     bx\r
+@@3:\r
+        mov     ax, [Width]\r
+        mov     cx, [Height]\r
+; Horizontal, vertical and diagonal lines are not optimized yet\r
+        cmp     ax, cx\r
+        jae     @@4\r
+        inc     bx\r
+@@4:\r
+        shl     bx, 1\r
+        call    tblDrawFunc[bx]\r
+\r
+; Reset logical function if needed\r
+        cmp     BYTE PTR [Op], OP_MOVE\r
+        je      @@Exit\r
+        mov     ax, 0003h\r
+        mov     dx, GDC\r
+        out     dx, ax\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, di\r
+        .leave  ARG_SIZE\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Checks the coordinates of a line against the active\r
+; clip region.\r
+; Uses a variation of the Cohen-Sutherland algorithm developed\r
+; by Victor Duvanenko.\r
+;\r
+; Input:\r
+;       AX, BX  = X1, Y1\r
+;       CX, DX  = X2, Y2\r
+; Output:\r
+;       CF      = set if line is full clipped\r
+;       AX, BX  = clipped X1, Y1\r
+;       CX, DX  = clipped X2, Y2\r
+; Note:\r
+;       destroys SI, DI\r
+;\r
+subClipLine     PROC    NEAR\r
+        mov     di, ax                  ; Copy X1 to DI and free AX\r
+        mov     si, dx                  ; Copy Y2 to SI and free DX\r
+; Compute clip codes for point (X2,Y2)=(CX,SI)\r
+        xor     al, al\r
+@@P2X1: cmp     cx, [mx_ClipX1]\r
+        jge     @@P2X2\r
+        or      al, 1\r
+@@P2X2: cmp     cx, [mx_ClipX2]\r
+        jle     @@P2Y1\r
+        or      al, 2\r
+@@P2Y1: cmp     si, [mx_ClipY1]\r
+        jge     @@P2Y2\r
+        or      al, 4\r
+@@P2Y2: cmp     si, [mx_ClipY2]\r
+        jle     @@P2XY\r
+        or      al, 8\r
+@@P2XY: mov     [P2], al\r
+; Compute clip codes for point (X1,Y1)=(DI,BX)\r
+        xor     al, al\r
+@@P1X1: cmp     di, [mx_ClipX1]\r
+        jge     @@P1X2\r
+        or      al, 1\r
+@@P1X2: cmp     di, [mx_ClipX2]\r
+        jle     @@P1Y1\r
+        or      al, 2\r
+@@P1Y1: cmp     bx, [mx_ClipY1]\r
+        jge     @@P1Y2\r
+        or      al, 4\r
+@@P1Y2: cmp     bx, [mx_ClipY2]\r
+        jle     @@P1XY\r
+        or      al, 8\r
+@@P1XY: mov     [P1], al\r
+; Check codes for trivial cases\r
+        mov     ah, [P2]\r
+        test    al, ah                  ; Is line invisible?\r
+        jnz     @@FullClip              ; Yes, exit\r
+        or      ah, al                  ; Both points clipped?\r
+        jz      @@Done                  ; Yes, exit\r
+; Calculate deltas\r
+        mov     ax, cx\r
+        sub     ax, di\r
+        mov     [DeltaX], ax\r
+        mov     ax, si\r
+        sub     ax, bx\r
+        mov     [DeltaY], ax\r
+        mov     al, [P1]                ; Init clipping code\r
+; Clipping loop\r
+@@ClipLoop:\r
+        test    al, al                  ; Is first point clipped?\r
+        jnz     @@ClipX1                ; No, continue\r
+        xchg    cx, di                  ; Swap points...\r
+        xchg    bx, si\r
+        xchg    al, [P2]                ; ...and codes\r
+; Clip left: Y1 = Y1 + DeltaY*(mx_ClipX1-X1)/DeltaX\r
+@@ClipX1:\r
+        test    al, 1\r
+        jz      @@ClipX2\r
+        mov     ax, [mx_ClipX1]\r
+        sub     ax, di\r
+        mov     di, [mx_ClipX1]\r
+        jmp     @@ClipX1X2\r
+; Clip right: Y1 = Y1 + DeltaY*(mx_ClipX2-X1)/DeltaX\r
+@@ClipX2:\r
+        test    al, 2\r
+        jz      @@ClipY1\r
+        mov     ax, [mx_ClipX2]\r
+        sub     ax, di\r
+        mov     di, [mx_ClipX2]\r
+@@ClipX1X2:\r
+        imul    [DeltaY]\r
+        idiv    [DeltaX]\r
+        add     bx, ax\r
+        mov     al, 8\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      @@CheckLoop\r
+        mov     al, 4\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      @@CheckLoop\r
+        xor     al, al\r
+        jmp     @@CheckLoop\r
+; Clip top: X1 = X1 + DeltaX*(mx_ClipY1-Y1)/DeltaY\r
+@@ClipY1:\r
+        test    al, 4\r
+        jz      @@ClipY2\r
+        mov     ax, [mx_ClipY1]\r
+        sub     ax, bx\r
+        mov     bx, [mx_ClipY1]\r
+        jmp     @@ClipY1Y2\r
+; Clip bottom: X1 = X1 + DeltaX*(mx_ClipY2-Y1)/DeltaY\r
+@@ClipY2:\r
+        mov     ax, [mx_ClipY2]\r
+        sub     ax, bx\r
+        mov     bx, [mx_ClipY2]\r
+@@ClipY1Y2:\r
+        imul    [DeltaX]\r
+        idiv    [DeltaY]\r
+        add     di, ax\r
+        mov     al, 1\r
+        cmp     di, [mx_ClipX1]\r
+        jl      @@CheckLoop\r
+        mov     al, 2\r
+        cmp     di, [mx_ClipX2]\r
+        jg      @@CheckLoop\r
+        xor     al, al\r
+@@CheckLoop:\r
+        mov     ah, [P2]\r
+        test    al, ah\r
+        jnz     @@FullClip\r
+        or      ah, al\r
+        jnz     @@ClipLoop\r
+\r
+@@Done:\r
+        mov     ax, di\r
+        mov     dx, si\r
+        clc\r
+        ret\r
+@@FullClip:\r
+        stc\r
+        ret\r
+subClipLine     ENDP\r
+\r
+; Called when Width >= Height and Op = OP_MOVE\r
+subWidthMove    PROC NEAR\r
+        mov     di, ax\r
+        neg     di                      ; Initialize error term\r
+        shl     cx, 1\r
+        mov     [ErrorAdd], cx\r
+        mov     cx, ax\r
+        shl     ax, 1\r
+        mov     [ErrorSub], ax\r
+        mov     al, 02h\r
+        mov     ah, [WritePlane]\r
+        mov     bl, BYTE PTR [Color]\r
+        mov     dx, TS\r
+        inc     cx\r
+@@Loop:\r
+        mov     ds:[si], bl\r
+        dec     cx\r
+        jz      @@Exit\r
+        rol     ah, 1\r
+        adc     si, 0\r
+        out     dx, ax\r
+        add     di, [ErrorAdd]\r
+        jl      @@Loop\r
+        add     si, [DeltaY]\r
+        sub     di, [ErrorSub]\r
+        jmp     @@Loop\r
+@@Exit:\r
+        ret\r
+subWidthMove    ENDP\r
+\r
+; Called when Width < Height and Op = OP_MOVE\r
+subHeightMove   PROC NEAR\r
+        mov     di, cx\r
+        neg     di                      ; Initialize error term\r
+        shl     ax, 1\r
+        mov     [ErrorAdd], ax\r
+        mov     ax, cx\r
+        shl     ax, 1\r
+        mov     [ErrorSub], ax\r
+        mov     bl, BYTE PTR [Color]\r
+        mov     ah, [WritePlane]\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        inc     cx\r
+@@Loop:\r
+        mov     ds:[si], bl\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, [DeltaY]\r
+        add     di, [ErrorAdd]\r
+        jl      @@Loop\r
+        rol     ah, 1                   ; Next write plane\r
+        adc     si, 0                   ; Bump video offset if plane overflows\r
+        out     dx, ax\r
+        sub     di, [ErrorSub]          ; Adjust error down\r
+        jmp     @@Loop\r
+@@Exit:\r
+        ret\r
+subHeightMove   ENDP\r
+\r
+; Called when Width >= Height and Op <> OP_MOVE\r
+subWidthOp      PROC NEAR\r
+        mov     di, ax\r
+        neg     di                      ; Initialize error term\r
+        shl     cx, 1\r
+        mov     [ErrorAdd], cx\r
+        mov     cx, ax\r
+        shl     ax, 1\r
+        mov     [ErrorSub], ax\r
+        mov     al, 02h\r
+        mov     ah, [WritePlane]\r
+        mov     bl, BYTE PTR [Color]\r
+        mov     dx, TS\r
+        inc     cx\r
+@@Loop:\r
+        mov     bh, ds:[si]             ; Latch data\r
+        mov     ds:[si], bl\r
+        dec     cx\r
+        jz      @@Exit\r
+        rol     ah, 1\r
+        adc     si, 0\r
+        out     dx, ax\r
+        add     di, [ErrorAdd]\r
+        jl      @@Loop\r
+        add     si, [DeltaY]\r
+        sub     di, [ErrorSub]\r
+        jmp     @@Loop\r
+@@Exit:\r
+        ret\r
+subWidthOp      ENDP\r
+\r
+; Called when Width < Height and Op <> OP_MOVE\r
+subHeightOp     PROC NEAR\r
+        mov     di, cx\r
+        neg     di                      ; Initialize error term\r
+        shl     ax, 1\r
+        mov     [ErrorAdd], ax\r
+        mov     ax, cx\r
+        shl     ax, 1\r
+        mov     [ErrorSub], ax\r
+        mov     bl, BYTE PTR [Color]\r
+        mov     ah, [WritePlane]\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        inc     cx\r
+@@Loop:\r
+        mov     bh, ds:[si]\r
+        mov     ds:[si], bl\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, [DeltaY]\r
+        add     di, [ErrorAdd]\r
+        jl      @@Loop\r
+        rol     ah, 1                   ; Next write plane\r
+        adc     si, 0                   ; Bump video offset if plane overflows\r
+        out     dx, ax\r
+        sub     di, [ErrorSub]          ; Adjust error down\r
+        jmp     @@Loop\r
+@@Exit:\r
+        ret\r
+subHeightOp     ENDP\r
+\r
+mxLine  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxot.asm b/16/x/mxot.asm
new file mode 100755 (executable)
index 0000000..6254766
--- /dev/null
@@ -0,0 +1,330 @@
+;-----------------------------------------------------------\r
+;\r
+; MXOT.ASM - Text functions\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES                             ; We use the reserved name 'WIDTH'\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxOutChar\r
+PUBLIC  mxOutText\r
+PUBLIC  mxSetFont\r
+PUBLIC  mxSetTextColor\r
+PUBLIC  mxGetTextStep\r
+PUBLIC  mxSetTextStep\r
+\r
+MAX_WIDTH       EQU     16              ; Must be <= 16\r
+MAX_HEIGHT      EQU     32\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_CodeSegment  : WORD\r
+EXTRN   mxPutImage      : FAR\r
+\r
+; Default 8x8 font\r
+fnt_Default     LABEL\r
+        INCLUDE DEFAULT.FNT\r
+\r
+; Table of system fonts\r
+tbl_SystemFont   LABEL   WORD\r
+        DW      fnt_Default, 8, 8\r
+\r
+MX_MAXSYSFONT   EQU     ($-OFFSET tbl_SystemFont) SHR 2\r
+\r
+mx_FontPtr      DW      OFFSET fnt_Default, SEG MX_TEXT\r
+mx_FontWidth    DW      8               ; Font width in pixels\r
+mx_FontHeight   DW      8               ; Font height in pixels\r
+mx_FontCharSize DW      8               ; Size in bytes of a font character\r
+mx_FontColor    DW      00FFh           ; Color: foreground + background*256\r
+mx_FontOp       DW      OP_MOVE         ; Raster op\r
+mx_DeltaX       DW      8               ; Horizontal step\r
+mx_DeltaY       DW      0               ; Vertical step\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the current font.\r
+;\r
+; Input:\r
+;       Font    = pointer to font data\r
+;       Width   = width of font character in pixels\r
+;       Height  = height of font character in pixels\r
+; Output:\r
+;       AX = 0 on success, else invalid parameters\r
+;\r
+; Note: when the high word of Font (i.e. the segment) is zero, the low\r
+;       word is used to select one of the system fonts.\r
+;\r
+mxSetFont       PROC FAR\r
+        ARG     Height:WORD,    \\r
+                Width:WORD,     \\r
+                Font:DWORD      = ARG_SIZE\r
+        .enter  0\r
+        .push   ds\r
+\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, WORD PTR Font[2]    ; Get font segment\r
+        test    ax, ax                  ; Null segment?\r
+        jnz     @@UserFont              ; No, install user font\r
+\r
+; Install system font\r
+        mov     ax, WORD PTR Font[0]    ; Get font number\r
+        cmp     ax, MX_MAXSYSFONT       ; Check range\r
+        jb      @@SystemFont\r
+        xor     ax, ax                  ; Out of range, use default font\r
+@@SystemFont:\r
+        shl     ax, 1\r
+        shl     ax, 1\r
+        mov     bx, ax\r
+        mov     ax, tbl_SystemFont[bx]  ; Get font offset\r
+        mov     WORD PTR mx_FontPtr[0], ax\r
+        mov     WORD PTR mx_FontPtr[2], cs\r
+        mov     al, BYTE PTR tbl_SystemFont[bx+2]\r
+        xor     ah, ah\r
+        mov     [mx_FontWidth], ax\r
+        mov     [mx_DeltaX], ax\r
+        mov     dl, BYTE PTR tbl_SystemFont[bx+3]\r
+        xor     dh, dh\r
+        mov     [mx_FontHeight], dx\r
+        mul     dx\r
+        mov     [mx_FontCharSize], ax\r
+        mov     [mx_DeltaX], ax\r
+        xor     ax, ax\r
+        mov     [mx_DeltaY], ax\r
+        jmp     @@Exit\r
+\r
+; Install user font\r
+@@UserFont:\r
+        mov     ax, -1                  ; Assume an error\r
+        mov     bx, [Width]\r
+        cmp     bx, MAX_WIDTH\r
+        ja      @@Exit                  ; Invalid character width\r
+        mov     dx, [Height]\r
+        cmp     dx, MAX_HEIGHT\r
+        ja      @@Exit                  ; Invalid character height\r
+        mov     [mx_FontWidth], bx\r
+        mov     [mx_FontHeight], dx\r
+        mov     ax, bx\r
+        add     ax, 7\r
+        .shr    ax, 3\r
+        mul     dx\r
+        mov     [mx_FontCharSize], ax\r
+        mov     ax, WORD PTR Font[0]\r
+        mov     WORD PTR mx_FontPtr[0], ax\r
+        mov     ax, WORD PTR Font[2]\r
+        mov     WORD PTR mx_FontPtr[2], ax\r
+        xor     ax, ax\r
+\r
+@@Exit:\r
+        .pop    ds\r
+        ASSUME  ds:NOTHING\r
+        .leave  ARG_SIZE\r
+mxSetFont       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the text color and raster op.\r
+;\r
+; Input:\r
+;       Color   = text color (foreground + background*256)\r
+;       Op      = raster op\r
+; Output:\r
+;       none\r
+;\r
+mxSetTextColor  PROC FAR\r
+        ARG     Op:WORD,        \\r
+                Color:WORD      = ARG_SIZE\r
+        .enter  0\r
+        .push   ds\r
+\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, [Color]\r
+        mov     [mx_FontColor], ax\r
+        mov     ax, [Op]\r
+        mov     [mx_FontOp], ax\r
+\r
+        xor     ax, ax\r
+        .pop    ds\r
+        ASSUME  ds:NOTHING\r
+        .leave  ARG_SIZE\r
+mxSetTextColor  ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a character using the current font and attributes.\r
+;\r
+; Input:\r
+;       X, Y    = video coordinates\r
+;       C       = character to print\r
+; Output:\r
+;       none\r
+;\r
+mxOutChar       PROC FAR\r
+        ARG     C:BYTE:2,       \\r
+                Y:WORD,         \\r
+                X:WORD          = ARG_SIZE\r
+        LOCAL   Image:BYTE:MAX_WIDTH*MAX_HEIGHT,        \\r
+                Count:WORD                              = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+        ASSUME  ds:NOTHING\r
+\r
+; Gets the pointer to font data for the selected character\r
+        lds     si, DWORD PTR [mx_FontPtr]\r
+        mov     al, [C]\r
+        xor     ah, ah\r
+        mul     [mx_FontCharSize]       ; Offset into font\r
+        add     si, ax                  ; DS:SI -> font data for character\r
+\r
+; Converts font data into a 256-color linear image\r
+        mov     ax, ss\r
+        mov     es, ax\r
+        lea     di, [Image]\r
+        mov     dx, [mx_FontColor]\r
+        mov     ax, [mx_FontHeight]\r
+        mov     [Count], ax\r
+@@HeightLoop:\r
+        mov     cx, [mx_FontWidth]\r
+        mov     bh, ds:[si]\r
+        inc     si                      ; Get a byte from font data\r
+        cmp     cx, 8\r
+        jbe     @@WidthLoop             ; Ok for width <= 8\r
+        mov     bl, ds:[si]             ; Get another byte\r
+        inc     si\r
+@@WidthLoop:\r
+        mov     al, dl                  ; Assume foreground color\r
+        shl     bx, 1                   ; Is font bit set?\r
+        jc      @@1                     ; Yes, foreground is just great\r
+        mov     al, dh                  ; Get background color\r
+@@1:\r
+        mov     es:[di], al             ; Put pixel into image\r
+        inc     di\r
+        dec     cx\r
+        jnz     @@WidthLoop\r
+        dec     [Count]\r
+        jnz     @@HeightLoop\r
+\r
+; Now pass image to mx_PutImage\r
+        lea     ax, [Image]\r
+        push    es\r
+        push    ax                      ; Pointer to image\r
+        push    [X]\r
+        push    [Y]                     ; Image coordinates\r
+        push    [mx_FontWidth]\r
+        push    [mx_FontHeight]         ; Image size\r
+        push    [mx_FontOp]             ; Raster op\r
+        call    mxPutImage              ; Write character\r
+\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxOutChar       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a string at the coordinates specified.\r
+;\r
+; Input:\r
+;       X, Y    = text coordinates\r
+;       S       = pointer to ASCIIZ string\r
+; Output:\r
+;       none\r
+;\r
+mxOutText       PROC FAR\r
+        ARG     S:DWORD,        \\r
+                Y:WORD,         \\r
+                X:WORD          = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+        ASSUME  ds:NOTHING\r
+\r
+        lds     si, [S]\r
+@@Loop:\r
+        mov     al, ds:[si]\r
+        test    al, al                  ; End of string?\r
+        jz      @@Exit                  ; Yes, exit\r
+        inc     si\r
+        push    [X]                     ; Display character\r
+        push    [Y]\r
+        push    ax\r
+        call    mxOutChar\r
+        mov     ax, [mx_DeltaX]\r
+        add     [X], ax                 ; Bump X coordinate\r
+        mov     ax, [mx_DeltaY]\r
+        add     [Y], ax                 ; Bump Y coordinate\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+        ret\r
+mxOutText       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the distance between characters.\r
+;\r
+; Input:\r
+;       DeltaX  = horizontal distance in pixels\r
+;       DeltaY  = vertical distance in pixels\r
+; Output:\r
+;       none\r
+;\r
+; Note: this function may be used to set the text direction.\r
+;\r
+mxSetTextStep   PROC FAR\r
+        ARG     DeltaY:WORD,    \\r
+                DeltaX:WORD     = ARG_SIZE\r
+        .enter  0\r
+        .push   ds\r
+\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, [DeltaX]\r
+        mov     [mx_DeltaX], ax\r
+        mov     ax, [DeltaY]\r
+        mov     [mx_DeltaY], ax\r
+\r
+        .pop    ds\r
+        .leave  ARG_SIZE\r
+mxSetTextStep   ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Gets the current distance between characters.\r
+;\r
+; Input:\r
+;       DeltaX  = pointer to horizontal distance in pixels (integer)\r
+;       DeltaY  = pointer to vertical distance in pixels (integer)\r
+; Output:\r
+;       none\r
+;\r
+mxGetTextStep   PROC FAR\r
+        ARG     DeltaY:DWORD,   \\r
+                DeltaX:DWORD    = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+        ASSUME  ds:NOTHING\r
+\r
+        mov     ax, [mx_DeltaX]\r
+        lds     si, [DeltaX]\r
+        mov     ds:[si], ax\r
+        mov     ax, [mx_DeltaY]\r
+        lds     si, [DeltaY]\r
+        mov     ds:[si], ax\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetTextStep   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxpb.asm b/16/x/mxpb.asm
new file mode 100755 (executable)
index 0000000..8c6aa44
--- /dev/null
@@ -0,0 +1,22 @@
+;-----------------------------------------------------------\r
+;\r
+; MXPB.ASM - Scan buffer for convex polygon fills\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mx_ScanBuffer\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+ALIGN   4\r
+\r
+mx_ScanBuffer   LABEL\r
+        DW      POLYSCANBUFSIZE DUP(?)\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxpf.asm b/16/x/mxpf.asm
new file mode 100755 (executable)
index 0000000..db0da89
--- /dev/null
@@ -0,0 +1,420 @@
+;-----------------------------------------------------------\r
+;\r
+; MXPG.ASM - Convex polygon fill\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxFillPoly\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; "Local" definitions\r
+;\r
+TPOINT  STRUC\r
+        X       DW      ?\r
+        Y       DW      ?\r
+TPOINT  ENDS\r
+\r
+; Do NOT change order!\r
+TSCAN   STRUC\r
+        Y1      DW      ?\r
+        Y2      DW      ?\r
+TSCAN   ENDS\r
+\r
+MAXSCANCOLUMNS  EQU     POLYSCANBUFSIZE / SIZE TSCAN\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_CodeSegment  : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+EXTRN   mx_ScanBuffer   : NEAR\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Scans an edge using the DDA (digital differential analyzer) algorithm.\r
+;\r
+; Input:\r
+;       DS:BX   = pointer to start point (X1, Y1)\r
+;       DS:SI   = pointer to end point (X2, Y2)\r
+;       ES:DI   = pointer to edge buffer\r
+; Output:\r
+;       ES:DI   = updated pointer to edge buffer\r
+; Notes:\r
+;       must preserve DS:SI.\r
+;\r
+subScan         PROC NEAR\r
+        mov     cx, ds:[si].X\r
+        sub     cx, ds:[bx].X           ; Get width\r
+        jg      @@1\r
+        ret\r
+@@1:\r
+        push    bp                      ; Save BP\r
+\r
+        mov     ax, ds:[si].Y\r
+        mov     bx, ds:[bx].Y\r
+        sub     ax, bx                  ; Get height\r
+        jg      @@T2B                   ; Scan top to bottom\r
+        jl      @@B2T                   ; Scan bottom to top\r
+\r
+; Special case: vertical line\r
+        mov     ax, bx\r
+@@V:\r
+        mov     es:[di].Y1, ax\r
+        add     di, SIZE TSCAN\r
+        dec     cx\r
+       jnz     @@V\r
+        jmp     @@Exit\r
+\r
+; Scan top to bottom\r
+@@T2B:\r
+        cwd\r
+        div     cx\r
+        mov     bp, ax\r
+        xor     ax, ax\r
+        div     cx\r
+        xchg    ax, bx                  ; BP:BX = fixed 16:16 step\r
+        mov     dx, 8000h\r
+@@T2BLoop:\r
+        mov     es:[di].Y1, ax\r
+        add     di, SIZE TSCAN\r
+        add     dx, bx\r
+        adc     ax, bp\r
+        dec     cx\r
+        jnz     @@T2BLoop\r
+        jmp     @@Exit\r
+\r
+; Scan bottom to top\r
+@@B2T:\r
+        neg     ax\r
+        cwd\r
+        div     cx\r
+        mov     bp, ax\r
+        xor     ax, ax\r
+        div     cx\r
+        xchg    ax, bx\r
+        mov     dx, 8000h\r
+@@B2TLoop:\r
+        mov     es:[di].Y1, ax\r
+        add     di, SIZE TSCAN\r
+        sub     dx, bx\r
+        sbb     ax, bp\r
+        dec     cx\r
+        jnz     @@B2TLoop\r
+\r
+@@Exit:\r
+        pop     bp                      ; Restore BP\r
+        ret\r
+subScan         ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a convex polygon with the specified color.\r
+;\r
+; Input:\r
+;       Count   = number of vertexes\r
+;       Map     = indexes of points and colors (integer)\r
+;       Points  = array of points (integer X, Y coordinates)\r
+;       Color   = base color\r
+; Output:\r
+;       none\r
+; Notes:\r
+;       vertexes must be in counterclockwise order, arrays are 0-based.\r
+;\r
+mxFillPoly      PROC FAR\r
+        ARG     Color:WORD,     \\r
+                Points:DWORD,   \\r
+                Map:DWORD,      \\r
+                Count:WORD      = ARG_SIZE\r
+        LOCAL   WritePlane:BYTE:2,      \\r
+                ScanOffsetT:WORD,       \\r
+                ScanOffsetB:WORD,       \\r
+                ScanCount:WORD,         \\r
+                Holder:WORD,            \\r
+                Height:WORD,            \\r
+                MinIdxT:WORD,           \\r
+                MinIdxB:WORD,           \\r
+                MaxIdx:WORD,            \\r
+                Width:WORD,             \\r
+                BoxX1:WORD,             \\r
+                BoxY1:WORD,             \\r
+                BoxX2:WORD,             \\r
+                BoxY2::WORD             = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+        ASSUME  ds:NOTHING\r
+\r
+; Check that at least three vertexes are specified\r
+        mov     cx, [Count]\r
+        cmp     cx, 3\r
+        jb      @@Exit\r
+\r
+;------------------------------\r
+; Find bounding box for polygon\r
+        les     di, [Map]\r
+        lds     si, [Points]            ; Pointer to vertex array\r
+        mov     [BoxX1], 32767\r
+        mov     [BoxX2], -32768\r
+        mov     [BoxY1], 32767\r
+        mov     [BoxY2], -32768\r
+\r
+        xor     dx, dx\r
+@@MinMaxLoop:\r
+        mov     bx, es:[di]             ; Get index of vertex\r
+        .shl    bx, 2                   ; Get offset in point array\r
+        add     bx, si\r
+\r
+; Check X range\r
+@@CheckMinX:\r
+        mov     ax, ds:[bx].X           ; Get X coordinate\r
+        cmp     ax, [BoxX1]\r
+        jge     @@CheckMaxX\r
+        mov     [BoxX1], ax\r
+        mov     [MinIdxT], dx\r
+        mov     [MinIdxB], dx\r
+@@CheckMaxX:\r
+        cmp     ax, [BoxX2]\r
+        jle     @@CheckMinY\r
+        mov     [BoxX2], ax\r
+        mov     [MaxIdx], dx\r
+\r
+; Check Y range\r
+@@CheckMinY:\r
+        mov     ax, ds:[bx].Y\r
+        cmp     ax, [BoxY1]\r
+        jge     @@CheckMaxY\r
+        mov     [BoxY1], ax\r
+@@CheckMaxY:\r
+        cmp     ax, [BoxY2]\r
+        jle     @@CheckDone\r
+        mov     [BoxY2], ax\r
+\r
+; Repeat thru all points\r
+@@CheckDone:\r
+        inc     di                      ; Next map entry\r
+        inc     dx\r
+        inc     di\r
+        inc     dx\r
+        dec     cx\r
+        jnz     @@MinMaxLoop\r
+\r
+;---------------------------------\r
+; Check if polygon is full clipped\r
+        mov     ax, [BoxX2]\r
+        cmp     ax, [mx_ClipX1]         ; Is poly full clipped?\r
+        jl      @@Exit\r
+        mov     bx, [BoxX1]\r
+        cmp     bx, [mx_ClipX2]         ; Is poly full clipped?\r
+        jg      @@Exit\r
+        sub     ax, bx                  ; Get width\r
+        jle     @@Exit                  ; Exit if not positive\r
+        mov     ax, [BoxY2]\r
+        cmp     ax, [mx_ClipY1]         ; Is poly full clipped?\r
+        jl      @@Exit\r
+        mov     bx, [BoxY1]\r
+        cmp     bx, [mx_ClipY2]         ; Is poly full clipped?\r
+        jg      @@Exit\r
+        sub     ax, bx                  ; Get height\r
+        jle     @@Exit                  ; Exit if not positive\r
+\r
+        dec     [Count]\r
+        shl     [Count], 1              ; We'll work with word offsets\r
+        mov     es, [mx_CodeSegment]\r
+\r
+;--------------\r
+; Scan top edge\r
+        mov     ax, OFFSET mx_ScanBuffer\r
+        mov     [ScanOffsetT], ax\r
+        mov     si, [MinIdxT]           ; Offset of bottom point index\r
+@@STLoop:\r
+        lds     bx, [Map]               ; DS:BX -> map table\r
+        mov     di, ds:[bx+si]          ; Index of top point #1\r
+        dec     si                      ; Next point\r
+        dec     si\r
+        test    si, si\r
+        jnl     @@ST1\r
+        mov     si, [Count]\r
+@@ST1:\r
+        mov     [MinIdxT], si           ; Save new index of top point\r
+        mov     si, ds:[bx+si]          ; Get index of top point #2\r
+        .shl    di, 2                   ; Convert indexes to offsets\r
+        .shl    si, 2\r
+        lds     bx, [Points]            ; DS:BX -> point array\r
+        add     si, bx                  ; DS:SI -> top point #2\r
+        add     bx, di                  ; DS:BX -> top point #1\r
+        mov     di, [ScanOffsetT]\r
+        call    subScan                 ; Scan edge\r
+        mov     [ScanOffsetT], di\r
+        mov     si, [MinIdxT]\r
+        cmp     si, [MaxIdx]            ; End of edge?\r
+        jne     @@STLoop                ; No, continue\r
+\r
+;-----------------\r
+; Scan bottom edge\r
+        mov     ax, OFFSET mx_ScanBuffer + OFFSET Y2\r
+        mov     [ScanOffsetB], ax\r
+        mov     si, [MinIdxB]           ; Offset of bottom point index\r
+@@SBLoop:\r
+        lds     bx, [Map]               ; DS:BX -> map table\r
+        mov     di, ds:[bx+si]          ; Index of bottom point #1\r
+        inc     si                      ; Next bottom point\r
+        inc     si\r
+        cmp     si, [Count]\r
+        jbe     @@SB1\r
+        xor     si, si\r
+@@SB1:\r
+        mov     [MinIdxB], si           ; Save new index of bottom point\r
+        mov     si, ds:[bx+si]          ; Get index of bottom point #2\r
+        .shl    di, 2                   ; Convert indexes to offsets\r
+        .shl    si, 2\r
+        lds     bx, [Points]            ; DS:BX -> point array\r
+        add     si, bx                  ; DS:SI -> top point #2\r
+        add     bx, di                  ; DS:BX -> top point #1\r
+        mov     di, [ScanOffsetB]\r
+        call    subScan                 ; Scan edge\r
+        mov     [ScanOffsetB], di\r
+        mov     si, [MinIdxB]\r
+        cmp     si, [MaxIdx]            ; End of edge?\r
+        jne     @@SBLoop                ; No, continue\r
+\r
+;--------------------\r
+; Clip left and right\r
+        mov     si, OFFSET mx_ScanBuffer\r
+        mov     ax, [BoxX1]\r
+        mov     cx, [BoxX2]\r
+        sub     cx, ax                  ; CX = bounding box width\r
+        mov     bx, [mx_ClipX1]\r
+        sub     bx, ax\r
+        jle     @@ClipL1                ; No need to clip left\r
+        sub     cx, bx                  ; Update width\r
+        add     ax, bx                  ; BoxX1 = mx_ClipX1\r
+        mov     [BoxX1], ax\r
+        .shl    bx, 2                   ; Warning!!! This is an hand-coded\r
+        add     si, bx                  ; multiply by the size of TSCAN\r
+@@ClipL1:\r
+        mov     bx, ax\r
+        add     bx, cx                  ; Last scan column\r
+        sub     bx, [mx_ClipX2]\r
+        jle     @@ClipL2                ; No need to clip right\r
+        sub     cx, bx                  ; Clip right\r
+@@ClipL2:\r
+        test    cx, cx                  ; Is clipped width positive?\r
+        jle     @@Exit                  ; No, exit\r
+        mov     [ScanCount], cx         ; Save number of columns to draw\r
+        mov     [ScanOffsetT], si       ; Remember offset of (clipped) buffer\r
+        mov     ds, [mx_CodeSegment]    ; DS:SI -> scan buffer\r
+\r
+;------------------------------\r
+; Check if Y clipping is needed\r
+        mov     ax, [BoxY1]\r
+        cmp     ax, [mx_ClipY1]\r
+        jl      @@ClipTB                ; Need to clip top\r
+        mov     ax, [BoxY2]\r
+        cmp     ax, [mx_ClipY2]\r
+        jg      @@ClipTB                ; Need to clip bottom\r
+        jmp     @@ClipYExit             ; Skip Y clipping\r
+\r
+;--------------------\r
+; Clip top and bottom\r
+@@ClipTB:\r
+        mov     di, cx                  ; DI = scan count\r
+        inc     di                      ; Increment count for pre-loop test\r
+        sub     si, SIZE TSCAN\r
+@@ClipYLoop:\r
+        dec     di                      ; Any column left?\r
+        jz      @@ClipYExit             ; No, exit\r
+        add     si, SIZE TSCAN\r
+        mov     ax, ds:[si].Y1          ; Y1\r
+        mov     cx, ds:[si].Y2          ; Y2\r
+        mov     dx, [mx_ClipY2]\r
+        cmp     ax, dx                  ; Full clipped?\r
+        jg      @@ClipYClip             ; Yes, skip this column\r
+        cmp     cx, dx                  ; Need to clip bottom?\r
+        jle     @@ClipY1                ; No, continue\r
+; Clip bottom\r
+        mov     ds:[si].Y2, dx\r
+        mov     bx, cx\r
+        sub     bx, dx                  ; Clip distance\r
+        sub     cx, ax                  ; Height\r
+        jle     @@ClipYClip\r
+        mov     cx, ds:[si].Y2\r
+@@ClipY1:\r
+        mov     dx, [mx_ClipY1]\r
+        cmp     cx, dx                  ; Full top clipped?\r
+        jl      @@ClipYClip             ; Yes, skip\r
+        sub     cx, ax                  ; Get height\r
+        jle     @@ClipYClip             ; Skip if not positive\r
+        cmp     ax, dx                  ; Need to clip top?\r
+        jge     @@ClipYLoop             ; No, continue\r
+; Clip top\r
+        mov     ds:[si].Y1, dx          ; Y1 = mx_ClipY1\r
+        sub     dx, ax                  ; DX = number of pixels clipped\r
+        cmp     cx, dx\r
+        ja      @@ClipYLoop             ; Not clipped, continue\r
+@@ClipYClip:\r
+        mov     ds:[si].Y1, -1          ; Mark column as clipped\r
+        jmp     @@ClipYLoop\r
+@@ClipYExit:\r
+\r
+;-------------\r
+; Draw columns\r
+        mov     es, [mx_VideoSegment]\r
+        mov     si, [ScanOffsetT]\r
+        mov     cl, BYTE PTR [BoxX1]    ; Init write plane\r
+        and     cl, 03h\r
+        mov     al, 11h\r
+        shl     al, cl\r
+        mov     [WritePlane], al\r
+        .shr    [BoxX1], 2\r
+@@DrawLoop:\r
+        mov     ax, ds:[si].Y1\r
+        test    ax, ax                  ; Was column clipped?\r
+        js      @@DrawNext              ; Yes, skip\r
+        mov     cx, ds:[si].Y2\r
+        sub     cx, ax                  ; CX = height\r
+        jle     @@DrawNext\r
+        mul     [mx_BytesPerLine]       ; Get pixel address\r
+        add     ax, [BoxX1]\r
+        mov     di, ax\r
+        mov     ah, [WritePlane]\r
+        mov     dx, TS\r
+        mov     al, 02h\r
+        out     dx, ax\r
+        mov     ax, [Color]\r
+        mov     dx, [mx_BytesPerLine]\r
+        shr     cx, 1\r
+        jnc     @@FillScan\r
+        mov     es:[di], al\r
+        add     di, dx\r
+        jcxz    @@DrawNext\r
+@@FillScan:\r
+        mov     es:[di], al\r
+        add     di, dx\r
+        mov     es:[di], al\r
+        add     di, dx\r
+        dec     cx\r
+        jnz     @@FillScan\r
+@@DrawNext:\r
+        rol     [WritePlane], 1\r
+        adc     [BoxX1], 0              ; Bump pointer to video memory if needed\r
+        add     si, SIZE TSCAN\r
+        dec     [ScanCount]\r
+        jnz     @@DrawLoop\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxFillPoly      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxpg.asm b/16/x/mxpg.asm
new file mode 100755 (executable)
index 0000000..caa7cf1
--- /dev/null
@@ -0,0 +1,589 @@
+;-----------------------------------------------------------\r
+;\r
+; MXPG.ASM - Convex polygon fill with Gouraud shading\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxGouraudPoly\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; "Local" definitions\r
+;\r
+TPOINT  STRUC\r
+        X       DW      ?\r
+        Y       DW      ?\r
+TPOINT  ENDS\r
+\r
+; Do NOT change order!\r
+TSCAN   STRUC\r
+        Y1      DW      ?\r
+        E1      DB      ?\r
+        C1      DB      ?\r
+        Y2      DW      ?\r
+        E2      DB      ?\r
+        C2      DB      ?\r
+TSCAN   ENDS\r
+\r
+MAXSCANCOLUMNS  EQU     POLYSCANBUFSIZE / SIZE TSCAN\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_CodeSegment  : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+EXTRN   mx_ScanBuffer   : NEAR\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Scans an edge using the DDA (digital differential analyzer) algorithm.\r
+; Also interpolates color for shading.\r
+;\r
+; Input:\r
+;       DS:BX   = pointer to start point (X1, Y1)\r
+;       DS:SI   = pointer to end point (X2, Y2)\r
+;       ES:DI   = pointer to edge buffer\r
+;       DX      = start color\r
+;       AX      = end color\r
+; Output:\r
+;       ES:DI   = updated pointer to edge buffer\r
+; Notes:\r
+;       must preserve DS:SI.\r
+;\r
+subScan         PROC NEAR\r
+        mov     cx, ds:[si].X\r
+        sub     cx, ds:[bx].X           ; Get width\r
+        jg      @@1\r
+        ret\r
+@@1:\r
+        push    bp                      ; Save BP\r
+        push    di                      ; Save scan info offset\r
+        push    cx                      ; Save height\r
+        push    ax                      ; Save colors\r
+        push    dx\r
+\r
+        mov     ax, ds:[si].Y\r
+        mov     bx, ds:[bx].Y\r
+        sub     ax, bx                  ; Get height\r
+        jg      @@T2B                   ; Scan top to bottom\r
+        jl      @@B2T                   ; Scan bottom to top\r
+\r
+; Special case: vertical line\r
+        mov     ax, bx\r
+@@V:\r
+        mov     es:[di].Y1, ax\r
+        add     di, SIZE TSCAN\r
+        dec     cx\r
+       jnz     @@V\r
+        jmp     @@GetColorInfo\r
+\r
+; Scan top to bottom\r
+@@T2B:\r
+        cwd\r
+        div     cx\r
+        mov     bp, ax\r
+        xor     ax, ax\r
+        div     cx\r
+        xchg    ax, bx                  ; BP:BX = fixed 16:16 step\r
+        mov     dx, 8000h\r
+@@T2BLoop:\r
+        mov     es:[di].Y1, ax\r
+        add     di, SIZE TSCAN\r
+        add     dx, bx\r
+        adc     ax, bp\r
+        dec     cx\r
+        jnz     @@T2BLoop\r
+        jmp     @@GetColorInfo\r
+\r
+; Scan bottom to top\r
+@@B2T:\r
+        neg     ax\r
+        cwd\r
+        div     cx\r
+        mov     bp, ax\r
+        xor     ax, ax\r
+        div     cx\r
+        xchg    ax, bx\r
+        mov     dx, 8000h\r
+@@B2TLoop:\r
+        mov     es:[di].Y1, ax\r
+        add     di, SIZE TSCAN\r
+        sub     dx, bx\r
+        sbb     ax, bp\r
+        dec     cx\r
+        jnz     @@B2TLoop\r
+\r
+; Now get the color info\r
+@@GetColorInfo:\r
+        pop     bx                      ; Restore colors\r
+        pop     ax\r
+        pop     cx                      ; Height\r
+        pop     di                      ; ES:DI -> scan info\r
+\r
+        sub     ax, bx                  ; Get color range\r
+        jg      @@CL2R\r
+        jl      @@CR2L\r
+\r
+; Special case: same color\r
+        mov     ah, bl\r
+        mov     al, 80h\r
+@@CV:\r
+        mov     WORD PTR es:[di].E1, ax\r
+        add     di, SIZE TSCAN\r
+        dec     cx\r
+        jnz     @@CV\r
+        jmp     @@Exit\r
+\r
+; Scan left to right\r
+@@CL2R:\r
+        cwd\r
+        div     cx\r
+        mov     bp, ax\r
+        xor     ax, ax\r
+        div     cx\r
+        xchg    ax, bx                  ; BP:BX = fixed 16:16 step\r
+        mov     dx, 8000h\r
+@@CL2RLoop:\r
+        mov     es:[di].C1, al\r
+        mov     es:[di].E1, dh\r
+        add     di, SIZE TSCAN\r
+        add     dx, bx\r
+        adc     ax, bp\r
+        dec     cx\r
+        jnz     @@CL2RLoop\r
+        jmp     @@Exit\r
+\r
+; Scan right to left\r
+@@CR2L:\r
+        neg     ax\r
+        cwd\r
+        div     cx\r
+        mov     bp, ax\r
+        xor     ax, ax\r
+        div     cx\r
+        xchg    ax, bx\r
+        mov     dx, 8000h\r
+\r
+@@CR2LLoop:\r
+        mov     es:[di].C1, al\r
+        mov     es:[di].E1, dh\r
+        add     di, SIZE TSCAN\r
+        sub     dx, bx\r
+        sbb     ax, bp\r
+        dec     cx\r
+        jnz     @@CR2LLoop\r
+\r
+@@Exit:\r
+        pop     bp\r
+        ret\r
+subScan         ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a scan column.\r
+;\r
+; Input:\r
+;       DS:SI   = current TSCAN\r
+;       ES:DI   = address of top pixel\r
+;       CX      = number of pixels to write\r
+;       DX      = base color\r
+; Output:\r
+;       none\r
+;\r
+subFillScan     PROC NEAR\r
+        mov     ax, WORD PTR ds:[si].E2\r
+        mov     bx, WORD PTR ds:[si].E1\r
+        cmp     ah, bh\r
+        jg      @@L2R                   ; Color increases\r
+        jl      @@R2L                   ; Color decreases\r
+\r
+; Special case: color doesn't change\r
+        add     ax, dx\r
+        mov     dx, [mx_BytesPerLine]\r
+@@V:\r
+        mov     es:[di], ah\r
+        add     di, dx\r
+        dec     cx\r
+        jnz     @@V\r
+        ret\r
+\r
+; Color increases\r
+@@L2R:\r
+        .push   bp, si\r
+        mov     si, bx\r
+        add     si, dx                  ; Relocate color\r
+        sub     ax, bx\r
+        xor     dx, dx\r
+        div     cx\r
+        mov     bp, ax                  ; BP = color step, integer part\r
+        xor     ax, ax\r
+        div     cx\r
+        mov     bx, ax                  ; BX = color step, fractional part\r
+        mov     dx, 8000h\r
+        mov     ax, [mx_BytesPerLine]\r
+        xchg    si, ax\r
+@@L2RLoop:\r
+        mov     es:[di], ah\r
+        add     dx, bx\r
+        adc     ax, bp\r
+        add     di, si\r
+        dec     cx\r
+        jnz     @@L2RLoop\r
+        .pop    bp, si\r
+        ret\r
+\r
+; Color decreases\r
+@@R2L:\r
+        .push   bp, si\r
+        mov     si, bx\r
+        add     si, dx                  ; Relocate color\r
+        sub     ax, bx\r
+        neg     ax\r
+        xor     dx, dx\r
+        div     cx\r
+        mov     bp, ax                  ; BP = color step, integer part\r
+        xor     ax, ax\r
+        div     cx\r
+        mov     bx, ax                  ; BX = color step, fractional part\r
+        mov     dx, 8000h\r
+        mov     ax, [mx_BytesPerLine]\r
+        xchg    si, ax\r
+@@R2LLoop:\r
+        mov     es:[di], ah\r
+        sub     dx, bx\r
+        sbb     ax, bp\r
+        add     di, si\r
+        dec     cx\r
+        jnz     @@R2LLoop\r
+        .pop    bp, si\r
+        ret\r
+subFillScan     ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a convex polygon with the specified color.\r
+; Interpolates pixel colors using the Gouraud algorithm.\r
+;\r
+; Input:\r
+;       Count   = number of vertexes\r
+;       Map     = indexes of points and colors (integer)\r
+;       Points  = array of points (integer X, Y coordinates)\r
+;       Colors  = array of colors (integer)\r
+;       Color   = base color\r
+; Output:\r
+;       none\r
+; Notes:\r
+;       vertexes must be in counterclockwise order, arrays are 0-based.\r
+;\r
+mxGouraudPoly  PROC FAR\r
+        ARG     Color:WORD,     \\r
+                Colors:DWORD,   \\r
+                Points:DWORD,   \\r
+                Map:DWORD,      \\r
+                Count:WORD      = ARG_SIZE\r
+        LOCAL   WritePlane:BYTE:2,      \\r
+                ScanOffsetT:WORD,       \\r
+                ScanOffsetB:WORD,       \\r
+                ScanCount:WORD,         \\r
+                Holder:WORD,            \\r
+                Height:WORD,            \\r
+                MinIdxT:WORD,           \\r
+                MinIdxB:WORD,           \\r
+                MaxIdx:WORD,            \\r
+                Width:WORD,             \\r
+                BoxX1:WORD,             \\r
+                BoxY1:WORD,             \\r
+                BoxX2:WORD,             \\r
+                BoxY2::WORD             = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+        ASSUME  ds:NOTHING\r
+\r
+; Check that at least three vertexes are specified\r
+        mov     cx, [Count]\r
+        cmp     cx, 3\r
+        jb      @@Exit\r
+\r
+;------------------------------\r
+; Find bounding box for polygon\r
+        les     di, [Map]\r
+        lds     si, [Points]            ; Pointer to vertex array\r
+        mov     [BoxX1], 32767\r
+        mov     [BoxX2], -32768\r
+        mov     [BoxY1], 32767\r
+        mov     [BoxY2], -32768\r
+\r
+        xor     dx, dx\r
+@@MinMaxLoop:\r
+        mov     bx, es:[di]             ; Get index of vertex\r
+        .shl    bx, 2                   ; Get offset in point array\r
+        add     bx, si\r
+\r
+; Check X range\r
+@@CheckMinX:\r
+        mov     ax, ds:[bx].X           ; Get X coordinate\r
+        cmp     ax, [BoxX1]\r
+        jge     @@CheckMaxX\r
+        mov     [BoxX1], ax\r
+        mov     [MinIdxT], dx\r
+        mov     [MinIdxB], dx\r
+@@CheckMaxX:\r
+        cmp     ax, [BoxX2]\r
+        jle     @@CheckMinY\r
+        mov     [BoxX2], ax\r
+        mov     [MaxIdx], dx\r
+\r
+; Check Y range\r
+@@CheckMinY:\r
+        mov     ax, ds:[bx].Y\r
+        cmp     ax, [BoxY1]\r
+        jge     @@CheckMaxY\r
+        mov     [BoxY1], ax\r
+@@CheckMaxY:\r
+        cmp     ax, [BoxY2]\r
+        jle     @@CheckDone\r
+        mov     [BoxY2], ax\r
+\r
+; Repeat thru all points\r
+@@CheckDone:\r
+        inc     di                      ; Next map entry\r
+        inc     di\r
+        inc     dx\r
+        inc     dx\r
+        dec     cx\r
+        jnz     @@MinMaxLoop\r
+\r
+;---------------------------------\r
+; Check if polygon is full clipped\r
+        mov     ax, [BoxX2]\r
+        cmp     ax, [mx_ClipX1]         ; Is poly full clipped?\r
+        jl      @@Exit\r
+        mov     bx, [BoxX1]\r
+        cmp     bx, [mx_ClipX2]         ; Is poly full clipped?\r
+        jg      @@Exit\r
+        sub     ax, bx                  ; Get width\r
+        jle     @@Exit                  ; Exit if not positive\r
+        mov     ax, [BoxY2]\r
+        cmp     ax, [mx_ClipY1]         ; Is poly full clipped?\r
+        jl      @@Exit\r
+        mov     bx, [BoxY1]\r
+        cmp     bx, [mx_ClipY2]         ; Is poly full clipped?\r
+        jg      @@Exit\r
+        sub     ax, bx                  ; Get height\r
+        jle     @@Exit                  ; Exit if not positive\r
+\r
+        dec     [Count]\r
+        shl     [Count], 1              ; We'll work with word offsets\r
+        mov     es, [mx_CodeSegment]\r
+\r
+;--------------\r
+; Scan top edge\r
+        mov     ax, OFFSET mx_ScanBuffer\r
+        mov     [ScanOffsetT], ax\r
+        mov     si, [MinIdxT]           ; Offset of bottom point index\r
+@@STLoop:\r
+        lds     bx, [Map]               ; DS:BX -> map table\r
+        mov     di, ds:[bx+si]          ; Index of top point #1\r
+        dec     si                      ; Next point\r
+        dec     si\r
+        test    si, si\r
+        jnl     @@ST1\r
+        mov     si, [Count]\r
+@@ST1:\r
+        mov     [MinIdxT], si           ; Save new index of top point\r
+        mov     si, ds:[bx+si]          ; Get index of top point #2\r
+        lds     bx, [Colors]            ; Get pointer to color array\r
+        shl     di, 1                   ; Convert indexes to offsets\r
+        shl     si, 1\r
+        mov     ax, ds:[bx+si]          ; Get colors\r
+        mov     dx, ds:[bx+di]\r
+        lds     bx, [Points]            ; DS:BX -> point array\r
+        shl     si, 1\r
+        shl     di, 1\r
+        add     si, bx                  ; DS:SI -> top point #2\r
+        add     bx, di                  ; DS:BX -> top point #1\r
+        mov     di, [ScanOffsetT]\r
+        call    subScan                 ; Scan edge\r
+        mov     [ScanOffsetT], di\r
+        mov     si, [MinIdxT]\r
+        cmp     si, [MaxIdx]            ; End of edge?\r
+        jne     @@STLoop                ; No, continue\r
+\r
+;-----------------\r
+; Scan bottom edge\r
+        mov     ax, OFFSET mx_ScanBuffer + OFFSET Y2\r
+        mov     [ScanOffsetB], ax\r
+        mov     si, [MinIdxB]           ; Offset of bottom point index\r
+@@SBLoop:\r
+        lds     bx, [Map]               ; DS:BX -> map table\r
+        mov     di, ds:[bx+si]          ; Index of bottom point #1\r
+        inc     si                      ; Next bottom point\r
+        inc     si\r
+        cmp     si, [Count]\r
+        jbe     @@SB1\r
+        xor     si, si\r
+@@SB1:\r
+        mov     [MinIdxB], si           ; Save new index of bottom point\r
+        mov     si, ds:[bx+si]          ; Get index of bottom point #2\r
+        lds     bx, [Colors]            ; Get pointer to color array\r
+        shl     di, 1                   ; Convert indexes to offsets\r
+        shl     si, 1\r
+        mov     ax, ds:[bx+si]          ; Get colors\r
+        mov     dx, ds:[bx+di]\r
+        lds     bx, [Points]            ; DS:BX -> point array\r
+        shl     si, 1\r
+        shl     di, 1\r
+        add     si, bx                  ; DS:SI -> top point #2\r
+        add     bx, di                  ; DS:BX -> top point #1\r
+        mov     di, [ScanOffsetB]\r
+        call    subScan                 ; Scan edge\r
+        mov     [ScanOffsetB], di\r
+        mov     si, [MinIdxB]\r
+        cmp     si, [MaxIdx]            ; End of edge?\r
+        jne     @@SBLoop                ; No, continue\r
+\r
+;--------------------\r
+; Clip left and right\r
+        mov     si, OFFSET mx_ScanBuffer\r
+        mov     ax, [BoxX1]\r
+        mov     cx, [BoxX2]\r
+        sub     cx, ax                  ; CX = bounding box width\r
+        mov     bx, [mx_ClipX1]\r
+        sub     bx, ax\r
+        jle     @@ClipL1                ; No need to clip left\r
+        sub     cx, bx                  ; Update width\r
+        add     ax, bx                  ; BoxX1 = mx_ClipX1\r
+        mov     [BoxX1], ax\r
+        .shl    bx, 3                   ; Warning!!! This is an hand-coded\r
+        add     si, bx                  ; multiply by the size of TSCAN\r
+@@ClipL1:\r
+        mov     bx, ax\r
+        add     bx, cx                  ; Last scan column\r
+        sub     bx, [mx_ClipX2]\r
+        jle     @@ClipL2                ; No need to clip right\r
+        sub     cx, bx                  ; Clip right\r
+@@ClipL2:\r
+        test    cx, cx                  ; Is clipped width positive?\r
+        jle     @@Exit                  ; No, exit\r
+        mov     [ScanCount], cx         ; Save number of columns to draw\r
+        mov     [ScanOffsetT], si       ; Remember offset of (clipped) buffer\r
+        mov     ds, [mx_CodeSegment]    ; DS:SI -> scan buffer\r
+\r
+;------------------------------\r
+; Check if Y clipping is needed\r
+        mov     ax, [BoxY1]\r
+        cmp     ax, [mx_ClipY1]\r
+        jl      @@ClipTB                ; Need to clip top\r
+        mov     ax, [BoxY2]\r
+        cmp     ax, [mx_ClipY2]\r
+        jg      @@ClipTB                ; Need to clip bottom\r
+        jmp     @@ClipYExit             ; Skip Y clipping\r
+\r
+;--------------------\r
+; Clip top and bottom\r
+@@ClipTB:\r
+        mov     di, cx                  ; DI = scan count\r
+        inc     di                      ; Increment count for pre-loop test\r
+        sub     si, SIZE TSCAN\r
+@@ClipYLoop:\r
+        dec     di                      ; Any column left?\r
+        jz      @@ClipYExit             ; No, exit\r
+        add     si, SIZE TSCAN\r
+        mov     ax, ds:[si].Y1          ; Y1\r
+        mov     cx, ds:[si].Y2          ; Y2\r
+        mov     dx, [mx_ClipY2]\r
+        cmp     ax, dx                  ; Full clipped?\r
+        jg      @@ClipYClip             ; Yes, skip this column\r
+        cmp     cx, dx                  ; Need to clip bottom?\r
+        jle     @@ClipY1                ; No, continue\r
+; Clip bottom, need to scale colors too\r
+        mov     ds:[si].Y2, dx\r
+        mov     bx, cx\r
+        sub     bx, dx                  ; Clip distance\r
+        sub     cx, ax                  ; Height\r
+        jle     @@ClipYClip\r
+        mov     ax, WORD PTR ds:[si].E1\r
+        sub     ax, WORD PTR ds:[si].E2\r
+        imul    bx\r
+        idiv    cx\r
+        add     WORD PTR ds:[si].E2, ax\r
+        mov     ax, ds:[si].Y1          ; Restore AX and CX\r
+        mov     cx, ds:[si].Y2\r
+@@ClipY1:\r
+        mov     dx, [mx_ClipY1]\r
+        cmp     cx, dx                  ; Full top clipped?\r
+        jl      @@ClipYClip             ; Yes, skip\r
+        sub     cx, ax                  ; Get height\r
+        jle     @@ClipYClip             ; Skip if not positive\r
+        cmp     ax, dx                  ; Need to clip top?\r
+        jge     @@ClipYLoop             ; No, continue\r
+; Clip top, need to scale colors too\r
+        mov     ds:[si].Y1, dx          ; Y1 = mx_ClipY1\r
+        sub     dx, ax                  ; DX = number of pixels clipped\r
+        cmp     cx, dx\r
+        jbe     @@ClipYClip             ; Full clipped, skip\r
+        mov     ax, WORD PTR ds:[si].E2\r
+        sub     ax, WORD PTR ds:[si].E1 ; AX = color distance\r
+        imul    dx\r
+        idiv    cx\r
+        add     WORD PTR ds:[si].E1, ax ; Update starting color\r
+        jmp     @@ClipYLoop\r
+@@ClipYClip:\r
+        mov     ds:[si].Y1, -1          ; Mark column as clipped\r
+        jmp     @@ClipYLoop\r
+@@ClipYExit:\r
+\r
+;-------------\r
+; Draw columns\r
+        mov     es, [mx_VideoSegment]\r
+        mov     si, [ScanOffsetT]\r
+        mov     cl, BYTE PTR [BoxX1]    ; Init write plane\r
+        and     cl, 03h\r
+        mov     al, 11h\r
+        shl     al, cl\r
+        mov     [WritePlane], al\r
+        .shr    [BoxX1], 2\r
+        mov     ax, [Color]             ; Make 8:8 fixed color\r
+        mov     ah, al\r
+        xor     al, al\r
+        mov     [Color], ax\r
+@@DrawLoop:\r
+        mov     ax, ds:[si].Y1\r
+        test    ax, ax                  ; Was column clipped?\r
+        js      @@DrawNext              ; Yes, skip\r
+        mov     cx, ds:[si].Y2\r
+        sub     cx, ax                  ; CX = height\r
+        jle     @@DrawNext\r
+        mul     [mx_BytesPerLine]       ; Get pixel address\r
+        add     ax, [BoxX1]\r
+        mov     di, ax\r
+        mov     ah, [WritePlane]\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax\r
+        mov     dx, [Color]\r
+        call    subFillScan\r
+@@DrawNext:\r
+        rol     [WritePlane], 1\r
+        adc     [BoxX1], 0              ; Bump pointer to video memory if needed\r
+        add     si, SIZE TSCAN\r
+        dec     [ScanCount]\r
+        jnz     @@DrawLoop\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxGouraudPoly  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxpi.asm b/16/x/mxpi.asm
new file mode 100755 (executable)
index 0000000..9e8525f
--- /dev/null
@@ -0,0 +1,267 @@
+;-----------------------------------------------------------\r
+;\r
+; MXPI.ASM - Put image\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxPutImage\r
+\r
+EXTRN   subClipImage            : NEAR\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+mxTable LABEL   WORD                    ; Raster ops\r
+        DW      subMove\r
+        DW      subAnd\r
+        DW      subOr\r
+        DW      subXor\r
+        DW      subTrans\r
+        DW      subAdd\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Move functions.\r
+; Note: loops unrolled and optimized for CX even, no check for CX = 0.\r
+;\r
+subMove         PROC    NEAR\r
+        shr     cx, 1                   ; Make CX even\r
+        jc      @@Odd                   ; Special case if odd byte\r
+@@Loop: movsb\r
+        add     si, 3\r
+        movsb\r
+        add     si, 3\r
+        dec     cx\r
+        jnz     @@Loop\r
+@@Exit: ret\r
+@@Odd:  movsb\r
+        add     si, 3\r
+        jcxz    @@Exit\r
+        jmp     @@Loop\r
+subMove         ENDP\r
+;\r
+subAnd          PROC     NEAR\r
+        shr     cx, 1\r
+        jc      @@Odd\r
+@@Loop: mov     al, ds:[si]\r
+        mov     ah, ds:[si+4]\r
+        and     es:[di], ax\r
+        inc     di\r
+        inc     di\r
+        add     si, 8\r
+        dec     cx\r
+        jnz     @@Loop\r
+@@Exit: ret\r
+@@Odd:  lodsb\r
+        and     es:[di], al\r
+        inc     di\r
+        add     si, 3\r
+        jcxz    @@Exit\r
+        jmp     @@Loop\r
+subAnd          ENDP\r
+;\r
+subOr           PROC     NEAR\r
+        shr     cx, 1\r
+        jc      @@Odd\r
+@@Loop: mov     al, ds:[si]\r
+        mov     ah, ds:[si+4]\r
+        or      es:[di], ax\r
+        inc     di\r
+        inc     di\r
+        add     si, 8\r
+        dec     cx\r
+        jnz     @@Loop\r
+@@Exit: ret\r
+@@Odd:  lodsb\r
+        or      es:[di], al\r
+        inc     di\r
+        add     si, 3\r
+        jcxz    @@Exit\r
+        jmp     @@Loop\r
+subOr           ENDP\r
+;\r
+subXor          PROC     NEAR\r
+        shr     cx, 1\r
+        jc      @@Odd\r
+@@Loop: mov     al, ds:[si]\r
+        mov     ah, ds:[si+4]\r
+        xor     es:[di], ax\r
+        inc     di\r
+        inc     di\r
+        add     si, 8\r
+        dec     cx\r
+        jnz     @@Loop\r
+@@Exit: ret\r
+@@Odd:  lodsb\r
+        xor     es:[di], al\r
+        inc     di\r
+        add     si, 3\r
+        jcxz    @@Exit\r
+        jmp     @@Loop\r
+subXor          ENDP\r
+;\r
+subTrans        PROC     NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        cmp     al, ah\r
+        je      @@Skip\r
+        mov     es:[di], al\r
+@@Skip: inc     di\r
+        add     si, 4\r
+        dec     cx\r
+        jnz     @@Loop\r
+@@Exit: ret\r
+subTrans        ENDP\r
+;\r
+subAdd          PROC     NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        add     es:[di], al\r
+        inc     di\r
+        add     si, 4\r
+        dec     cx\r
+        jnz     @@Loop\r
+        ret\r
+subAdd          ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies a "raw" image from memory to screen.\r
+;\r
+; Input:\r
+;       Image   = pointer to image\r
+;       X, Y    = coordinates of destination\r
+;       Width   = width of image in pixels\r
+;       Height  = height of image in pixels\r
+;       Op      = raster op (OP_xxx)\r
+; Output:\r
+;       none\r
+;\r
+mxPutImage      PROC    FAR\r
+        ARG     Op:WORD,                \\r
+                Height:WORD,            \\r
+                Width:WORD,             \\r
+                Y:WORD,                 \\r
+                X:WORD,                 \\r
+                Image:DWORD             = ARG_SIZE\r
+        LOCAL   PlaneWidth:WORD:4,      \\r
+                PixelOffset:WORD,       \\r
+                MoveFunction:WORD,      \\r
+                Count:BYTE,             \\r
+                ReadPlane:BYTE,         \\r
+                OpInfo:BYTE,            \\r
+                WritePlane:BYTE         = AUTO_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+\r
+; Clip image\r
+        mov     bx, [X]\r
+        mov     ax, [Y]\r
+        mov     cx, [Width]\r
+        mov     dx, [Height]\r
+        call    subClipImage\r
+        jc      @@Exit                  ; Full clipped\r
+        mov     [Height], dx\r
+        add     WORD PTR Image[0], si   ; Skip clipped pixels\r
+\r
+; Get pixel address\r
+        mul     [mx_BytesPerLine]\r
+        mov     di, bx\r
+        shr     di, 1\r
+        shr     di, 1\r
+        add     di, ax\r
+        mov     [PixelOffset], di\r
+        mov     es, [mx_VideoSegment]   ; ES:DI points to pixel\r
+        and     bl, 03h\r
+        mov     [ReadPlane], bl\r
+\r
+; Compute extra bytes and width count for each plane\r
+        mov     bx, cx\r
+        shr     bx, 1\r
+        shr     bx, 1                   ; Width for each plane\r
+        and     cl, 03h\r
+        mov     al, 00001000b\r
+        shr     al, cl\r
+        mov     si, 3 SHL 1\r
+@@PatchLoop:\r
+        mov     PlaneWidth[si], bx\r
+        shr     al, 1\r
+        adc     bx, 0\r
+        dec     si\r
+        dec     si\r
+        jge     @@PatchLoop\r
+\r
+; Setup planes for output to VGA registers\r
+        mov     cl, [ReadPlane]\r
+        mov     al, 00010001b\r
+        shl     al, cl\r
+        mov     [WritePlane], al\r
+\r
+; Install move function\r
+        mov     bx, [Op]\r
+        mov     [OpInfo], bh            ; Remember additional info if needed\r
+        xor     bh, bh\r
+        cmp     bl, OP_ADD\r
+        jbe     @@SetMoveFunction\r
+        xor     bl, bl\r
+@@SetMoveFunction:\r
+        shl     bx, 1\r
+        mov     ax, mxTable[bx]\r
+        mov     [MoveFunction], ax\r
+\r
+; Put image\r
+        cld\r
+        mov     [Count], 4              ; Four planes\r
+        lea     bx, PlaneWidth          ; SS:[BX] = width in bytes for plane\r
+        mov     ds, WORD PTR Image[2]\r
+@@PlaneLoop:\r
+        cmp     WORD PTR ss:[bx], 0     ; Exit if nothing more to do\r
+        je      @@Exit                  ; (also, never try to move zero bytes!)\r
+        mov     si, WORD PTR Image[0]\r
+        mov     ah, [WritePlane]\r
+        and     ah, 0Fh\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax                  ; Select write plane\r
+        mov     ah, [ReadPlane]\r
+        and     ah, 03h\r
+        mov     al, 04h\r
+        mov     dx, GDC\r
+        out     dx, ax                  ; Select read plane\r
+        mov     dx, [Height]\r
+        mov     di, [PixelOffset]\r
+@@Loop:\r
+        push    si\r
+        push    di\r
+        mov     cx, WORD PTR ss:[bx]    ; Number of bytes to move\r
+        mov     ah, [OpInfo]            ; Transparent color for subTrans\r
+        call    [MoveFunction]\r
+        pop     di\r
+        pop     si\r
+        add     si, [Width]             ; Go to next image line\r
+        add     di, [mx_BytesPerLine]   ; Go to next screen row\r
+        dec     dx\r
+        jnz     @@Loop                  ; Repeat for all lines\r
+        inc     bx\r
+        inc     bx                      ; Select width for next plane\r
+        inc     [ReadPlane]\r
+        rol     [WritePlane], 1\r
+        adc     [PixelOffset], 0\r
+        inc     WORD PTR Image[0]\r
+        dec     [Count]\r
+        jnz     @@PlaneLoop             ; Repeat for all planes\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxPutImage      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxpn.asm b/16/x/mxpn.asm
new file mode 100755 (executable)
index 0000000..eaaf61b
--- /dev/null
@@ -0,0 +1,60 @@
+;-----------------------------------------------------------\r
+;\r
+; MXPN.ASM - Panning function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxPan\r
+\r
+EXTRN   mxWaitDisplay   : FAR\r
+EXTRN   mxStartAddress  : FAR\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Moves the screen.\r
+;\r
+; Input:\r
+;       X, Y    = new X, Y coordinates of view screen\r
+; Output:\r
+;       none\r
+;\r
+mxPan           PROC    FAR\r
+        ARG     Y:WORD,                 \\r
+                X:WORD                  = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+\r
+        mov     ax, [Y]\r
+        mul     [mx_BytesPerLine]\r
+        mov     dx, [X]\r
+        shr     dx, 1\r
+        shr     dx, 1\r
+        add     ax, dx\r
+        push    ax                      ; Push the start address\r
+        call    mxWaitDisplay\r
+        call    mxStartAddress\r
+\r
+        mov     dx, 03DAh               ; Set the pixel pan register\r
+        in      al, dx\r
+        mov     dx, 03C0h\r
+        mov     al, 33h\r
+        out     dx, al\r
+        mov     al, BYTE PTR [X]\r
+        and     al, 3\r
+        shl     al, 1\r
+        out     dx, al\r
+\r
+        xor     ax, ax\r
+        .leave  ARG_SIZE\r
+mxPan           ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxpp.asm b/16/x/mxpp.asm
new file mode 100755 (executable)
index 0000000..fc1755a
--- /dev/null
@@ -0,0 +1,121 @@
+;-----------------------------------------------------------\r
+;\r
+; MXPP.ASM - Get/put pixel functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxGetPixel\r
+PUBLIC  mxPutPixel\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Gets a pixel.\r
+;\r
+; Input:\r
+;       X, Y    = pixel coordinates\r
+; Output:\r
+;       pixel color\r
+;\r
+mxGetPixel      PROC    FAR\r
+        ARG     Y:WORD,                 \\r
+                X:WORD                  = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si\r
+\r
+        xor     ax, ax\r
+        mov     si, [X]\r
+        cmp     si, [mx_ClipX1]\r
+        jl      @@Exit\r
+        cmp     si, [mx_ClipX2]\r
+        jg      @@Exit\r
+        mov     bx, [Y]\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      @@Exit\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      @@Exit\r
+\r
+        mov     al, 04h                 ; Set read plane\r
+        mov     ah, BYTE PTR [X]\r
+        and     ah, 3\r
+        mov     dx, GDC\r
+        out     dx, ax\r
+\r
+        mov     ds, [mx_VideoSegment]\r
+        mov     ax, bx\r
+        mul     [mx_BytesPerLine]\r
+        .shr    si, 2\r
+        add     si, ax\r
+\r
+        mov     al, ds:[si]             ; Get pixel value\r
+        xor     ah, ah\r
+\r
+@@Exit:\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetPixel      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Puts a pixel of the specified color.\r
+;\r
+; Input:\r
+;       X, Y    = pixel coordinates\r
+;       Color   = pixel color\r
+; Output:\r
+;       none\r
+;\r
+mxPutPixel      PROC    FAR\r
+        ARG     Color:BYTE:2,           \\r
+                Y:WORD,                 \\r
+                X:WORD                  = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+\r
+        mov     si, [X]\r
+        cmp     si, [mx_ClipX1]\r
+        jl      @@Exit\r
+        cmp     si, [mx_ClipX2]\r
+        jg      @@Exit\r
+        mov     ax, [Y]\r
+        cmp     ax, [mx_ClipY1]\r
+        jl      @@Exit\r
+        cmp     ax, [mx_ClipY2]\r
+        jg      @@Exit\r
+\r
+        mov     ds, [mx_VideoSegment]\r
+        mul     [mx_BytesPerLine]\r
+        .shr    si, 2\r
+        add     si, ax\r
+\r
+        mov     cl, BYTE PTR [X]        ; Set write plane\r
+        and     cl, 3\r
+        mov     ax, 0102h\r
+        shl     ah, cl\r
+        mov     dx, TS\r
+        out     dx, ax\r
+\r
+        mov     al, [Color]             ; Write pixel\r
+        mov     ds:[si], al\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxPutPixel      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxra.asm b/16/x/mxra.asm
new file mode 100755 (executable)
index 0000000..dd8e683
--- /dev/null
@@ -0,0 +1,37 @@
+;-----------------------------------------------------------\r
+;\r
+; MXRA.ASM - Row address\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxRowAddress\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the row address register.\r
+;\r
+; Input:\r
+;       RowAddress      = row size in words\r
+; Output:\r
+;       none\r
+;\r
+mxRowAddress    PROC    FAR\r
+        ARG     RowAddress:BYTE:2       = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        mov     dx, CRTC\r
+        mov     al, 13h\r
+        mov     ah, [RowAddress]\r
+        out     dx, ax\r
+        xor     ax, ax\r
+        .leave  ARG_SIZE\r
+mxRowAddress    ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxrp.asm b/16/x/mxrp.asm
new file mode 100755 (executable)
index 0000000..de820c1
--- /dev/null
@@ -0,0 +1,101 @@
+;-----------------------------------------------------------\r
+;\r
+; MXRP.ASM - Rotate palette function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxRotatePalette\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Rotates the palette of the specified number of colors.\r
+;\r
+; Input:\r
+;       Palette = pointer to palette\r
+;       Count   = number of colors to rotate\r
+;       Step    = step size\r
+; Output:\r
+;       none\r
+;\r
+; Note: if Step is positive palette is rotated left to right, otherwise\r
+;       right to left.\r
+;\r
+mxRotatePalette PROC    FAR\r
+        ARG     Step:WORD,      \\r
+                Count:WORD,     \\r
+                Palette:DWORD   = ARG_SIZE\r
+        LOCAL   Holder:BYTE:768 = AUTO_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+\r
+        mov     bx, [Count]\r
+        add     bx, bx\r
+        add     bx, [Count]             ; BX = Count*3\r
+\r
+        lds     si, [Palette]           ; DS:SI -> palette\r
+        push    ss\r
+        pop     es\r
+        lea     di, Holder              ; ES:DI -> local space\r
+        cld\r
+\r
+        mov     ax, [Step]\r
+        mov     dx, ax\r
+        test    ax, ax\r
+        jz      @@Exit                  ; Nothing to do, exit\r
+        jl      @@RightToLeft\r
+\r
+@@LeftToRight:\r
+        add     ax, ax\r
+        add     dx, ax                  ; DX = Step*3\r
+        sub     bx, dx                  ; BX = (Count-Step)*3\r
+        add     si, bx\r
+        push    si\r
+        mov     cx, dx\r
+        rep     movsb\r
+        mov     es, WORD PTR Palette[2]\r
+        mov     di, si\r
+        dec     di                      ; ES:DI -> last byte of palette\r
+        pop     si\r
+        dec     si\r
+        mov     cx, bx\r
+        std\r
+        rep     movsb\r
+        push    ss\r
+        pop     ds\r
+        lea     si, Holder\r
+        les     di, [Palette]\r
+        mov     cx, dx\r
+        cld\r
+        rep     movsb\r
+        jmp     @@Exit\r
+\r
+@@RightToLeft:\r
+        add     ax, ax\r
+        add     dx, ax\r
+        neg     dx                      ; DX = Step*3\r
+        sub     bx, dx                  ; BX = (Count-Step)*3\r
+        mov     cx, dx\r
+        rep     movsb\r
+        les     di, [Palette]\r
+        mov     cx, bx\r
+        rep     movsb\r
+        push    ss\r
+        pop     ds\r
+        lea     si, Holder\r
+        mov     cx, dx\r
+        rep     movsb\r
+\r
+@@Exit:\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxRotatePalette ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxsa.asm b/16/x/mxsa.asm
new file mode 100755 (executable)
index 0000000..3ebae67
--- /dev/null
@@ -0,0 +1,44 @@
+;-----------------------------------------------------------\r
+;\r
+; MXSA.ASM - Start address function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxStartAddress\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Modifies the starting address of video memory.\r
+;\r
+; Input:\r
+;       StartAddr       = new start address of video memory\r
+; Output:\r
+;       none\r
+;\r
+mxStartAddress  PROC    FAR\r
+        ARG     StartAddr:WORD  = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+\r
+        mov     bx, [StartAddr]\r
+        mov     dx, CRTC\r
+        mov     al, 0Ch                 ; Linear Starting Address high\r
+        mov     ah, bh\r
+        cli\r
+        out     dx, ax\r
+        mov     al, 0Dh                 ; Linear Starting Address low\r
+        mov     ah, bl\r
+        out     dx, ax\r
+        sti\r
+\r
+        .leave  ARG_SIZE\r
+mxStartAddress  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxsc.asm b/16/x/mxsc.asm
new file mode 100755 (executable)
index 0000000..bcae45e
--- /dev/null
@@ -0,0 +1,50 @@
+;-----------------------------------------------------------\r
+;\r
+; MXSC.ASM - Set color function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxSetColor\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Updates the selected DAC register.\r
+;\r
+; Input:\r
+;       Index   = index of color to set\r
+;       R, G, B = color components\r
+; Output:\r
+;       none\r
+;\r
+mxSetColor      PROC FAR\r
+        ARG     B:BYTE:2,       \\r
+                G:BYTE:2,       \\r
+                R:BYTE:2,       \\r
+                Index:WORD      = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+\r
+        mov     ax, [Index]\r
+        mov     dx, 3C8h                ; PEL write address register\r
+        out     dx, al\r
+        inc     dx\r
+\r
+        mov     al, [R]\r
+        out     dx, al\r
+        mov     al, [G]\r
+        out     dx, al\r
+        mov     al, [B]\r
+        out     dx, al\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxSetColor      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxsi.asm b/16/x/mxsi.asm
new file mode 100755 (executable)
index 0000000..b88d3b1
--- /dev/null
@@ -0,0 +1,317 @@
+;-----------------------------------------------------------\r
+;\r
+; MXPI.ASM - Stretch image\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxStretchImage\r
+\r
+EXTRN   subClipBox              : NEAR\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+mxTable LABEL   WORD                    ; Raster ops\r
+        DW      subMove\r
+        DW      subAnd\r
+        DW      subOr\r
+        DW      subXor\r
+        DW      subTrans\r
+        DW      subAdd\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Stretches and copies a "raw" image from memory to screen.\r
+;\r
+; Input:\r
+;       Image     = pointer to image\r
+;       X, Y      = coordinates of destination\r
+;       Width     = width of image in pixels\r
+;       Height    = height of image in pixels\r
+;       NewWidth  = new width of image in pixels\r
+;       NewHeight = new height of image in pixels\r
+;       Op        = raster op (OP_xxx)\r
+; Output:\r
+;       none\r
+;\r
+mxStretchImage  PROC    FAR\r
+        ARG     Op:WORD,                \\r
+                NewHeight:WORD,         \\r
+                NewWidth:WORD,          \\r
+                Height:WORD,            \\r
+                Width:WORD,             \\r
+                Y:WORD,                 \\r
+                X:WORD,                 \\r
+                Image:DWORD             = ARG_SIZE\r
+        LOCAL   PixelOffset:WORD,       \\r
+                MoveFunction:WORD,      \\r
+                ReadPlane:BYTE,         \\r
+                OpInfo:BYTE,            \\r
+                WidthStep:DWORD,        \\r
+                HeightStep:DWORD,       \\r
+                ImageLo:WORD,           \\r
+                WritePlane:BYTE         = AUTO_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+\r
+; Get width stretch factor\r
+    IF USE386 EQ TRUE\r
+        movzx   edx, [Width]\r
+        xor     eax, eax\r
+        movzx   ebx, [NewWidth]\r
+        shl     ebx, 16\r
+        idiv    ebx\r
+        mov     [WidthStep], eax\r
+    ELSE\r
+        xor     dx, dx                  ; Width stretch factor\r
+        mov     ax, [Width]\r
+        mov     bx, [NewWidth]\r
+        div     bx\r
+        mov     WORD PTR WidthStep[2], ax\r
+        xor     ax, ax\r
+        div     bx\r
+        mov     WORD PTR WidthStep[0], ax\r
+    ENDIF\r
+; Get height stretch factor\r
+    IF USE386 EQ TRUE\r
+        movzx   edx, [Height]\r
+        xor     eax, eax\r
+        movzx   ebx, [NewHeight]\r
+        shl     ebx, 16\r
+        idiv    ebx\r
+        mov     [HeightStep], eax\r
+    ELSE\r
+        xor     dx, dx\r
+        mov     ax, [Height]\r
+        mov     bx, [NewHeight]\r
+        div     bx\r
+        mov     WORD PTR HeightStep[2], ax\r
+        xor     ax, ax\r
+        div     bx\r
+        mov     WORD PTR HeightStep[0], ax\r
+   ENDIF\r
+\r
+; Clip image\r
+        mov     bx, [X]\r
+        mov     ax, [Y]\r
+        mov     cx, [NewWidth]\r
+        mov     dx, [NewHeight]\r
+        call    subClipBox\r
+        jc      @@Exit                  ; Full clipped\r
+        mov     [NewWidth], cx\r
+        mov     [NewHeight], dx\r
+        sub     [X], bx\r
+        sub     [Y], ax\r
+\r
+; Get pixel address\r
+        mul     [mx_BytesPerLine]\r
+        mov     di, bx\r
+        shr     di, 1\r
+        shr     di, 1\r
+        add     di, ax\r
+        mov     [PixelOffset], di\r
+        mov     es, [mx_VideoSegment]   ; ES:DI points to pixel\r
+        and     bl, 03h\r
+        mov     [ReadPlane], bl         ; Set read plane\r
+        mov     cl, bl\r
+        mov     al, 00010001b\r
+        shl     al, cl\r
+        mov     [WritePlane], al        ; Set write plane\r
+\r
+; Relocate image origin if previously clipped\r
+        mov     ax, [Y]\r
+        test    ax, ax\r
+        jz      @@OriginYDone\r
+    IF USE386 EQ TRUE\r
+        shl     eax, 16\r
+        imul    [HeightStep]\r
+        mov     ax, [Width]\r
+        mul     dx\r
+    ELSE\r
+        mov     bx, ax\r
+        mul     WORD PTR HeightStep[0]\r
+        mov     cx, dx\r
+        mov     ax, bx\r
+        mul     WORD PTR HeightStep[2]\r
+        add     ax, cx\r
+        mul     [Width]\r
+    ENDIF\r
+        add     WORD PTR [Image], ax\r
+@@OriginYDone:\r
+        mov     ax, [X]\r
+        test    ax, ax\r
+        jz      @@OriginXDone\r
+    IF USE386 EQ TRUE\r
+        shl     eax, 16\r
+        imul    [WidthStep]\r
+        add     WORD PTR [Image], dx\r
+    ELSE\r
+        mov     bx, ax\r
+        mul     WORD PTR WidthStep[0]\r
+        mov     cx, dx\r
+        mov     ax, bx\r
+        mul     WORD PTR WidthStep[2]\r
+        add     ax, cx\r
+        add     WORD PTR [Image], ax\r
+    ENDIF\r
+@@OriginXDone:\r
+        mov     ax, WORD PTR HeightStep[2]\r
+        mul     [Width]\r
+        mov     WORD PTR HeightStep[2], ax\r
+\r
+; Install move function\r
+        mov     bx, [Op]\r
+        mov     [OpInfo], bh            ; Remember additional info if needed\r
+        xor     bh, bh\r
+        cmp     bl, OP_ADD\r
+        jbe     @@SetMoveFunction\r
+        xor     bl, bl\r
+@@SetMoveFunction:\r
+        shl     bx, 1\r
+        mov     ax, mxTable[bx]\r
+        mov     [MoveFunction], ax\r
+\r
+; Put image\r
+        mov     ds, WORD PTR Image[2]\r
+        xor     ax, ax\r
+        mov     [ImageLo], ax\r
+@@Loop:\r
+        mov     si, WORD PTR Image[0]   ; Get pointer to image\r
+        mov     ah, [WritePlane]\r
+        and     ah, 0Fh\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax                  ; Select write plane\r
+        mov     ah, [ReadPlane]\r
+        and     ah, 03h\r
+        mov     al, 04h\r
+        mov     dx, GDC\r
+        out     dx, ax                  ; Select read plane\r
+        mov     cx, [NewHeight]\r
+        mov     di, [PixelOffset]       ; ES:DI points to video memory\r
+        mov     ah, [OpInfo]            ; Additional raster op info\r
+        xor     bx, bx\r
+        mov     dx, [mx_BytesPerLine]\r
+        call    [MoveFunction]          ; Draw column\r
+        inc     [ReadPlane]             ; Next read plane\r
+        rol     [WritePlane], 1         ; Next write plane\r
+        adc     [PixelOffset], 0        ; Update video offset if needed\r
+        mov     dx, WORD PTR WidthStep[0]\r
+        mov     ax, WORD PTR WidthStep[2]\r
+        add     [ImageLo], dx\r
+        adc     WORD PTR Image[0], ax   ; Next image column\r
+        dec     [NewWidth]\r
+        jnz     @@Loop                  ; Repeat for all columns\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Move functions, on entry:\r
+;       AH = additional raster op info (e.g. transparent color)\r
+;       BX = 0,\r
+;       CX = pixel count,\r
+;       DX = mx_BytesPerLine.\r
+;\r
+subMove         PROC    NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        mov     es:[di], al\r
+        add     di, dx\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, WORD PTR HeightStep[2]\r
+        add     bx, WORD PTR HeightStep[0]\r
+        jnc     @@Loop\r
+        add     si, [Width]\r
+        jmp     @@Loop\r
+@@Exit: ret\r
+subMove         ENDP\r
+;\r
+subAnd          PROC     NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        and     es:[di], al\r
+        add     di, dx\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, WORD PTR HeightStep[2]\r
+        add     bx, WORD PTR HeightStep[0]\r
+        jnc     @@Loop\r
+        add     si, [Width]\r
+        jmp     @@Loop\r
+@@Exit: ret\r
+subAnd          ENDP\r
+;\r
+subOr           PROC     NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        or      es:[di], al\r
+        add     di, dx\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, WORD PTR HeightStep[2]\r
+        add     bx, WORD PTR HeightStep[0]\r
+        jnc     @@Loop\r
+        add     si, [Width]\r
+        jmp     @@Loop\r
+@@Exit: ret\r
+subOr           ENDP\r
+;\r
+subXor          PROC     NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        xor     es:[di], al\r
+        add     di, dx\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, WORD PTR HeightStep[2]\r
+        add     bx, WORD PTR HeightStep[0]\r
+        jnc     @@Loop\r
+        add     si, [Width]\r
+        jmp     @@Loop\r
+@@Exit: ret\r
+subXor          ENDP\r
+;\r
+subTrans        PROC     NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        cmp     al, ah\r
+        je      @@Skip\r
+        mov     es:[di], al\r
+@@Skip:\r
+        add     di, dx\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, WORD PTR HeightStep[2]\r
+        add     bx, WORD PTR HeightStep[0]\r
+        jnc     @@Loop\r
+        add     si, [Width]\r
+        jmp     @@Loop\r
+@@Exit: ret\r
+subTrans        ENDP\r
+;\r
+subAdd          PROC     NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        add     es:[di], al\r
+        add     di, dx\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, WORD PTR HeightStep[2]\r
+        add     bx, WORD PTR HeightStep[0]\r
+        jnc     @@Loop\r
+        add     si, [Width]\r
+        jmp     @@Loop\r
+@@Exit: ret\r
+subAdd          ENDP\r
+\r
+mxStretchImage  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxsl.asm b/16/x/mxsl.asm
new file mode 100755 (executable)
index 0000000..d790885
--- /dev/null
@@ -0,0 +1,62 @@
+;-----------------------------------------------------------\r
+;\r
+; MXLN.ASM - Start line function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxStartLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+        ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Changes the video start address to the specified line.\r
+;\r
+; Input:\r
+;       Line    = new start line\r
+; Output:\r
+;       none\r
+;\r
+mxStartLine     PROC FAR\r
+        ARG     Line:WORD       = ARG_SIZE\r
+        .enter  0\r
+        ASSUME  ds:NOTHING\r
+\r
+        mov     ax, [Line]              ; Get video offset\r
+        mul     [mx_BytesPerLine]\r
+        xchg    ax, bx                  ; Copy it into BX\r
+\r
+; Wait display\r
+        mov     dx, STATUS\r
+@@1:    in      al, dx\r
+        test    al, 08h\r
+        jnz     @@1\r
+\r
+; Set starting address\r
+        mov     dx, CRTC\r
+        mov     al, 0Ch                 ; Linear Starting Address high\r
+        mov     ah, bh\r
+        cli\r
+        out     dx, ax\r
+        mov     al, 0Dh                 ; Linear Starting Address low\r
+        mov     ah, bl\r
+        out     dx, ax\r
+        sti\r
+\r
+; Wait retrace\r
+        mov     dx, STATUS\r
+@@2:    in      al,dx\r
+        test    al, 08h\r
+        jz      @@2\r
+\r
+        xor     ax, ax\r
+        .leave  ARG_SIZE\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxsm.asm b/16/x/mxsm.asm
new file mode 100755 (executable)
index 0000000..183fba1
--- /dev/null
@@ -0,0 +1,508 @@
+;-----------------------------------------------------------\r
+;\r
+; MXSM.ASM - Set/change mode functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxChangeMode\r
+PUBLIC  mxGetAspect\r
+PUBLIC  mxGetScreenSize\r
+PUBLIC  mxSetMode\r
+\r
+PUBLIC  mx_ScreenWidth\r
+PUBLIC  mx_ScreenHeight\r
+PUBLIC  mx_BytesPerLine\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mxSetSysClipRegion      : FAR\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_CodeSegment  : WORD\r
+\r
+mx_ScreenWidth  DW      ?               ; Current screen width\r
+mx_ScreenHeight DW      ?\r
+mx_AspectX      DW      ?               ; Aspect ratio for current mode\r
+mx_AspectY      DW      ?\r
+mx_BytesPerLine DW      0               ; Bytes per line\r
+\r
+;\r
+; Tables for setting video modes, sources:\r
+; - MODEX.ASM, Matt Pritchard\r
+; - Dr. Dobb's Journal, Michael Abrash\r
+; - Fractint VIDEO.ASM module\r
+;\r
+TBL_SingleLine  LABEL   WORD            ; CRTC\r
+        DW      04009h                  ; Cell height: 1 scan line\r
+        DW      00014h                  ; Double word mode off\r
+        DW      0E317h                  ; Byte mode on\r
+        DW      0\r
+TBL_DoubleLine  LABEL   WORD            ; CRTC\r
+        DW      04109h                  ; Cell height: 2 scan lines\r
+        DW      00014h\r
+        DW      0E317h\r
+        DW      0\r
+TBL_Width320    LABEL   WORD            ; CRTC\r
+        DW      05F00h                  ; Horizontal total\r
+        DW      04F01h                  ; Horizontal displayed\r
+        DW      05002h                  ; Start horizontal blanking\r
+        DW      08203h                  ; End horizontal blanking\r
+        DW      05404h                  ; Start horizontal sync\r
+        DW      08005h                  ; End horizontal sync\r
+        DW      02813h                  ; Row address\r
+        DW      0\r
+TBL_Width360    LABEL   WORD            ; CRTC\r
+        DW      06B00h                  ; Horizontal total\r
+        DW      05901h                  ; Horizontal displayed\r
+        DW      05A02h                  ; Start horizontal blanking\r
+        DW      08E03h                  ; End horizontal blanking\r
+        DW      05E04h                  ; Start horizontal sync\r
+        DW      08A05h                  ; End horizontal sync\r
+        DW      02D13h                  ; Row address\r
+        DW      0\r
+TBL_Height175   LABEL   WORD            ; CRTC\r
+        DW      0BF06h                  ; Vertical total\r
+        DW      01F07h                  ; Overflow\r
+        DW      08310h                  ; Start vertical sync\r
+        DW      08511h                  ; End vertical sync\r
+        DW      05D12h                  ; Vertical displayed\r
+        DW      06315h                  ; Start vertical blanking\r
+        DW      0BA16h                  ; End vertical blanking\r
+        DW      0\r
+TBL_Height200   LABEL   WORD            ; CRTC\r
+        DW      0BF06h                  ; Vertical total\r
+        DW      01F07h                  ; Overflow\r
+        DW      09C10h                  ; Start vertical sync\r
+        DW      08E11h                  ; End vertical sync\r
+        DW      08F12h                  ; Vertical displayed\r
+        DW      09615h                  ; Start vertical blanking\r
+        DW      0B916h                  ; End vertical blanking\r
+        DW      0\r
+TBL_Height240   LABEL   WORD            ; CRTC\r
+        DW      00D06h                  ; Vertical total\r
+        DW      03E07h                  ; Overflow\r
+        DW      0EA10h                  ; Start vertical sync\r
+        DW      08C11h                  ; End vertical sync\r
+        DW      0DF12h                  ; Vertical displayed\r
+        DW      0E715h                  ; Start vertical blanking\r
+        DW      00616h                  ; End vertical blanking\r
+        DW      0\r
+TBL_Tweak400x600:\r
+        DW      07400h\r
+        DW      06301h\r
+        DW      06402h\r
+        DW      09703h\r
+        DW      06804h\r
+        DW      09505h\r
+        DW      08606h\r
+        DW      0F007h\r
+        DW      06009h\r
+        DW      0310Fh\r
+        DW      05B10h\r
+        DW      08D11h\r
+        DW      05712h\r
+        DW      03213h\r
+        DW      00014h\r
+        DW      06015h\r
+        DW      08016h\r
+        DW      0E317h\r
+        DW      0\r
+\r
+TBL_320x200:\r
+        DB      63h                     ; 400 scan lines, 25 MHz clock\r
+        DW      6, 5                    ; Aspect: 6/5 = 1.2:1\r
+        DW      320, 200                ; Size\r
+        DW      TBL_Width320, TBL_Height200, TBL_DoubleLine, 0\r
+        DW      819                     ; Max height\r
+TBL_320x240:\r
+        DB      0E3h                    ; 400 scan lines, 25 MHz clock\r
+        DW      1, 1                    ; Aspect: 1/1 = 1:1\r
+        DW      320, 240                ; Size\r
+        DW      TBL_Width320, TBL_Height240, TBL_DoubleLine, 0\r
+        DW      819                     ; Max height\r
+TBL_320x400:\r
+        DB      63h                     ; 480 scan lines, 25 MHz clock\r
+        DW      6, 10                   ; Aspect: 6/10 = 0.6:1\r
+        DW      320, 400                ; Size\r
+        DW      TBL_Width320, TBL_Height200, TBL_SingleLine, 0\r
+        DW      819                     ; Max height\r
+TBL_320x480:\r
+        DB      0E3h                    ; 480 scan lines, 25 MHz clock\r
+        DW      1, 2                    ; Aspect: 1/2 = 0.5:1\r
+        DW      320, 480                ; Size\r
+        DW      TBL_Width320, TBL_Height240, TBL_SingleLine, 0\r
+        DW      819                     ; Max height\r
+TBL_360x200:\r
+        DB      067h                    ; 400 scan lines, 28 MHz clock\r
+        DW      27, 20                  ; Aspect: 27/20 = 1.35:1\r
+        DW      360, 200                ; Size\r
+        DW      TBL_Width360, TBL_Height200, TBL_DoubleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_360x240:\r
+        DB      0E7h                    ; 480 scan lines, 28 MHz clock\r
+        DW      9, 8                    ; Aspect: 9/8 = 1.125:1\r
+        DW      360, 240                ; Size\r
+        DW      TBL_Width360, TBL_Height240, TBL_DoubleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_360x400:\r
+        DB      067h                    ; 400 scan lines, 28 MHz clock\r
+        DW      27, 40                  ; Aspect: 27/40 = 0.675:1\r
+        DW      360, 400                ; Size\r
+        DW      TBL_Width360, TBL_Height200, TBL_SingleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_360x480:\r
+        DB      0E7h                    ; 480 scan lines, 28 MHz clock\r
+        DW      9, 16                   ; Aspect: 9/16 = 0.5625:1\r
+        DW      360, 480                ; Size\r
+        DW      TBL_Width360, TBL_Height240, TBL_SingleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_320x175:\r
+        DB      0A3h\r
+        DW      0, 0                    ; Aspect:\r
+        DW      320, 175\r
+        DW      TBL_Width320, TBL_Height175, TBL_DoubleLine, 0\r
+        DW      819\r
+TBL_320x350:\r
+        DB      0A3h\r
+        DW      0, 0                    ; Aspect:\r
+        DW      320, 175\r
+        DW      TBL_Width320, TBL_Height175, TBL_SingleLine, 0\r
+        DW      819\r
+TBL_360x175:\r
+        DB      0A7h\r
+        DW      0, 0                    ; Aspect:\r
+        DW      360, 480                ; Size\r
+        DW      TBL_Width360, TBL_Height175, TBL_DoubleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_360x350:\r
+        DB      0A7h\r
+        DW      0, 0                    ; Aspect:\r
+        DW      360, 480                ; Size\r
+        DW      TBL_Width360, TBL_Height175, TBL_SingleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_400x600:\r
+        DB      0E7h                    ; 28 MHz clock\r
+        DW      1, 2                    ; Aspect: 1/2 = 0.5:1\r
+        DW      400, 600                ; Size\r
+        DW      TBL_Tweak400x600, 0\r
+        DW      655                     ; Max height\r
+\r
+TBL_Mode        LABEL   WORD\r
+        DW      TBL_320x175\r
+        DW      TBL_320x200\r
+        DW      TBL_320x240\r
+        DW      TBL_320x350\r
+        DW      TBL_320x400\r
+        DW      TBL_320x480\r
+        DW      TBL_360x175\r
+        DW      TBL_360x200\r
+        DW      TBL_360x240\r
+        DW      TBL_360x350\r
+        DW      TBL_360x400\r
+        DW      TBL_360x480\r
+        DW      TBL_400x600\r
+\r
+MAXVMODE        EQU     ($-OFFSET TBL_Mode) / 2\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Enables 80x25 color text mode\r
+;\r
+subText         PROC    NEAR\r
+        ASSUME  ds:MX_TEXT\r
+        mov     ax, 0003h\r
+        int     10h                     ; Call BIOS set mode\r
+\r
+        mov     [mx_ScreenHeight], 0\r
+        mov     [mx_BytesPerLine], 0\r
+        ret\r
+subText         ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Enables the selected graphics mode.\r
+;\r
+; Input:\r
+;       Mode    = mode to select (MX_???x???)\r
+; Output:\r
+;       none\r
+;\r
+mxSetMode       PROC    FAR\r
+        ARG     Mode:WORD       = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si, es, di\r
+\r
+; Set DS to code segment alias\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     si, [Mode]\r
+        cmp     si, MAXVMODE            ; Is it a valid mode?\r
+        ja      @@Exit                  ; No, exit\r
+        test    si, si                  ; Text mode?\r
+        jnz     @@Set                   ; No, handle it\r
+\r
+        call    subText                 ; Back to text mode\r
+        jmp     @@Exit                  ; Exit now\r
+\r
+; Set video mode\r
+@@Set:\r
+        dec     si                      ; Skip text mode\r
+        shl     si, 1\r
+        mov     si, TBL_Mode[si]\r
+        cld\r
+\r
+; Use BIOS to set 320x200x256 linear mode\r
+        push    si                      ; Save SI\r
+        mov     ax, 0013h\r
+        int     10h                     ; Use BIOS to set 320x200 linear mode\r
+        pop     si                      ; Restore SI\r
+\r
+        mov     dx, TS\r
+        mov     ax, 0604h\r
+        out     dx, ax                  ; Disable chain-4 mode\r
+        mov     ax, 0100h\r
+        out     dx, ax                  ; Reset\r
+        mov     dx, MISC\r
+        lodsb\r
+        out     dx, al                  ; New timing/size\r
+        mov     dx, TS\r
+        mov     ax, 0300h\r
+        out     dx, ax                  ; Restart sequencer\r
+\r
+; Unlock CRTC registers 0-7\r
+        mov     dx, CRTC\r
+        mov     al, 11h\r
+        out     dx, al                  ; Vertical sync end register\r
+        inc     dx\r
+        in      al, dx\r
+        and     al, 7Fh                 ; Clear write protect bit\r
+        out     dx, al\r
+\r
+        lodsw                           ; Get X aspect\r
+        mov     [mx_AspectX], ax\r
+        lodsw                           ; Get Y aspect\r
+        mov     [mx_AspectY], ax\r
+        lodsw                           ; Get screen width\r
+        mov     [mx_ScreenWidth], ax\r
+        shr     ax, 1\r
+        shr     ax, 1                   ; Divide by four to get bytes per line\r
+        mov     [mx_BytesPerLine], ax\r
+        lodsw                           ; Get screen height\r
+        mov     [mx_ScreenHeight], ax\r
+\r
+; Set CRTC registers\r
+        mov     bx, si\r
+        mov     dx, CRTC\r
+@@TableLoop:\r
+        mov     si, ds:[bx]             ; DS:SI -> table of CRTC registers\r
+        inc     bx\r
+        inc     bx                      ; DS:BX -> offset of next table\r
+        test    si, si                  ; Last table?\r
+        jz      @@EndLoop               ; Yes, exit loop\r
+@@Loop:\r
+        lodsw                           ; Get CRTC register index and value\r
+        test    ax, ax                  ; End of table?\r
+        jz      @@TableLoop             ; Yes, go to next table\r
+        out     dx, ax                  ; Set register AL to value AH\r
+        jmp     @@Loop                  ; Get next register/value\r
+@@EndLoop:\r
+\r
+; Set virtual screen and system clip region\r
+        push    [mx_ScreenWidth]\r
+        push    WORD PTR ds:[bx]\r
+        call    mxSetSysClipRegion\r
+\r
+; Clear video memory\r
+        mov     dx, TS\r
+        mov     ax, 0F02h\r
+        out     dx, ax                  ; Enable all planes\r
+        mov     es, [mx_VideoSegment]\r
+        xor     di, di\r
+        mov     cx, 8000h\r
+        xor     ax, ax\r
+        rep     stosw\r
+\r
+@@Done:\r
+; Lock CRTC registers 0-7 (some cards need this)\r
+        mov     dx, CRTC\r
+        mov     al, 11h\r
+        out     dx, al                  ; Vertical sync end register\r
+        inc     dx\r
+        in      al, dx\r
+        or      al, 80h                 ; Set write protect bit\r
+        out     dx, al\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        mov     ax, [mx_ScreenWidth]\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxSetMode       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Changes from the current mode the selected graphics mode.\r
+;\r
+; Input:\r
+;       Mode    = mode to select (MX_???x???)\r
+; Output:\r
+;       none\r
+; Notes:\r
+;       this function assumes that mxSetMode and mxSetVirtualScreen\r
+;       have been called first. View size is rearranged to match the\r
+;       specified mode, but video memory is not cleared.\r
+;       Differences from mxSetMode:\r
+;       - video BIOS is not called to initialize graphics;\r
+;       - row address register is not modified;\r
+;       - video memory is not cleared;\r
+;       - mx_BytesPerLine is not modified;\r
+;       - system clip region is not modified.\r
+;\r
+mxChangeMode    PROC    FAR\r
+        ARG     Mode:WORD       = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si, es, di\r
+\r
+; Set DS to code segment alias\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     si, [Mode]\r
+        cmp     si, MAXVMODE            ; Is it a valid mode?\r
+        ja      @@Exit                  ; No, exit\r
+        test    si, si                  ; Text mode?\r
+        jz      @@Exit                  ; Yes, exit\r
+\r
+        dec     si                      ; Skip text mode\r
+        shl     si, 1\r
+        mov     si, TBL_Mode[si]\r
+        cld\r
+\r
+        mov     dx, TS\r
+        mov     ax, 0604h\r
+        out     dx, ax                  ; Disable chain-4 mode\r
+        mov     ax, 0100h\r
+        out     dx, ax                  ; Reset\r
+        mov     dx, MISC\r
+        lodsb\r
+        out     dx, al                  ; New timing/size\r
+        mov     dx, TS\r
+        mov     ax, 0300h\r
+        out     dx, ax                  ; Restart sequencer\r
+\r
+; Unlock CRTC registers 0-7\r
+        mov     dx, CRTC\r
+        mov     al, 11h\r
+        out     dx, al                  ; Vertical sync end register\r
+        inc     dx\r
+        in      al, dx\r
+        and     al, 7Fh                 ; Clear write protect bit\r
+        out     dx, al\r
+\r
+        lodsw                           ; Get X aspect\r
+        mov     [mx_AspectX], ax\r
+        lodsw                           ; Get Y aspect\r
+        mov     [mx_AspectY], ax\r
+        lodsw                           ; Get screen width\r
+        mov     [mx_ScreenWidth], ax\r
+        lodsw                           ; Get screen height\r
+        mov     [mx_ScreenHeight], ax\r
+\r
+; Set CRTC registers\r
+        mov     bx, si\r
+        mov     dx, CRTC\r
+@@TableLoop:\r
+        mov     si, ds:[bx]             ; DS:SI -> table of CRTC registers\r
+        inc     bx\r
+        inc     bx                      ; DS:BX -> offset of next table\r
+        test    si, si                  ; Last table?\r
+        jz      @@EndLoop               ; Yes, exit loop\r
+@@Loop:\r
+        lodsw                           ; Get CRTC register index and value\r
+        test    ax, ax                  ; End of table?\r
+        jz      @@TableLoop             ; Yes, go to next table\r
+        cmp     al, 13h                 ; Row address register?\r
+        je      @@Loop                  ; Yes, ignore it\r
+        out     dx, ax                  ; Set register AL to value AH\r
+        jmp     @@Loop                  ; Get next register/value\r
+@@EndLoop:\r
+\r
+; Lock CRTC registers 0-7 (some cards need this)\r
+        mov     dx, CRTC\r
+        mov     al, 11h\r
+        out     dx, al                  ; Vertical sync end register\r
+        inc     dx\r
+        in      al, dx\r
+        or      al, 80h                 ; Set write protect bit\r
+        out     dx, al\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        mov     ax, [mx_ScreenWidth]\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxChangeMode    ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the aspect ratio for the current mode.\r
+;\r
+; Input:\r
+;       AspectX = pointer to aspect X\r
+;       AspectY = pointer to aspect Y\r
+;\r
+; A rectangle of width AspectX and height AspectY looks like a square.\r
+;\r
+mxGetAspect     PROC FAR\r
+        ARG     AspectY:DWORD,  \\r
+                AspectX:DWORD   = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+        ASSUME  ds:NOTHING\r
+\r
+        lds     si, [AspectX]\r
+        mov     ax, [mx_AspectX]\r
+        mov     ds:[si], ax\r
+        lds     si, [AspectY]\r
+        mov     ax, [mx_AspectY]\r
+        mov     ds:[si], ax\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetAspect     ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current screen size.\r
+;\r
+; Input:\r
+;       Width   = pointer to screen width\r
+;       Height  = pointer to screen height\r
+;\r
+mxGetScreenSize PROC FAR\r
+        ARG     SizeY:DWORD,    \\r
+                SizeX:DWORD     = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+        ASSUME  ds:NOTHING\r
+\r
+        lds     si, [SizeX]\r
+        mov     ax, [mx_ScreenWidth]\r
+        mov     ds:[si], ax\r
+        lds     si, [SizeY]\r
+        mov     ax, [mx_ScreenHeight]\r
+        mov     ds:[si], ax\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetScreenSize ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxsp.asm b/16/x/mxsp.asm
new file mode 100755 (executable)
index 0000000..1d08e71
--- /dev/null
@@ -0,0 +1,57 @@
+;-----------------------------------------------------------\r
+;\r
+; MXSP.ASM - Set palette function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxSetPalette\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Updates the VGA palette.\r
+;\r
+; Input:\r
+;       Buffer          = pointer to palette data (R,G,B)\r
+;       Start           = index of first color to set\r
+;       Count           = number of color to set\r
+; Output:\r
+;       none\r
+;\r
+mxSetPalette    PROC    FAR\r
+        ARG     Count:WORD,             \\r
+                Start:WORD,             \\r
+                Buffer:DWORD            = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si\r
+\r
+        lds     si, [Buffer]\r
+        mov     cx, [Count]\r
+        mov     ax, [Start]\r
+        mov     dx, 3C8h                ; PEL write address register\r
+        out     dx, al\r
+        inc     dx\r
+        cld\r
+        cli                             ; Disable interrupts\r
+@@Loop:\r
+        lodsb\r
+        out     dx, al                  ; Red\r
+        lodsb\r
+        out     dx, al                  ; Green\r
+        lodsb\r
+        out     dx, al                  ; Blue\r
+        loop    @@Loop                  ; Loop until done\r
+        sti                             ; Enable interrupts\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxSetPalette    ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxss.asm b/16/x/mxss.asm
new file mode 100755 (executable)
index 0000000..97df736
--- /dev/null
@@ -0,0 +1,72 @@
+;-----------------------------------------------------------\r
+;\r
+; MXSS.ASM - Split screen function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxSplitScreen\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Splits the screen.\r
+;\r
+; Input:\r
+;       Line    = scan line at which screen has to be splitted\r
+; Output:\r
+;       none\r
+;\r
+mxSplitScreen   PROC    FAR\r
+        ARG     Line:WORD       = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+\r
+; Modify the line compare value: bits 0-7 are in the Line Compare\r
+; register (CRTC #18), bit 8 is in the Overflow Low register (CRTC #7)\r
+; and bit 9 is in the Maximum Row Address register (CRTC #9)\r
+        mov     ax, [Line]\r
+        shl     ax, 1                   ; Adjust line for mode "X"\r
+        mov     bh, ah\r
+        mov     bl, ah\r
+        and     bx, 0201h\r
+        mov     cl, 4\r
+        shl     bx, cl\r
+        shl     bh, 1\r
+        mov     dx, CRTC\r
+; Write bits 0-7 to line compare register\r
+        mov     ah, al\r
+        mov     al, 18h\r
+        out     dx, ax\r
+; Write bit 8 to overflow register\r
+        mov     al, 07h\r
+        out     dx, al\r
+        inc     dx\r
+        in      al, dx\r
+        dec     dx\r
+        mov     ah, al\r
+        and     ah, 11101111b\r
+        or      ah, bl\r
+        mov     al, 07h\r
+        out     dx, ax\r
+; Write bit 9 to maximum row address register\r
+        mov     al, 09h\r
+        out     dx, al\r
+        inc     dx\r
+        in      al, dx\r
+        dec     dx\r
+        mov     ah, al\r
+        and     ah, 10111111b\r
+        or      ah, bh\r
+        mov     al, 09h\r
+        out     dx, ax\r
+\r
+        .leave  ARG_SIZE\r
+mxSplitScreen   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxtl.asm b/16/x/mxtl.asm
new file mode 100755 (executable)
index 0000000..69900c8
--- /dev/null
@@ -0,0 +1,169 @@
+;-----------------------------------------------------------\r
+;\r
+; MXTL.ASM - Put tile\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxPutTile\r
+PUBLIC  mxTransPutTile\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies a "mode-x" tile from memory to screen.\r
+;\r
+; Input:\r
+;       Image   = pointer to tile\r
+;       X, Y    = coordinates of destination\r
+;       Width   = width of image in pixels (Width and 3 = 0)\r
+;       Height  = height of image in pixels\r
+; Output:\r
+;       none\r
+; Note:\r
+;       no clipping is performed on tiles!\r
+;\r
+mxPutTile       PROC    FAR\r
+        ARG     Height:WORD,            \\r
+                Width:WORD,             \\r
+                Y:WORD,                 \\r
+                X:WORD,                 \\r
+                Image:DWORD             = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si, es, di\r
+\r
+        mov     ax, [Y]                 ; Get pixel address\r
+        mul     [mx_BytesPerLine]\r
+        mov     di, [X]\r
+        .shr    di, 2\r
+        add     di, ax\r
+        mov     es, [mx_VideoSegment]\r
+\r
+        lds     si, [Image]             ; Get tile address\r
+        .shr    [Width], 2              ; Number of bytes per plane\r
+        mov     cl, BYTE PTR [X]\r
+        and     cl, 3\r
+        mov     ah, 11h                 ; AH = plane mask\r
+        shl     ah, cl                  ; Align mask to first plane\r
+\r
+        mov     [Y], 4                  ; Number of planes\r
+        mov     bx, [mx_BytesPerLine]\r
+        sub     bx, [Width]             ; Extra bytes per line\r
+@@Loop:\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax                  ; Set write plane\r
+        mov     [X], di                 ; Save video offset\r
+        mov     dx, [Height]\r
+@@Loop2:\r
+        mov     cx, [Width]             ; Number of bytes to move\r
+\r
+        shr     cx, 1                   ; Move line\r
+        rep     movsw\r
+        rcl     cx, 1\r
+        rep     movsb\r
+\r
+        add     di, bx                  ; Move video offset to next line\r
+        dec     dx                      ; Done all lines?\r
+        jnz     @@Loop2                 ; No, continue\r
+        mov     di, [X]                 ; Restore video offset\r
+        rol     ah, 1                   ; Next plane\r
+        adc     di, 0                   ; Bump video offset if needed\r
+        dec     [Y]                     ; Any plane left?\r
+        jnz     @@Loop                  ; Yes, keep looping\r
+\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxPutTile       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies a "mode-x" tile from memory to screen.\r
+; Skips over color 0.\r
+;\r
+; Input:\r
+;       Image   = pointer to tile\r
+;       X, Y    = coordinates of destination\r
+;       Width   = width of image in pixels (Width and 3 = 0)\r
+;       Height  = height of image in pixels\r
+; Output:\r
+;       none\r
+; Note:\r
+;       no clipping is performed on tiles!\r
+;\r
+mxTransPutTile  PROC    FAR\r
+        ARG     Height:WORD,            \\r
+                Width:WORD,             \\r
+                Y:WORD,                 \\r
+                X:WORD,                 \\r
+                Image:DWORD             = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si, es, di\r
+\r
+        mov     ax, [Y]                 ; Get pixel address\r
+        mul     [mx_BytesPerLine]\r
+        mov     di, [X]\r
+        .shr    di, 2\r
+        add     di, ax\r
+        mov     es, [mx_VideoSegment]\r
+\r
+        lds     si, [Image]             ; Get tile address\r
+        .shr    [Width], 2              ; Number of bytes per plane\r
+        mov     cl, BYTE PTR [X]\r
+        and     cl, 3\r
+        mov     ah, 11h                 ; AH = plane mask\r
+        shl     ah, cl                  ; Align mask to first plane\r
+\r
+        mov     [Y], 4                  ; Number of planes\r
+        mov     bx, [mx_BytesPerLine]\r
+        sub     bx, [Width]             ; Extra bytes per line\r
+@@Loop:\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax                  ; Set write plane\r
+        mov     [X], di                 ; Save video offset\r
+        mov     dx, [Height]\r
+@@Loop2:\r
+        mov     cx, [Width]             ; Number of bytes to move\r
+\r
+; Move one line\r
+        jcxz    @@MoveLineDone\r
+@@MoveLineLoop:\r
+        mov     al, ds:[si]\r
+        test    al, al\r
+        jz      @@MoveLineNext\r
+        mov     es:[di], al\r
+@@MoveLineNext:\r
+        inc     si\r
+        inc     di\r
+        dec     cx\r
+        jnz     @@MoveLineLoop\r
+@@MoveLineDone:\r
+\r
+        add     di, bx                  ; Move video offset to next line\r
+        dec     dx                      ; Done all lines?\r
+        jnz     @@Loop2                 ; No, continue\r
+        mov     di, [X]                 ; Restore video offset\r
+        rol     ah, 1                   ; Next plane\r
+        adc     di, 0                   ; Bump video offset if needed\r
+        dec     [Y]                     ; Any plane left?\r
+        jnz     @@Loop                  ; Yes, keep looping\r
+\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxTransPutTile  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxvs.asm b/16/x/mxvs.asm
new file mode 100755 (executable)
index 0000000..992eaba
--- /dev/null
@@ -0,0 +1,110 @@
+;-----------------------------------------------------------\r
+;\r
+; MXVS.ASM - Set/get virtual screen\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxSetVirtualScreen\r
+PUBLIC  mxGetVirtualScreen\r
+\r
+EXTRN   mxRowAddress            : FAR\r
+EXTRN   mxSetSysClipRegion      : FAR\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_CodeSegment  : WORD\r
+\r
+mx_VirtualWidth         DW      ?       ; Virtual screen size\r
+mx_VirtualHeight        DW      ?\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the virtual screen.\r
+;\r
+; Input:\r
+;       Width   = virtual screen width\r
+;       Height  = virtual screen height\r
+; Output:\r
+;       0 on success, else invalid parameters\r
+;\r
+mxSetVirtualScreen      PROC    FAR\r
+        ARG     Height:WORD,            \\r
+                Width:WORD              = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds\r
+\r
+; Set DS to code segment\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, 1                   ; Assume an error\r
+        cmp     [Width], 320            ; Check width\r
+        jb      @@Exit\r
+        push    ax                      ; Save return code\r
+        mov     dx, 0004h\r
+        xor     ax, ax                  ; DX:AX = 256K\r
+        div     [Width]                 ; Max height in AX\r
+        cmp     [Height], ax\r
+        pop     ax                      ; Restore return code\r
+        ja      @@Exit                  ; Exit if bad heigth\r
+\r
+        mov     ax, [Width]\r
+        and     ax, 0FFF8h              ; Align to byte\r
+        mov     [mx_VirtualWidth], ax\r
+        shr     ax, 1\r
+        shr     ax, 1\r
+        mov     [mx_BytesPerLine], ax\r
+        shr     ax, 1\r
+        push    ax\r
+        call    mxRowAddress            ; Set row address\r
+        mov     ax, [Height]\r
+        mov     [mx_VirtualHeight], ax\r
+\r
+        push    [Width]\r
+        push    [Height]\r
+        call    mxSetSysClipRegion\r
+        xor     ax, ax\r
+\r
+@@Exit:\r
+        .pop    ds\r
+        .leave  ARG_SIZE\r
+mxSetVirtualScreen      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current virtual screen size.\r
+;\r
+; Input:\r
+;       Width   = pointer to virtual screen width\r
+;       Height  = pointer to virtual screen height\r
+; Output:\r
+;       none\r
+;\r
+mxGetVirtualScreen      PROC    FAR\r
+        ARG     Height:DWORD,           \\r
+                Width:DWORD             = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si\r
+\r
+        mov     ax, [mx_VirtualWidth]\r
+        lds     si, [Width]\r
+        mov     ds:[si], ax\r
+        mov     ax, [mx_VirtualHeight]\r
+        lds     si, [Height]\r
+        mov     ds:[si], ax\r
+\r
+        xor     ax, ax\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetVirtualScreen      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxwd.asm b/16/x/mxwd.asm
new file mode 100755 (executable)
index 0000000..de55208
--- /dev/null
@@ -0,0 +1,28 @@
+;-----------------------------------------------------------\r
+;\r
+; MXWD.ASM - Wait display function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxWaitDisplay\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Waits for display start.\r
+;\r
+mxWaitDisplay   PROC    FAR\r
+        mov     dx, STATUS\r
+@@1:    in      al, dx\r
+        test    al, 08h\r
+        jnz     @@1\r
+        ret\r
+mxWaitDisplay   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxwm.asm b/16/x/mxwm.asm
new file mode 100755 (executable)
index 0000000..0615885
--- /dev/null
@@ -0,0 +1,39 @@
+;-----------------------------------------------------------\r
+;\r
+; MXWM.ASM - Set write mode function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxWriteMode\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the write mode.\r
+;\r
+; Input:\r
+;       Mode    = write mode (0,1,2,3)\r
+; Output:\r
+;       none\r
+;\r
+mxWriteMode     PROC    FAR\r
+        ARG     Mode:BYTE:2     = ARG_SIZE\r
+        .enter  0\r
+\r
+        mov     dx, GDC\r
+        mov     ah, [Mode]\r
+        and     ah, 00000011b\r
+        or      ah, 01000000b\r
+        mov     al, 05h\r
+        out     dx, ax\r
+\r
+        .leave  ARG_SIZE\r
+mxWriteMode     ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxwp.asm b/16/x/mxwp.asm
new file mode 100755 (executable)
index 0000000..19ca99d
--- /dev/null
@@ -0,0 +1,62 @@
+;-----------------------------------------------------------\r
+;\r
+; MXWP.ASM - Set write/read plane functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxWritePlane\r
+PUBLIC  mxReadPlane\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the write plane(s).\r
+;\r
+; Input:\r
+;       Plane   = write plane(s) to set (bit 0 enables plane 0,\r
+;                 bit 1 enables plane 1 and so on, different planes\r
+;                 may be selected at the same time)\r
+; Output:\r
+;       none\r
+;\r
+mxWritePlane    PROC    FAR\r
+        ARG     Plane:BYTE:2    = ARG_SIZE\r
+        .enter  0\r
+\r
+        mov     ah, [Plane]\r
+        and     ah, 00001111b           ; Mask off unused bits\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax\r
+\r
+        .leave  ARG_SIZE\r
+mxWritePlane    ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the read plane.\r
+;\r
+; Input:\r
+;       Plane   = read plane to set (0,1,2,3)\r
+; Output:\r
+;       none\r
+;\r
+mxReadPlane     PROC    FAR\r
+        ARG     Plane:BYTE:2    = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        mov     al, 04h\r
+        mov     ah, [Plane]\r
+        and     ah, 0000011b            ; Mask off unused bits\r
+        mov     dx, GDC\r
+        out     dx, ax\r
+        .leave  ARG_SIZE\r
+mxReadPlane     ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/mxwr.asm b/16/x/mxwr.asm
new file mode 100755 (executable)
index 0000000..bd29fe5
--- /dev/null
@@ -0,0 +1,28 @@
+;-----------------------------------------------------------\r
+;\r
+; MXWR.ASM - Wait vertical retrace function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxWaitRetrace\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Waits for vertical retrace start.\r
+;\r
+mxWaitRetrace   PROC    FAR\r
+        mov     dx, STATUS\r
+@@1:    in      al,dx\r
+        test    al, 08h\r
+        jz      @@1\r
+        ret\r
+mxWaitRetrace   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x/readme.txt b/16/x/readme.txt
new file mode 100755 (executable)
index 0000000..306e8b9
--- /dev/null
@@ -0,0 +1,8 @@
+ModeX - A graphical library for DOS programs\r
+Copyright (c) 1993-1994 Alessandro Scotti\r
+http://www.ascotti.org/\r
+\r
+Please look at the above site in the "Art of..." and\r
+then in the "Old programs" section for more information.\r
+\r
+\r
diff --git a/16/x_/MODEX.BAK b/16/x_/MODEX.BAK
new file mode 100755 (executable)
index 0000000..923d02e
Binary files /dev/null and b/16/x_/MODEX.BAK differ
diff --git a/16/x_/default.fnt b/16/x_/default.fnt
new file mode 100755 (executable)
index 0000000..12eb22c
--- /dev/null
@@ -0,0 +1,260 @@
+;\r
+; MODEX library default font\r
+; Copyright (c) 1993-1994 by Alessandro Scotti\r
+;\r
+  DB    000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h  ; #0\r
+  DB   07Eh, 081h, 0A5h, 081h, 0A5h, 099h, 081h, 07Eh  ; #1\r
+  DB   07Eh, 0FFh, 0DBh, 0FFh, 0DBh, 0E7h, 0FFh, 07Eh  ; #2\r
+  DB   06Ch, 0FEh, 0FEh, 0FEh, 07Ch, 038h, 010h, 000h  ; #3\r
+  DB   010h, 038h, 07Ch, 0FEh, 07Ch, 038h, 010h, 000h  ; #4\r
+  DB   010h, 038h, 010h, 054h, 0FEh, 054h, 010h, 0FEh  ; #5\r
+  DB   010h, 038h, 07Ch, 0FEh, 0FEh, 07Ch, 010h, 0FEh  ; #6\r
+  DB   000h, 018h, 03Ch, 07Eh, 07Eh, 03Ch, 018h, 000h  ; #7\r
+  DB   0FFh, 0E7h, 0C3h, 081h, 081h, 0C3h, 0E7h, 0FFh  ; #8\r
+  DB   000h, 03Ch, 066h, 042h, 042h, 066h, 03Ch, 000h  ; #9\r
+  DB   0FFh, 0C3h, 099h, 0BDh, 0BDh, 099h, 0C3h, 0FFh  ; #10\r
+  DB   007h, 003h, 005h, 078h, 084h, 084h, 084h, 078h  ; #11\r
+  DB   07Ch, 082h, 082h, 082h, 07Ch, 010h, 038h, 010h  ; #12\r
+  DB   01Ch, 010h, 01Ch, 010h, 010h, 010h, 030h, 030h  ; #13\r
+  DB   03Eh, 022h, 03Eh, 022h, 022h, 026h, 066h, 060h  ; #14\r
+  DB   099h, 05Ah, 03Ch, 0E7h, 0E7h, 03Ch, 05Ah, 099h  ; #15\r
+  DB   000h, 010h, 030h, 070h, 0F0h, 070h, 030h, 010h  ; #16\r
+  DB   000h, 080h, 0C0h, 0E0h, 0F0h, 0E0h, 0C0h, 080h  ; #17\r
+  DB   010h, 038h, 054h, 010h, 010h, 054h, 038h, 010h  ; #18\r
+  DB   048h, 048h, 048h, 048h, 048h, 000h, 048h, 000h  ; #19\r
+  DB   07Eh, 092h, 092h, 072h, 012h, 012h, 012h, 000h  ; #20\r
+  DB   03Ch, 022h, 018h, 024h, 024h, 018h, 044h, 03Ch  ; #21\r
+  DB   000h, 000h, 000h, 000h, 000h, 03Eh, 03Eh, 000h  ; #22\r
+  DB   038h, 054h, 010h, 010h, 010h, 054h, 038h, 0FEh  ; #23\r
+  DB   000h, 010h, 038h, 054h, 010h, 010h, 010h, 000h  ; #24\r
+  DB   000h, 010h, 010h, 010h, 054h, 038h, 010h, 000h  ; #25\r
+  DB   000h, 008h, 004h, 0FEh, 004h, 008h, 000h, 000h  ; #26\r
+  DB   000h, 020h, 040h, 0FEh, 040h, 020h, 000h, 000h  ; #27\r
+  DB   000h, 000h, 080h, 080h, 080h, 0FCh, 000h, 000h  ; #28\r
+  DB   000h, 024h, 042h, 0FFh, 042h, 024h, 000h, 000h  ; #29\r
+  DB   000h, 000h, 010h, 038h, 07Ch, 0FEh, 000h, 000h  ; #30\r
+  DB   000h, 000h, 0FEh, 07Ch, 038h, 010h, 000h, 000h  ; #31\r
+  DB   000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h  ;  \r
+  DB   010h, 010h, 010h, 010h, 010h, 000h, 010h, 000h  ; !\r
+  DB   000h, 024h, 024h, 000h, 000h, 000h, 000h, 000h  ; "\r
+  DB   024h, 024h, 07Eh, 024h, 07Eh, 024h, 024h, 000h  ; #\r
+  DB   038h, 054h, 050h, 038h, 014h, 054h, 038h, 010h  ; $\r
+  DB   000h, 002h, 044h, 008h, 010h, 020h, 042h, 000h  ; %\r
+  DB   038h, 044h, 038h, 060h, 094h, 088h, 074h, 000h  ; &\r
+  DB   020h, 020h, 040h, 000h, 000h, 000h, 000h, 000h  ; '\r
+  DB   010h, 020h, 040h, 040h, 040h, 020h, 010h, 000h  ; (\r
+  DB   040h, 020h, 010h, 010h, 010h, 020h, 040h, 000h  ; )\r
+  DB   000h, 024h, 018h, 07Eh, 018h, 024h, 000h, 000h  ; *\r
+  DB   000h, 010h, 010h, 07Ch, 010h, 010h, 000h, 000h  ; +\r
+  DB   000h, 000h, 000h, 000h, 000h, 010h, 010h, 020h  ; ,\r
+  DB   000h, 000h, 000h, 0FCh, 000h, 000h, 000h, 000h  ; -\r
+  DB   000h, 000h, 000h, 000h, 000h, 000h, 010h, 000h  ; .\r
+  DB   000h, 004h, 008h, 010h, 020h, 040h, 080h, 000h  ; /\r
+  DB   07Ch, 0C6h, 08Ah, 092h, 0A2h, 0C6h, 07Ch, 000h  ; 0\r
+  DB   010h, 030h, 010h, 010h, 010h, 010h, 038h, 000h  ; 1\r
+  DB   078h, 084h, 004h, 018h, 060h, 080h, 0FCh, 000h  ; 2\r
+  DB   078h, 084h, 004h, 038h, 004h, 084h, 078h, 000h  ; 3\r
+  DB   01Ch, 024h, 044h, 084h, 0FEh, 004h, 00Eh, 000h  ; 4\r
+  DB   0FCh, 080h, 0F8h, 004h, 004h, 084h, 078h, 000h  ; 5\r
+  DB   078h, 084h, 080h, 0F8h, 084h, 084h, 078h, 000h  ; 6\r
+  DB   0FCh, 004h, 004h, 008h, 010h, 020h, 020h, 000h  ; 7\r
+  DB   078h, 084h, 084h, 078h, 084h, 084h, 078h, 000h  ; 8\r
+  DB   078h, 084h, 084h, 07Ch, 004h, 084h, 078h, 000h  ; 9\r
+  DB   000h, 000h, 010h, 000h, 000h, 000h, 010h, 000h  ; :\r
+  DB   000h, 000h, 010h, 000h, 000h, 010h, 010h, 020h  ; ;\r
+  DB   008h, 010h, 020h, 040h, 020h, 010h, 008h, 000h  ; <\r
+  DB   000h, 000h, 0FCh, 000h, 000h, 0FCh, 000h, 000h  ; =\r
+  DB   040h, 020h, 010h, 008h, 010h, 020h, 040h, 000h  ; >\r
+  DB   078h, 084h, 004h, 008h, 010h, 000h, 010h, 000h  ; ?\r
+  DB   07Ch, 082h, 0BAh, 0A6h, 0BEh, 080h, 07Ch, 000h  ; @\r
+  DB   078h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h  ; A\r
+  DB   0F8h, 084h, 084h, 0F8h, 084h, 084h, 0F8h, 000h  ; B\r
+  DB   078h, 084h, 080h, 080h, 080h, 084h, 078h, 000h  ; C\r
+  DB   0F0h, 088h, 084h, 084h, 084h, 088h, 0F0h, 000h  ; D\r
+  DB   0FCh, 080h, 080h, 0F0h, 080h, 080h, 0FCh, 000h  ; E\r
+  DB   0FCh, 080h, 080h, 0F0h, 080h, 080h, 080h, 000h  ; F\r
+  DB   078h, 084h, 080h, 09Ch, 084h, 084h, 078h, 000h  ; G\r
+  DB   084h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h  ; H\r
+  DB   038h, 010h, 010h, 010h, 010h, 010h, 038h, 000h  ; I\r
+  DB   01Ch, 008h, 008h, 008h, 088h, 088h, 070h, 000h  ; J\r
+  DB   084h, 088h, 090h, 0E0h, 090h, 088h, 084h, 000h  ; K\r
+  DB   080h, 080h, 080h, 080h, 080h, 080h, 0FCh, 000h  ; L\r
+  DB   0C6h, 0AAh, 092h, 082h, 082h, 082h, 082h, 000h  ; M\r
+  DB   082h, 0C2h, 0A2h, 092h, 08Ah, 086h, 082h, 000h  ; N\r
+  DB   078h, 084h, 084h, 084h, 084h, 084h, 078h, 000h  ; O\r
+  DB   0F8h, 084h, 084h, 0F8h, 080h, 080h, 080h, 000h  ; P\r
+  DB   078h, 084h, 084h, 084h, 094h, 088h, 076h, 000h  ; Q\r
+  DB   0F8h, 084h, 084h, 0F8h, 090h, 088h, 084h, 000h  ; R\r
+  DB   078h, 084h, 080h, 078h, 004h, 084h, 078h, 000h  ; S\r
+  DB   0FEh, 010h, 010h, 010h, 010h, 010h, 010h, 000h  ; T\r
+  DB   084h, 084h, 084h, 084h, 084h, 084h, 078h, 000h  ; U\r
+  DB   084h, 084h, 084h, 084h, 084h, 048h, 030h, 000h  ; V\r
+  DB   082h, 082h, 082h, 082h, 092h, 0AAh, 0C6h, 000h  ; W\r
+  DB   082h, 044h, 028h, 010h, 028h, 044h, 082h, 000h  ; X\r
+  DB   044h, 044h, 044h, 038h, 010h, 010h, 010h, 000h  ; Y\r
+  DB   0FEh, 004h, 008h, 010h, 020h, 040h, 0FEh, 000h  ; Z\r
+  DB   078h, 040h, 040h, 040h, 040h, 040h, 078h, 000h  ; [\r
+  DB   000h, 080h, 040h, 020h, 010h, 008h, 004h, 000h  ; \\r
+  DB   078h, 008h, 008h, 008h, 008h, 008h, 078h, 000h  ; ]\r
+  DB   010h, 028h, 044h, 082h, 000h, 000h, 000h, 000h  ; ^\r
+  DB   000h, 000h, 000h, 000h, 000h, 000h, 000h, 0FFh  ; _\r
+  DB   020h, 020h, 010h, 000h, 000h, 000h, 000h, 000h  ; `\r
+  DB   000h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; a\r
+  DB   000h, 040h, 040h, 078h, 044h, 044h, 078h, 000h  ; b\r
+  DB   000h, 000h, 03Ch, 040h, 040h, 040h, 03Ch, 000h  ; c\r
+  DB   000h, 004h, 004h, 03Ch, 044h, 044h, 03Ch, 000h  ; d\r
+  DB   000h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h  ; e\r
+  DB   000h, 00Ch, 010h, 03Ch, 010h, 010h, 010h, 000h  ; f\r
+  DB   000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 038h  ; g\r
+  DB   000h, 040h, 040h, 078h, 044h, 044h, 044h, 000h  ; h\r
+  DB   000h, 010h, 000h, 010h, 010h, 010h, 010h, 000h  ; i\r
+  DB   000h, 004h, 000h, 004h, 004h, 004h, 044h, 038h  ; j\r
+  DB   000h, 040h, 040h, 050h, 060h, 050h, 048h, 000h  ; k\r
+  DB   000h, 030h, 010h, 010h, 010h, 010h, 010h, 000h  ; l\r
+  DB   000h, 000h, 068h, 054h, 054h, 044h, 044h, 000h  ; m\r
+  DB   000h, 000h, 078h, 044h, 044h, 044h, 044h, 000h  ; n\r
+  DB   000h, 000h, 038h, 044h, 044h, 044h, 038h, 000h  ; o\r
+  DB   000h, 000h, 078h, 044h, 044h, 078h, 040h, 040h  ; p\r
+  DB   000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 004h  ; q\r
+  DB   000h, 000h, 05Ch, 060h, 040h, 040h, 040h, 000h  ; r\r
+  DB   000h, 000h, 038h, 040h, 07Ch, 004h, 07Ch, 000h  ; s\r
+  DB   000h, 010h, 038h, 010h, 010h, 010h, 018h, 000h  ; t\r
+  DB   000h, 000h, 044h, 044h, 044h, 044h, 038h, 000h  ; u\r
+  DB   000h, 000h, 044h, 044h, 044h, 028h, 010h, 000h  ; v\r
+  DB   000h, 000h, 044h, 044h, 054h, 054h, 06Ch, 000h  ; w\r
+  DB   000h, 000h, 044h, 028h, 010h, 028h, 044h, 000h  ; x\r
+  DB   000h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch  ; y\r
+  DB   000h, 000h, 07Ch, 004h, 038h, 040h, 07Ch, 000h  ; z\r
+  DB   000h, 008h, 010h, 010h, 030h, 010h, 010h, 008h  ; {\r
+  DB   000h, 010h, 010h, 010h, 000h, 010h, 010h, 010h  ; |\r
+  DB   000h, 020h, 010h, 010h, 018h, 010h, 010h, 020h  ; }\r
+  DB   064h, 098h, 000h, 000h, 000h, 000h, 000h, 000h  ; ~\r
+  DB   000h, 010h, 028h, 044h, 082h, 082h, 0FEh, 000h  ; \7f\r
+  DB   07Ch, 080h, 080h, 080h, 080h, 07Ch, 004h, 07Ch  ; #128\r
+  DB   000h, 028h, 000h, 044h, 044h, 044h, 038h, 000h  ; #129\r
+  DB   03Ch, 000h, 07Ch, 044h, 07Ch, 040h, 07Ch, 000h  ; #130\r
+  DB   07Eh, 081h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #131\r
+  DB   024h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #132\r
+  DB   078h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #133\r
+  DB   018h, 018h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #134\r
+  DB   000h, 000h, 078h, 080h, 080h, 078h, 008h, 038h  ; #135\r
+  DB   07Ch, 082h, 038h, 044h, 07Ch, 040h, 03Ch, 000h  ; #136\r
+  DB   048h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h  ; #137\r
+  DB   078h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h  ; #138\r
+  DB   000h, 028h, 000h, 010h, 010h, 010h, 010h, 000h  ; #139\r
+  DB   010h, 028h, 000h, 010h, 010h, 010h, 010h, 000h  ; #140\r
+  DB   000h, 030h, 000h, 010h, 010h, 010h, 010h, 000h  ; #141\r
+  DB   048h, 000h, 078h, 084h, 0FCh, 084h, 084h, 000h  ; #142\r
+  DB   030h, 030h, 078h, 084h, 0FCh, 084h, 084h, 000h  ; #143\r
+  DB   038h, 000h, 0FCh, 080h, 0F0h, 080h, 0FCh, 000h  ; #144\r
+  DB   000h, 000h, 07Eh, 008h, 07Eh, 048h, 07Eh, 000h  ; #145\r
+  DB   07Eh, 090h, 090h, 0FCh, 090h, 090h, 09Eh, 000h  ; #146\r
+  DB   07Ch, 082h, 038h, 044h, 044h, 044h, 038h, 000h  ; #147\r
+  DB   028h, 000h, 038h, 044h, 044h, 044h, 038h, 000h  ; #148\r
+  DB   070h, 000h, 038h, 044h, 044h, 044h, 038h, 000h  ; #149\r
+  DB   038h, 044h, 000h, 044h, 044h, 044h, 038h, 000h  ; #150\r
+  DB   070h, 000h, 044h, 044h, 044h, 044h, 038h, 000h  ; #151\r
+  DB   028h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch  ; #152\r
+  DB   048h, 000h, 078h, 084h, 084h, 084h, 078h, 000h  ; #153\r
+  DB   048h, 000h, 084h, 084h, 084h, 084h, 078h, 000h  ; #154\r
+  DB   000h, 010h, 038h, 040h, 040h, 040h, 038h, 010h  ; #155\r
+  DB   038h, 044h, 040h, 0E0h, 040h, 040h, 082h, 0FCh  ; #156\r
+  DB   044h, 07Ch, 010h, 07Ch, 010h, 07Ch, 010h, 000h  ; #157\r
+  DB   0F0h, 088h, 08Ah, 0F7h, 082h, 082h, 082h, 000h  ; #158\r
+  DB   00Ch, 012h, 010h, 018h, 030h, 010h, 090h, 060h  ; #159\r
+  DB   03Ch, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #160\r
+  DB   000h, 018h, 000h, 010h, 010h, 010h, 010h, 000h  ; #161\r
+  DB   01Ch, 000h, 038h, 044h, 044h, 044h, 038h, 000h  ; #162\r
+  DB   01Ch, 000h, 044h, 044h, 044h, 044h, 038h, 000h  ; #163\r
+  DB   07Ch, 000h, 078h, 044h, 044h, 044h, 044h, 000h  ; #164\r
+  DB   07Ch, 000h, 044h, 064h, 054h, 04Ch, 044h, 000h  ; #165\r
+  DB   018h, 024h, 024h, 01Eh, 000h, 03Eh, 000h, 000h  ; #166\r
+  DB   01Ch, 022h, 022h, 01Ch, 000h, 03Eh, 000h, 000h  ; #167\r
+  DB   010h, 000h, 010h, 020h, 040h, 042h, 03Ch, 000h  ; #168\r
+  DB   000h, 000h, 000h, 0FCh, 080h, 080h, 000h, 000h  ; #169\r
+  DB   000h, 000h, 000h, 0FCh, 004h, 004h, 000h, 000h  ; #170\r
+  DB   040h, 044h, 048h, 057h, 021h, 047h, 004h, 007h  ; #171\r
+  DB   040h, 044h, 048h, 052h, 026h, 04Ah, 01Fh, 002h  ; #172\r
+  DB   010h, 000h, 010h, 010h, 010h, 010h, 010h, 000h  ; #173\r
+  DB   000h, 024h, 048h, 090h, 048h, 024h, 000h, 000h  ; #174\r
+  DB   000h, 048h, 024h, 012h, 024h, 048h, 000h, 000h  ; #175\r
+  DB   022h, 088h, 022h, 088h, 022h, 088h, 022h, 088h  ; #176\r
+  DB   055h, 0AAh, 055h, 0AAh, 055h, 0AAh, 055h, 0AAh  ; #177\r
+  DB   0DBh, 077h, 0DBh, 0EEh, 0DBh, 077h, 0DBh, 0EEh  ; #178\r
+  DB   018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h  ; #179\r
+  DB   018h, 018h, 018h, 018h, 0F8h, 018h, 018h, 018h  ; #180\r
+  DB   018h, 018h, 0F8h, 018h, 0F8h, 018h, 018h, 018h  ; #181\r
+  DB   036h, 036h, 036h, 036h, 0F6h, 036h, 036h, 036h  ; #182\r
+  DB   000h, 000h, 000h, 000h, 0FEh, 036h, 036h, 036h  ; #183\r
+  DB   000h, 000h, 0F8h, 018h, 0F8h, 018h, 018h, 018h  ; #184\r
+  DB   036h, 036h, 0F6h, 006h, 0F6h, 036h, 036h, 036h  ; #185\r
+  DB   036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h  ; #186\r
+  DB   000h, 000h, 0FEh, 006h, 0F6h, 036h, 036h, 036h  ; #187\r
+  DB   036h, 036h, 0F6h, 006h, 0FEh, 000h, 000h, 000h  ; #188\r
+  DB   036h, 036h, 036h, 036h, 0FEh, 000h, 000h, 000h  ; #189\r
+  DB   018h, 018h, 0F8h, 018h, 0F8h, 000h, 000h, 000h  ; #190\r
+  DB   000h, 000h, 000h, 000h, 0F8h, 018h, 018h, 018h  ; #191\r
+  DB   018h, 018h, 018h, 018h, 01Fh, 000h, 000h, 000h  ; #192\r
+  DB   018h, 018h, 018h, 018h, 0FFh, 000h, 000h, 000h  ; #193\r
+  DB   000h, 000h, 000h, 000h, 0FFh, 018h, 018h, 018h  ; #194\r
+  DB   018h, 018h, 018h, 018h, 01Fh, 018h, 018h, 018h  ; #195\r
+  DB   000h, 000h, 000h, 000h, 0FFh, 000h, 000h, 000h  ; #196\r
+  DB   018h, 018h, 018h, 018h, 0FFh, 018h, 018h, 018h  ; #197\r
+  DB   018h, 018h, 01Fh, 018h, 01Fh, 018h, 018h, 018h  ; #198\r
+  DB   036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h  ; #199\r
+  DB   036h, 036h, 037h, 030h, 03Fh, 000h, 000h, 000h  ; #200\r
+  DB   000h, 000h, 03Fh, 030h, 037h, 036h, 036h, 036h  ; #201\r
+  DB   036h, 036h, 0F7h, 000h, 0FFh, 000h, 000h, 000h  ; #202\r
+  DB   000h, 000h, 0FFh, 000h, 0F7h, 036h, 036h, 036h  ; #203\r
+  DB   036h, 036h, 037h, 030h, 037h, 036h, 036h, 036h  ; #204\r
+  DB   000h, 000h, 0FFh, 000h, 0FFh, 000h, 000h, 000h  ; #205\r
+  DB   036h, 036h, 0F7h, 000h, 0F7h, 036h, 036h, 036h  ; #206\r
+  DB   018h, 018h, 0FFh, 000h, 0FFh, 000h, 000h, 000h  ; #207\r
+  DB   036h, 036h, 036h, 036h, 0FFh, 000h, 000h, 000h  ; #208\r
+  DB   000h, 000h, 0FFh, 000h, 0FFh, 018h, 018h, 018h  ; #209\r
+  DB   000h, 000h, 000h, 000h, 0FFh, 036h, 036h, 036h  ; #210\r
+  DB   036h, 036h, 036h, 036h, 03Fh, 000h, 000h, 000h  ; #211\r
+  DB   018h, 018h, 01Fh, 018h, 01Fh, 000h, 000h, 000h  ; #212\r
+  DB   000h, 000h, 01Fh, 018h, 01Fh, 018h, 018h, 018h  ; #213\r
+  DB   000h, 000h, 000h, 000h, 03Fh, 036h, 036h, 036h  ; #214\r
+  DB   036h, 036h, 036h, 036h, 0FFh, 036h, 036h, 036h  ; #215\r
+  DB   018h, 018h, 0FFh, 018h, 0FFh, 018h, 018h, 018h  ; #216\r
+  DB   018h, 018h, 018h, 018h, 0F8h, 000h, 000h, 000h  ; #217\r
+  DB   000h, 000h, 000h, 000h, 01Fh, 018h, 018h, 018h  ; #218\r
+  DB   0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh  ; #219\r
+  DB   000h, 000h, 000h, 000h, 0FFh, 0FFh, 0FFh, 0FFh  ; #220\r
+  DB   0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h  ; #221\r
+  DB   00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh  ; #222\r
+  DB   0FFh, 0FFh, 0FFh, 0FFh, 000h, 000h, 000h, 000h  ; #223\r
+  DB   000h, 000h, 062h, 094h, 088h, 094h, 062h, 000h  ; #224\r
+  DB   000h, 0F0h, 088h, 0F0h, 088h, 088h, 0F0h, 080h  ; #225\r
+  DB   000h, 0F8h, 088h, 080h, 080h, 080h, 080h, 000h  ; #226\r
+  DB   000h, 0FCh, 048h, 048h, 048h, 048h, 048h, 000h  ; #227\r
+  DB   0FCh, 084h, 040h, 020h, 040h, 084h, 0FCh, 000h  ; #228\r
+  DB   03Ch, 040h, 038h, 044h, 044h, 044h, 038h, 000h  ; #229\r
+  DB   000h, 000h, 044h, 044h, 044h, 078h, 040h, 040h  ; #230\r
+  DB   000h, 036h, 048h, 008h, 008h, 008h, 008h, 000h  ; #231\r
+  DB   038h, 010h, 038h, 044h, 044h, 038h, 010h, 038h  ; #232\r
+  DB   078h, 084h, 084h, 0FCh, 084h, 084h, 078h, 000h  ; #233\r
+  DB   078h, 084h, 084h, 084h, 048h, 048h, 0CCh, 000h  ; #234\r
+  DB   078h, 004h, 038h, 044h, 044h, 044h, 038h, 000h  ; #235\r
+  DB   000h, 000h, 06Ch, 092h, 092h, 06Ch, 000h, 000h  ; #236\r
+  DB   000h, 000h, 03Ah, 044h, 05Ah, 022h, 05Ch, 000h  ; #237\r
+  DB   018h, 020h, 040h, 078h, 040h, 020h, 018h, 000h  ; #238\r
+  DB   078h, 084h, 084h, 084h, 084h, 084h, 084h, 000h  ; #239\r
+  DB   000h, 0FCh, 000h, 0FCh, 000h, 0FCh, 000h, 000h  ; #240\r
+  DB   020h, 020h, 0F8h, 020h, 020h, 000h, 0F8h, 000h  ; #241\r
+  DB   020h, 010h, 008h, 010h, 020h, 000h, 07Ch, 000h  ; #242\r
+  DB   008h, 010h, 020h, 010h, 008h, 000h, 07Ch, 000h  ; #243\r
+  DB   00Ch, 012h, 010h, 010h, 010h, 010h, 010h, 010h  ; #244\r
+  DB   010h, 010h, 010h, 010h, 010h, 010h, 090h, 060h  ; #245\r
+  DB   000h, 010h, 000h, 07Ch, 000h, 010h, 000h, 000h  ; #246\r
+  DB   000h, 032h, 04Ch, 000h, 032h, 04Ch, 000h, 000h  ; #247\r
+  DB   038h, 044h, 044h, 038h, 000h, 000h, 000h, 000h  ; #248\r
+  DB   000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h  ; #249\r
+  DB   000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h  ; #250\r
+  DB   00Eh, 008h, 008h, 008h, 048h, 028h, 018h, 008h  ; #251\r
+  DB   038h, 024h, 024h, 024h, 024h, 000h, 000h, 000h  ; #252\r
+  DB   03Ch, 004h, 03Ch, 020h, 03Ch, 000h, 000h, 000h  ; #253\r
+  DB   000h, 000h, 03Ch, 03Ch, 03Ch, 03Ch, 000h, 000h  ; #254\r
+  DB   000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h  ; #255\r
diff --git a/16/x_/makefile b/16/x_/makefile
new file mode 100755 (executable)
index 0000000..eb7bf62
--- /dev/null
@@ -0,0 +1,82 @@
+#\r
+# MODEX library makefile (for Borland MAKE)\r
+# Copyright (c) 1993,1994 by Alessandro Scotti\r
+#\r
+LIBINCS = MODEX.DEF\r
+\r
+LIBOBJS = MXBB.OBJ \\r
+          MXCC.OBJ \\r
+          MXCG.OBJ \\r
+          MXCL.OBJ \\r
+          MXCR.OBJ \\r
+          MXFB.OBJ \\r
+          MXFP.OBJ \\r
+          MXGC.OBJ \\r
+          MXGI.OBJ \\r
+          MXGM.OBJ \\r
+          MXGP.OBJ \\r
+          MXGV.OBJ \\r
+          MXHL.OBJ \\r
+          MXIT.OBJ \\r
+          MXLL.OBJ \\r
+          MXLN.OBJ \\r
+          MXOT.OBJ \\r
+          MXPB.OBJ \\r
+          MXPF.OBJ \\r
+          MXPG.OBJ \\r
+          MXPI.OBJ \\r
+          MXPN.OBJ \\r
+          MXPP.OBJ \\r
+          MXRA.OBJ \\r
+          MXRP.OBJ \\r
+          MXSA.OBJ \\r
+          MXSC.OBJ \\r
+          MXSI.OBJ \\r
+          MXSL.OBJ \\r
+          MXSM.OBJ \\r
+          MXSP.OBJ \\r
+          MXSS.OBJ \\r
+          MXTL.OBJ \\r
+          MXVS.OBJ \\r
+          MXWD.OBJ \\r
+          MXWM.OBJ \\r
+          MXWP.OBJ \\r
+          MXWR.OBJ\r
+\r
+#\r
+# ASM compiler\r
+#\r
+ASMC = tasm\r
+ASMO = /m5 /zi\r
+#/p\r
+\r
+#\r
+# PAS compiler\r
+#\r
+PASC = tpc\r
+PASO = /m -$D- -$L- -$S-\r
+\r
+#\r
+# LIB maker, uses response file\r
+#\r
+LIBC = tlib\r
+\r
+.asm.obj:\r
+        $(ASMC) $(ASMO) $<\r
+\r
+target: modex.lib\r
+# modex.tpu modex.tpp\r
+\r
+#modex.tpu: $(LIBOBJS) modex.pas\r
+#        $(PASC) $(PASO) modex\r
+#        copy modex.tpu ..\r
+#        copy modex.pas ..\r
+\r
+#modex.tpp: $(LIBOBJS) modex.pas\r
+#        $(PASC) /cp $(PASO) modex\r
+#        copy modex.tpp ..\r
+\r
+modex.lib: modex.lbr $(LIBOBJS)\r
+        $(LIBC) modex.lib @modex.lbr\r
+\r
+$(LIBOBJS):   modex.def\r
diff --git a/16/x_/modex.def b/16/x_/modex.def
new file mode 100755 (executable)
index 0000000..9c6b75b
--- /dev/null
@@ -0,0 +1,154 @@
+;------------------------------------------------------------\r
+;\r
+; MODEX.DEF - Include file\r
+; Copyright (c) 1993-1994 by Alessandro Scotti\r
+;\r
+JUMPS\r
+LOCALS\r
+\r
+TRUE            EQU     1       ; Boolean constants\r
+FALSE           EQU     0\r
+\r
+USE286  = FALSE                  ; TRUE enables 80286 instructions\r
+USE386  = FALSE                  ; TRUE enables 80386 (and 80286) instructions\r
+\r
+IF USE286 EQ TRUE\r
+        P286\r
+ENDIF\r
+\r
+IF USE386 EQ TRUE\r
+        P386\r
+        USE286  = TRUE\r
+ENDIF\r
+\r
+MXVERSION       EQU     0128h   ; Library version (1.40)\r
+\r
+;------------------------------------------------------------\r
+;\r
+; VGA definitions\r
+;\r
+MISC    EQU     3C2h            ; Miscellaneous output\r
+TS      EQU     3C4h            ; Timing Sequencer index register\r
+GDC     EQU     3CEh            ; Graphics Data Controller index register\r
+CRTC    EQU     3D4h            ; CRTC index register\r
+STATUS  EQU     3DAh            ; Input Status register one\r
+\r
+;------------------------------------------------------------\r
+;\r
+; Raster operators\r
+;\r
+OP_SET          EQU     0\r
+OP_MOVE         EQU     0       ; Same as OP_SET\r
+OP_AND          EQU     1\r
+OP_OR           EQU     2\r
+OP_XOR          EQU     3\r
+OP_TRANS        EQU     4\r
+OP_ADD          EQU     5       ; Must be last op\r
+\r
+;------------------------------------------------------------\r
+;\r
+; Polygon fill functions\r
+;\r
+POLYSCANBUFSIZE EQU     4*1024\r
+\r
+;------------------------------------------------------------\r
+; Macro to push registers, variables or flags onto the stack\r
+; Usage: .push "loc16"[,"loc16"...]\r
+; where "loc16" is a 16-bit register, a word-sized variable or the\r
+; keyword "FLAGS".\r
+; Exmpl: .push ax, flags, var1\r
+;        .pop  ax, flags, var1\r
+;\r
+.push   MACRO   r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10\r
+    IFNB <r10>\r
+        .ERROR <.PUSH has more than 10 arguments>\r
+    ENDIF\r
+    IRP $reg, <r0, r1, r2, r3, r4, r5, r6, r7, r8, r9>\r
+        IFB <$reg>                      ;; Is argument blank?\r
+            EXITM                       ;; Yes, exit\r
+        ELSEIFIDNI <$reg>, <FLAGS>      ;; Is argument the keyword "FLAGS"?\r
+            pushf                       ;; Yes, push flags\r
+        ELSE\r
+            push    $reg                ;; Push argument\r
+        ENDIF\r
+    ENDM\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+; Macro to pop registers, variables or flags from the stack\r
+; Usage: .pop "loc16"[,"loc16"...]\r
+; where "loc16" is a 16-bit register, a word-sized variable or the\r
+; keyword "FLAGS".\r
+; Exmpl: .push ax, flags, var1\r
+;        .pop  ax, flags, var1\r
+;\r
+.pop    MACRO   r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10\r
+    IFNB <r10>\r
+        .ERROR <.POP has more than 10 arguments>\r
+    ENDIF\r
+    IRP $reg, <r9, r8, r7, r6, r5, r4, r3, r2, r1, r0>\r
+        IFNB <$reg>                     ;; Is argument non-blank?\r
+            IFIDNI <$reg>, <FLAGS>      ;; Yes, is it the keyword "FLAGS"?\r
+                popf                    ;; Yes, pop flags\r
+            ELSE\r
+                pop     $reg            ;; Pop argument\r
+            ENDIF\r
+        ENDIF\r
+    ENDM\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.enter  MACRO   localsize\r
+    IF USE286 EQ TRUE\r
+        enter   localsize, 0\r
+    ELSE\r
+        push    bp\r
+        mov     bp, sp\r
+        sub     sp, localsize\r
+    ENDIF\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.leave  MACRO   argsize\r
+    IF USE286 EQ TRUE\r
+        leave\r
+    ELSE\r
+        mov     sp, bp\r
+        pop     bp\r
+    ENDIF\r
+    IFNB <argspace>\r
+        ret     argsize\r
+    ELSE\r
+        ret\r
+    ENDIF\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.shr    MACRO   arg, count\r
+    IF USE286 EQ TRUE\r
+        shr     arg, count\r
+    ELSE\r
+        $temp = count\r
+        WHILE $temp GT 0\r
+            shr arg, 1\r
+            $temp = $temp-1\r
+        ENDM\r
+    ENDIF\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.shl    MACRO   arg, count\r
+    IF USE286 EQ TRUE\r
+        shl     arg, count\r
+    ELSE\r
+        $temp = count\r
+        WHILE $temp GT 0\r
+            shl arg, 1\r
+            $temp = $temp-1\r
+        ENDM\r
+    ENDIF\r
+ENDM\r
diff --git a/16/x_/modex.h b/16/x_/modex.h
new file mode 100755 (executable)
index 0000000..2c1f1eb
--- /dev/null
@@ -0,0 +1,153 @@
+/*\r
+    MODEX.H - C/C++ include file for the MODEX library\r
+    Copyright (c) 1994 Alessandro Scotti\r
+*/\r
+\r
+#ifndef _MODEX_H_               // Avoid nested inclusions\r
+#define _MODEX_H_\r
+\r
+//\r
+// Video modes\r
+//\r
+#define MX_TEXT     0           // 80x25 text\r
+#define MX_320x175  1           // 320x175x256\r
+#define MX_320x200  2           // 320x200x256, 4 pages, aspect 6:5\r
+#define MX_320x240  3           // 320x240x256, 3 pages, aspect 1:1\r
+#define MX_320x350  4           // 320x350x256\r
+#define MX_320x400  5           // 320x400x256, 2 pages\r
+#define MX_320x480  6           // 320x480x256, 1 page\r
+#define MX_360x175  7           // 360x175x256\r
+#define MX_360x200  8           // 360x200x256, 3 pages\r
+#define MX_360x240  9           // 360x240x256, 2 pages\r
+#define MX_360x350  10          // 360x350x256\r
+#define MX_360x400  11          // 360x400x256, 1 page\r
+#define MX_360x480  12          // 360x480x256, 1 page\r
+#define MX_400x600  13          // 400x600x256, 1 page\r
+\r
+//\r
+// Fade effects\r
+//\r
+#define MX_FADEIN   0\r
+#define MX_FADEOUT  1\r
+\r
+//\r
+// Raster ops\r
+//\r
+#define OP_SET      0           // No operator\r
+#define OP_AND      1           // And\r
+#define OP_OR       2           // Or\r
+#define OP_XOR      3           // Xor\r
+#define OP_TRANS    4           // Transparent\r
+#define OP_ADD      5           // Additive\r
+#define OP_MOVE     0           // Alias for OP_SET\r
+\r
+//\r
+// Temporary definitions\r
+//\r
+#define MXBYTE      unsigned char\r
+#define MXBOOL      short int\r
+#define MXSINT      short int\r
+#define MXUINT      unsigned short int\r
+#define MXAPI       far pascal\r
+#define MXPTR       void far *\r
+\r
+// Functions\r
+\r
+#ifdef __cplusplus                      // Avoid C++ name mangling\r
+extern "C" {\r
+#endif\r
+\r
+//\r
+// Initialization\r
+//\r
+MXSINT  MXAPI mxInit( void );             // Returns 0 if successful\r
+void    MXAPI mxTerm( void );\r
+MXUINT  MXAPI mxGetVersion( void );\r
+//\r
+// Mode setting\r
+//\r
+void    MXAPI mxChangeMode( MXUINT mode );\r
+void    MXAPI mxSetMode( MXUINT mode );\r
+void    MXAPI mxGetAspect( MXUINT far *aspectx, MXUINT far *aspecty );\r
+void    MXAPI mxGetScreenSize( MXUINT far *width, MXUINT far *height );\r
+//\r
+// Hardware support\r
+//\r
+void    MXAPI mxWriteMode( MXBYTE wm );\r
+void    MXAPI mxSplitScreen( MXUINT line );\r
+void    MXAPI mxStartAddress( MXUINT sa );\r
+void    MXAPI mxStartLine( MXUINT sl );\r
+void    MXAPI mxWaitDisplay( void );\r
+void    MXAPI mxWaitRetrace( void );\r
+void    MXAPI mxWritePlane( MXBYTE wp );\r
+void    MXAPI mxReadPlane( MXBYTE rp );\r
+void    MXAPI mxRowAddress( MXBYTE ra );\r
+//\r
+// Virtual screen\r
+//\r
+void    MXAPI mxGetVirtualScreen( MXUINT far *width, MXUINT far *height );\r
+void    MXAPI mxSetVirtualScreen( MXUINT width, MXUINT height );\r
+void    MXAPI mxPan( MXUINT x, MXUINT y );\r
+//\r
+// Clipping\r
+//\r
+MXBOOL  MXAPI mxGetClip( void );\r
+MXBOOL  MXAPI mxGetClipRegion( MXSINT far *x, MXSINT far *y, MXSINT far *w, MXSINT far *h );\r
+MXBOOL  MXAPI mxSetClip( MXBOOL );\r
+void    MXAPI mxSetClipRegion( MXUINT x, MXUINT y, MXUINT width, MXUINT height );\r
+//\r
+// Graphics\r
+//\r
+void    MXAPI mxBitBlt( MXSINT sx, MXSINT sy, MXUINT width, MXUINT height, MXSINT dx, MXSINT dy );\r
+void    MXAPI mxFillBox( MXSINT x, MXSINT y, MXUINT width, MXUINT height, MXUINT color, MXUINT op );\r
+MXBYTE  MXAPI mxGetPixel( MXSINT x, MXSINT y );\r
+void    MXAPI mxPutPixel( MXSINT x, MXSINT y, MXBYTE color );\r
+void    MXAPI mxLine( MXSINT x1, MXSINT y1, MXSINT x2, MXSINT y2, MXUINT color, MXUINT op );\r
+void    MXAPI mxGetImage( MXPTR img, MXSINT x, MXSINT y, MXUINT width, MXUINT height );\r
+void    MXAPI mxPutImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT op );\r
+void    MXAPI mxPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT width, MXUINT height );\r
+void    MXAPI mxTransPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT w, MXUINT h );\r
+void    MXAPI mxCircle( MXSINT x, MXSINT y, MXUINT radius, MXBYTE color );\r
+void    MXAPI mxStretchImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT neww, MXUINT newh, MXUINT op );\r
+//\r
+// Palette\r
+//\r
+void    MXAPI mxColorToGray( MXPTR source, MXPTR dest, MXUINT count );\r
+void    MXAPI mxGammaCorrect( MXPTR source, MXPTR dest, MXUINT count );\r
+void    MXAPI mxGetColor( MXUINT index, MXSINT far *r, MXSINT far *g, MXSINT far *b );\r
+void    MXAPI mxSetColor( MXUINT index, MXSINT red, MXSINT green, MXSINT blue );\r
+void    MXAPI mxGetPalette( MXPTR palette, MXUINT index, MXUINT count );\r
+void    MXAPI mxSetPalette( MXPTR palette, MXUINT index, MXUINT count );\r
+void    MXAPI mxFadePalette( MXPTR, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT );\r
+void    MXAPI mxRotatePalette( MXPTR palette, MXUINT count, MXSINT step );\r
+//\r
+// Text\r
+//\r
+MXSINT  MXAPI mxSetFont( MXPTR font, MXUINT charwidth, MXUINT charheight );\r
+void    MXAPI mxSetTextColor( MXUINT color, MXUINT op );\r
+void    MXAPI mxGetTextStep( MXSINT far *deltax, MXSINT far *deltay );\r
+void    MXAPI mxSetTextStep( MXSINT deltax, MXSINT deltay );\r
+void    MXAPI mxOutChar( MXSINT x, MXSINT y, char c );\r
+void    MXAPI mxOutText( MXSINT x, MXSINT y, char far *sz );\r
+//\r
+// Convex polygons\r
+//\r
+void    MXAPI mxFillPoly( MXUINT, MXPTR, MXPTR, MXUINT, MXUINT );\r
+void    MXAPI mxGouraudPoly( MXUINT, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT );\r
+void    MXAPI mxTexturePoly( MXUINT, MXPTR, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+//\r
+// Remove temporary defines\r
+//\r
+#undef  MXBYTE\r
+#undef  MXBOOL\r
+#undef  MXSINT\r
+#undef  MXUINT\r
+#undef  MXPTR\r
+#undef  MXAPI\r
+\r
+#endif  // _MODEX_H_\r
diff --git a/16/x_/modex.lbr b/16/x_/modex.lbr
new file mode 100755 (executable)
index 0000000..b1ec26b
--- /dev/null
@@ -0,0 +1,38 @@
++-MXBB.OBJ &\r
++-MXCC.OBJ &\r
++-MXCG.OBJ &\r
++-MXCL.OBJ &\r
++-MXCR.OBJ &\r
++-MXFB.OBJ &\r
++-MXFP.OBJ &\r
++-MXGC.OBJ &\r
++-MXGI.OBJ &\r
++-MXGM.OBJ &\r
++-MXGP.OBJ &\r
++-MXGV.OBJ &\r
++-MXHL.OBJ &\r
++-MXIT.OBJ &\r
++-MXLL.OBJ &\r
++-MXLN.OBJ &\r
++-MXOT.OBJ &\r
++-MXPB.OBJ &\r
++-MXPF.OBJ &\r
++-MXPG.OBJ &\r
++-MXPI.OBJ &\r
++-MXPN.OBJ &\r
++-MXPP.OBJ &\r
++-MXRA.OBJ &\r
++-MXRP.OBJ &\r
++-MXSA.OBJ &\r
++-MXSC.OBJ &\r
++-MXSI.OBJ &\r
++-MXSL.OBJ &\r
++-MXSM.OBJ &\r
++-MXSP.OBJ &\r
++-MXSS.OBJ &\r
++-MXTL.OBJ &\r
++-MXVS.OBJ &\r
++-MXWD.OBJ &\r
++-MXWM.OBJ &\r
++-MXWP.OBJ &\r
++-MXWR.OBJ\r
diff --git a/16/x_/modex.pas b/16/x_/modex.pas
new file mode 100755 (executable)
index 0000000..7d9d26e
--- /dev/null
@@ -0,0 +1,194 @@
+(*\r
+   Turbo Pascal interface to the MODEX library\r
+   Copyright (c) 1993,1994 by Alessandro Scotti\r
+*)\r
+unit ModeX;\r
+interface\r
+\r
+const\r
+  (* Video modes *)\r
+  MX_TEXT       = 0;\r
+  MX_320x175    = 1;\r
+  MX_320x200    = 2;\r
+  MX_320x240    = 3;\r
+  MX_320x350    = 4;\r
+  MX_320x400    = 5;\r
+  MX_320x480    = 6;\r
+  MX_360x175    = 7;\r
+  MX_360x200    = 8;\r
+  MX_360x240    = 9;\r
+  MX_360x350    = 10;\r
+  MX_360x400    = 11;\r
+  MX_360x480    = 12;\r
+  MX_400x600    = 13;\r
+\r
+  (* Fade effects *)\r
+  MX_FADEIN     = 0;\r
+  MX_FADEOUT    = 1;\r
+\r
+  (* Raster ops *)\r
+  OP_SET        = 0;\r
+  OP_AND        = 1;\r
+  OP_OR         = 2;\r
+  OP_XOR        = 3;\r
+  OP_TRANS      = 4;\r
+  OP_ADD        = 5;\r
+  OP_MOVE       = 0;                    (* Alias for OP_SET *)\r
+\r
+procedure mxBitBlt( SX, SY: integer; Width, Height: word; DX, DY: integer );\r
+procedure mxCircle( CX, CY: integer; Radius: word; Color: byte );\r
+procedure mxChangeMode( Mode: word );\r
+procedure mxColorToGray( ColorPalette, GrayPalette: pointer; Count: word );\r
+procedure mxFadePalette( Palette: pointer; Cmd, Start, Count, R, G, B: word );\r
+procedure mxFillBox( X, Y: integer; Width, Height: word; Color: byte; Op: word );\r
+procedure mxGammaCorrect( ColorPalette, GammaPalette: pointer; Count: word );\r
+procedure mxGetAspect( var AspectX, AspectY: word );\r
+function  mxGetClipRegion( var X1, Y1, Width, Height: word ): boolean;\r
+function  mxGetClip: boolean;\r
+procedure mxGetImage( Image: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxGetPalette( Palette: pointer; Start, Count: word );\r
+function  mxGetPixel( X, Y: word ): byte;\r
+procedure mxGetScreenSize( var Width, Height: word );\r
+procedure mxGetTextStep( var DeltaX, DeltaY: integer );\r
+function  mxGetVersion: word;\r
+procedure mxGetVirtualScreen( var Width, Height: word );\r
+procedure mxInit;\r
+procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word );\r
+procedure mxOutChar( X, Y: integer; C: char );\r
+procedure mxOutText( X, Y: integer; S: pointer );\r
+procedure mxPan( X, Y: word );\r
+procedure mxPutImage( Image: pointer; X, Y: integer; Width, Height, Op: word );\r
+procedure mxPutPixel( X, Y: word; C: byte );\r
+procedure mxPutTile( Tile: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxReadPlane( Plane: byte );\r
+procedure mxRotatePalette( Palette: pointer; Count: word; Step: integer );\r
+procedure mxRowAddress( RowAddress: byte );\r
+function  mxSetClip( Clip: boolean ): boolean;\r
+procedure mxSetClipRegion( X1, Y1, Width, Height: word );\r
+procedure mxSetColor( Index, R, G, B: word );\r
+procedure mxSetFont( Font: pointer; Width, Height: word );\r
+procedure mxSetMode( Mode: word );\r
+procedure mxSetPalette( Palette: pointer; Start, Count: word );\r
+procedure mxSetTextColor( Color, Op: word );\r
+procedure mxSetTextStep( DeltaX, DeltaY: integer );\r
+procedure mxSetVirtualScreen( Width, Height: word );\r
+procedure mxStretchImage( Image: pointer; X, Y: integer; Width, Height, NewWidth, NewHeight, Op: word );\r
+procedure mxSplitScreen( Line: word );\r
+procedure mxStartAddress( StartAddress: word );\r
+procedure mxStartLine( Line: word );\r
+procedure mxTerm;\r
+procedure mxTransPutTile( Tile: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxWaitDisplay;\r
+procedure mxWaitRetrace;\r
+procedure mxWriteMode( Mode: byte );\r
+procedure mxWritePlane( Plane: byte );\r
+\r
+procedure mxFillPoly( Count: word; var Map, Points; Color: word );\r
+procedure mxGouraudPoly( Count: word; var Map, Points, Colors; BaseColor: word );\r
+procedure mxTexturePoly( Count: word; var Map, Points, ImgPoints, Texture; Width: word );\r
+\r
+procedure mxOutStr( X, Y: integer; S: string );\r
+\r
+implementation\r
+\r
+procedure mxBitBlt;                                             external;\r
+procedure mxChangeMode( Mode: word );                           external;\r
+procedure mxCircle;                                             external;\r
+procedure mxColorToGray;                                        external;\r
+procedure mxFadePalette;                                        external;\r
+procedure mxFillBox;                                            external;\r
+procedure mxGammaCorrect;                                       external;\r
+procedure mxGetAspect( var AspectX, AspectY: word );            external;\r
+function  mxGetClipRegion;                                      external;\r
+function  mxGetClip: boolean;                                   external;\r
+procedure mxGetImage;                                           external;\r
+procedure mxGetPalette( Palette: pointer; Start, Count: word ); external;\r
+function  mxGetPixel( X, Y: word ): byte;                       external;\r
+procedure mxGetScreenSize( var Width, Height: word );           external;\r
+procedure mxGetTextStep( var DeltaX, DeltaY: integer );         external;\r
+function  mxGetVersion: word;                                   external;\r
+procedure mxGetVirtualScreen( var Width, Height: word );        external;\r
+procedure mxInit;                                               external;\r
+procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word );   external;\r
+procedure mxOutChar( X, Y: integer; C: char );                  external;\r
+procedure mxOutText( X, Y: integer; S: pointer );               external;\r
+procedure mxPan( X, Y: word );                                  external;\r
+procedure mxPutImage;                                           external;\r
+procedure mxPutPixel( X, Y: word; C: byte );                    external;\r
+procedure mxPutTile;                                            external;\r
+procedure mxReadPlane( Plane: byte );                           external;\r
+procedure mxRotatePalette;                                      external;\r
+procedure mxRowAddress( RowAddress: byte );                     external;\r
+function  mxSetClip( Clip: boolean ): boolean;                  external;\r
+procedure mxSetClipRegion( X1, Y1, Width, Height: word );       external;\r
+procedure mxSetColor( Index, R, G, B: word );                   external;\r
+procedure mxSetFont( Font: pointer; Width, Height: word );      external;\r
+procedure mxSetMode( Mode: word );                              external;\r
+procedure mxSetPalette( Palette: pointer; Start, Count: word ); external;\r
+procedure mxSetTextColor( Color, Op: word );                    external;\r
+procedure mxSetTextStep( DeltaX, DeltaY: integer );             external;\r
+procedure mxSetVirtualScreen( Width, Height: word );            external;\r
+procedure mxSplitScreen( Line: word );                          external;\r
+procedure mxStartAddress( StartAddress: word );                 external;\r
+procedure mxStartLine;                                          external;\r
+procedure mxStretchImage;                                       external;\r
+procedure mxTerm;                                               external;\r
+procedure mxTransPutTile;                                       external;\r
+procedure mxWaitDisplay;                                        external;\r
+procedure mxWaitRetrace;                                        external;\r
+procedure mxWriteMode( Mode: byte );                            external;\r
+procedure mxWritePlane( Plane: byte );                          external;\r
+\r
+procedure mxFillPoly;                                           external;\r
+procedure mxGouraudPoly;                                        external;\r
+procedure mxTexturePoly;                                        external;\r
+{$L MXPB}\r
+{$L MXPF}\r
+{$L MXPG}\r
+{$L MXPT}\r
+\r
+{$L MXBB}\r
+{$L MXCC}\r
+{$L MXCG}\r
+{$L MXCL}\r
+{$L MXCR}\r
+{$L MXFB}\r
+{$L MXFP}\r
+{$L MXGI}\r
+{$L MXGM}\r
+{$L MXGP}\r
+{$L MXGV}\r
+{$L MXHL}\r
+{$L MXIT}\r
+{$L MXLN}\r
+{$L MXOT}\r
+{$L MXPI}\r
+{$L MXPN}\r
+{$L MXPP}\r
+{$L MXRA}\r
+{$L MXRP}\r
+{$L MXSA}\r
+{$L MXSC}\r
+{$L MXSI}\r
+{$L MXSL}\r
+{$L MXSM}\r
+{$L MXSP}\r
+{$L MXSS}\r
+{$L MXTL}\r
+{$L MXVS}\r
+{$L MXWD}\r
+{$L MXWM}\r
+{$L MXWP}\r
+{$L MXWR}\r
+\r
+(*\r
+   Prints a Turbo Pascal string.\r
+   Note: BP 7.0 supports ASCIIZ strings (PChar type).\r
+*)\r
+procedure mxOutStr;\r
+begin\r
+  S := S + #0;\r
+  mxOutText( X, Y, @S[1] );\r
+end;\r
+\r
+end.\r
diff --git a/16/x_/modex/DEMO01.EXE b/16/x_/modex/DEMO01.EXE
new file mode 100755 (executable)
index 0000000..28caff8
Binary files /dev/null and b/16/x_/modex/DEMO01.EXE differ
diff --git a/16/x_/modex/DEMO01.PAS b/16/x_/modex/DEMO01.PAS
new file mode 100755 (executable)
index 0000000..c684acd
--- /dev/null
@@ -0,0 +1,126 @@
+(*\r
+    DEMO01 - Sprites, page flipping and palette rotation\r
+    Copyright (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+  MAX_SPRITE = 100;\r
+type\r
+  (* Sprite structure *)\r
+  TSprite = record\r
+    X, Y : integer;                        (* Sprite coordinates *)\r
+    DX,DY: integer;                        (* Deltas for sprite movement *)\r
+    W, H : integer;                        (* Sprite width and height *)\r
+    Image: array[ 1..16, 1..16 ] of byte;  (* Sprite image data *)\r
+  end;\r
+  (* RGB color structure *)\r
+  TRgb    = record\r
+    R, G, B: byte;\r
+  end;\r
+var\r
+  S      : array[ 1..MAX_SPRITE ] of TSprite;   (* An array of sprites *)\r
+  Palette: array[ byte ] of TRgb;               (* Palette *)\r
+  Page   : word;                                (* Page offset *)\r
+  I      : word;\r
+\r
+(* Initializes a sprite structure *)\r
+procedure sxInit( var S: TSprite );\r
+var\r
+  I: word;\r
+begin\r
+  S.X := Random( 320 );  (* Initialize position with random values *)\r
+  S.Y := Random( 240 );\r
+  S.DX := Random( 7 )-3; (* Initialize speed with random values *)\r
+  S.DY := Random( 7 )-3;\r
+  S.W := 16;             (* Size is fixed in this program *)\r
+  S.H := 16;\r
+  (* The image is a square with a hole inside *)\r
+  FillChar( S.Image, SizeOf(S.Image), Random(15)+1 );\r
+  for I:=5 to 12 do FillChar( S.Image[ I, 5 ], 8, 0 );\r
+end;\r
+\r
+(* Moves a sprite *)\r
+procedure sxMove( var S: TSprite );\r
+begin\r
+  Inc( S.X, S.DX );     (* Get new position *)\r
+  Inc( S.Y, S.DY );\r
+  (* Check sprite position, change delta if needed *)\r
+  if( S.X > 320 ) then begin\r
+    S.X := 320;\r
+    S.DX := -S.DX;\r
+  end;\r
+  if( S.X < -16 ) then begin\r
+    S.X := -16;\r
+    S.DX := -S.DX;\r
+  end;\r
+  if( S.Y > 240 ) then begin\r
+    S.Y := 240;\r
+    S.DY := -S.DY;\r
+  end;\r
+  if( S.Y < -16 ) then begin\r
+    S.Y := -16;\r
+    S.DY := -S.DY;\r
+  end;\r
+  (* Draw the sprite, note the Page offset added to the *)\r
+  (* Y coordinate of the image *)\r
+  mxPutImage( @S.Image, S.X, Page+S.Y, S.W, S.H, OP_TRANS );\r
+end;\r
+\r
+begin\r
+  (* Initialize library *)\r
+  mxInit;\r
+\r
+  (* Enter graphics mode *)\r
+  mxSetMode( MX_320x240 );\r
+\r
+  (* Print initialization message *)\r
+  mxSetTextColor( 15, OP_TRANS );\r
+  mxOutStr( 4, 4, 'Initializing...' );\r
+\r
+  (* Initialize sprites *)\r
+  for I:=1 to MAX_SPRITE do sxInit( S[I] );\r
+\r
+  (* Draw background *)\r
+  for I:=1 to 192 do begin\r
+    mxCircle( 160, 480+120, I, I+63 );\r
+    mxCircle( 161, 480+120, I, I+63 );\r
+  end;\r
+\r
+  (* Compute and set palette *)\r
+  for I:=1 to 192 do with Palette[I+63] do begin\r
+    R := 0;\r
+    G := 0;\r
+    B := 0;\r
+    if( I < 64 ) then\r
+      R := I shr 1+31\r
+    else if( I < 128 ) then\r
+      G := (I-64) shr 1+31\r
+    else\r
+      B := (I-128) shr 1+31;\r
+  end;\r
+  mxSetPalette( @Palette[64], 64, 192 );\r
+\r
+  (* Main loop *)\r
+  Page := 240;\r
+  while( not KeyPressed ) do begin\r
+    (* Set clip region to current page *)\r
+    mxSetClipRegion( 0, Page, 320, 240 );\r
+    mxSetClip( TRUE );\r
+    (* Restore background *)\r
+    mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+    (* Draw sprites *)\r
+    for I:=1 to MAX_SPRITE do sxMove( S[I] );\r
+    (* Print message *)\r
+    mxOutStr( 4, Page+4, 'Some sprites moving...' );\r
+    (* Flip page *)\r
+    mxStartLine( Page );\r
+    Page := 240-Page;\r
+    (* Animate palette *)\r
+    mxSetPalette( @Palette[64], 64, 192 );\r
+    mxRotatePalette( @Palette[64], 192, 3 );\r
+  end;\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/x_/modex/DEMO02.EXE b/16/x_/modex/DEMO02.EXE
new file mode 100755 (executable)
index 0000000..14e7dc7
Binary files /dev/null and b/16/x_/modex/DEMO02.EXE differ
diff --git a/16/x_/modex/DEMO02.PAS b/16/x_/modex/DEMO02.PAS
new file mode 100755 (executable)
index 0000000..6b4fb6f
--- /dev/null
@@ -0,0 +1,125 @@
+(*\r
+    DEMO02 - Texture mapping and palette rotation\r
+    (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Plasma, Threed;\r
+\r
+const\r
+  LSIZE = 85;\r
+  Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+type\r
+  T2DPoint = record\r
+    X, Y: integer;\r
+  end;\r
+  TTexture = record\r
+    Desc   : array[ 0..3 ] of T2DPoint;\r
+    Width  : word;\r
+    Data   : array[ 1..64*64 ] of byte;\r
+  end;\r
+  TQuad = record\r
+    VtxCnt : word;\r
+    Vtx    : array[ 0..3 ] of word;\r
+    Texture: word;\r
+  end;\r
+var\r
+  Vtx   : array[ 0..7 ] of TPoint;\r
+  XVtx  : array[ 0..7 ] of TPoint;\r
+  VVtx  : array[ 0..7 ] of T2DPoint;\r
+  Face  : array[ 0..5 ] of TQuad;\r
+  Txts  : array[ 0..5 ] of TTexture;\r
+  Nrm   : array[ 0..5 ] of TPoint;\r
+  XNrm  : array[ 0..5 ] of TPoint;\r
+  Page  : word;\r
+  Palette: array[ byte ] of record R, G, B: byte; end;\r
+\r
+(* Make a 64x64 plasma to be used as texture *)\r
+procedure MakeTexture( Idx: word );\r
+var\r
+  I: word;\r
+begin\r
+  mxFillBox( 0, 0, 64, 64, 0, OP_SET );\r
+  MakePlasma( 0, 0, 64, 64, 96, Random(192)+1, Random(192)+1, Random(192)+1 );\r
+  mxGetImage( @Txts[Idx].Data, 0, 0, 64, 64 );\r
+  (* Texture vertexes are 8:8 fixed, add $80 (0.5) for best results *)\r
+  with Txts[Idx] do begin\r
+    Desc[0].X := $80; Desc[0].Y := $80;\r
+    Desc[1].X := $80; Desc[1].Y := $3F80;\r
+    Desc[2].X := $3F80; Desc[2].Y := $3F80;\r
+    Desc[3].X := $3F80; Desc[3].Y := $80;\r
+    Width := 64;\r
+  end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+  I: integer;\r
+begin\r
+  (* Build vertexes for a cube *)\r
+  with Vtx[0] do begin X:=-LSIZE; Y:=-LSIZE; Z:=-LSIZE; end;\r
+  with Vtx[1] do begin X:=+LSIZE; Y:=-LSIZE; Z:=-LSIZE; end;\r
+  with Vtx[2] do begin X:=-LSIZE; Y:=+LSIZE; Z:=-LSIZE; end;\r
+  with Vtx[3] do begin X:=+LSIZE; Y:=+LSIZE; Z:=-LSIZE; end;\r
+  with Vtx[4] do begin X:=-LSIZE; Y:=-LSIZE; Z:=+LSIZE; end;\r
+  with Vtx[5] do begin X:=+LSIZE; Y:=-LSIZE; Z:=+LSIZE; end;\r
+  with Vtx[6] do begin X:=-LSIZE; Y:=+LSIZE; Z:=+LSIZE; end;\r
+  with Vtx[7] do begin X:=+LSIZE; Y:=+LSIZE; Z:=+LSIZE; end;\r
+  for I:=0 to 7 do begin          (* Make points 16:16 fixed *)\r
+    Vtx[I].X := Vtx[I].X*$10000;\r
+    Vtx[I].Y := Vtx[I].Y*$10000;\r
+    Vtx[I].Z := Vtx[I].Z*$10000;\r
+  end;\r
+  (* Build faces *)\r
+  with Face[0] do begin Vtx[0]:=0; Vtx[1]:=2; Vtx[2]:=3; Vtx[3]:=1; end;\r
+  with Face[1] do begin Vtx[0]:=4; Vtx[1]:=5; Vtx[2]:=7; Vtx[3]:=6; end;\r
+  with Face[2] do begin Vtx[0]:=0; Vtx[1]:=1; Vtx[2]:=5; Vtx[3]:=4; end;\r
+  with Face[3] do begin Vtx[0]:=1; Vtx[1]:=3; Vtx[2]:=7; Vtx[3]:=5; end;\r
+  with Face[4] do begin Vtx[0]:=2; Vtx[1]:=0; Vtx[2]:=4; Vtx[3]:=6; end;\r
+  with Face[5] do begin Vtx[0]:=7; Vtx[1]:=3; Vtx[2]:=2; Vtx[3]:=6; end;\r
+  for I:=0 to 5 do Face[I].Texture := I;\r
+  (* Build textures and palette *)\r
+  Randomize;\r
+  FillChar( Palette, SizeOf(Palette), 0 );\r
+  MakePlasmaPalette( Palette, PAL_RGB );\r
+  mxSetPalette( @Palette, 0, 193 );\r
+  for I:=0 to 5 do MakeTexture( I );\r
+end;\r
+\r
+var\r
+  AX, AY, AZ: byte;\r
+  I: word;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;          (* Start with hidden page *)\r
+\r
+  AX := 0;\r
+  AY := 0;\r
+  AZ := 0;\r
+  (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+  tdSetTranslation( Trans );\r
+  tdSetPerspective( 400*$10000, $10000, $10000 );\r
+  (* Main loop, all magic here! *)\r
+  while( not KeyPressed ) do begin\r
+    tdSetRotation( AX, AY, AZ );                (* Set new angles *)\r
+    tdTransform( Vtx, XVtx, 8 );                (* 3D transform points *)\r
+    tdTransformToImage( XVtx, VVtx, 8, 160, 120+Page );\r
+    Inc( AX, 1 );                               (* Bump angles *)\r
+    Inc( AY, 1 );\r
+    Inc( AZ, 2 );\r
+    mxSetClipRegion( 0, Page, 320, 240 );       (* Set clip to new page *)\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+    mxRotatePalette( @Palette[1], 192, 3 );     (* Rotate palette *)\r
+    (* Draw cube: backface culling is straighforward in this case, so *)\r
+    (* it can be handled by the polygon filling procedure *)\r
+    for I:=0 to 5 do\r
+      mxTexturePoly( 4, Face[I].Vtx, VVtx, Txts[I].Desc, Txts[I].Data, Txts[I].Width );\r
+    mxStartLine( Page );                        (* Flip pages *)\r
+    mxSetPalette( @Palette[1], 1, 192 );        (* Set new palette *)\r
+    Page := 240-Page;\r
+  end;\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/x_/modex/DEMO03.EXE b/16/x_/modex/DEMO03.EXE
new file mode 100755 (executable)
index 0000000..c646c4b
Binary files /dev/null and b/16/x_/modex/DEMO03.EXE differ
diff --git a/16/x_/modex/DEMO03.PAS b/16/x_/modex/DEMO03.PAS
new file mode 100755 (executable)
index 0000000..01d10f4
--- /dev/null
@@ -0,0 +1,152 @@
+(*\r
+    DEMO03 - Simple star animation, morphs between a cube and a sphere\r
+    (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+const\r
+  MAXVTX = 1000;        (* Number of points *)\r
+  EDGE = 70;            (* Length of cube edge *)\r
+  RADIUS = 90;          (* Radius of sphere *)\r
+  WAITCOUNT = 192;      (* Frames to wait for non-morphing shapes *)\r
+  MS = 32;              (* Number of steps for morphing *)\r
+  Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+  InitMorph1: array[ 0..3 ] of integer = ( 0, MS, 0, 0 );\r
+  InitMorph2: array[ 0..3 ] of integer = ( 0, 0, 0, MS );\r
+  InitDelta1: array[ 0..3 ] of integer = ( 0, -1, 0, +1 );\r
+  InitDelta2: array[ 0..3 ] of integer = ( 0, +1, 0, -1 );\r
+type\r
+  T2DPoint = record\r
+    X, Y: integer;\r
+  end;\r
+  T3DPointArray = array[ 0..MAXVTX-1 ] of TPoint;\r
+  P3DPointArray = ^T3DPointArray;\r
+var\r
+  CubeVtx, SphereVtx, Vtx, XVtx: P3DPointArray;\r
+  VVtx  : array[ 0..MAXVTX-1 ] of T2DPoint;\r
+  Page  : word;\r
+  Status, Count, Delta1, Delta2, Morph1, Morph2: integer;\r
+\r
+procedure Swap( var A, B: longint );\r
+var\r
+  L: longint;\r
+begin\r
+  L := A; A := B; B := L;\r
+end;\r
+\r
+function Toggle( A: longint ): longint;\r
+begin\r
+  Toggle := A;\r
+  if( Random(2) = 0 ) then Toggle := -A;\r
+end;\r
+\r
+procedure Init;\r
+label Retry;\r
+var\r
+  I: integer;\r
+begin\r
+  New( CubeVtx );\r
+  New( SphereVtx );\r
+  New( Vtx );\r
+  New( XVtx );\r
+  (* Build vertexes (yes, I know this piece of code is terrible) *)\r
+  Randomize;\r
+  for I:=0 to MAXVTX-1 do begin\r
+    with CubeVtx^[I] do begin\r
+      (* Build cube *)\r
+      X := (longint(Random(2*EDGE))-EDGE)*$10000;\r
+      Y := (longint(Random(2*EDGE))-EDGE)*$10000;\r
+      Z := Toggle( EDGE*$10000 );\r
+      case Random(3) of\r
+        0: Swap( X, Z );\r
+        1: Swap( Y, Z );\r
+      end;\r
+    end;\r
+    with SphereVtx^[I] do begin\r
+      (* Build sphere *)\r
+Retry:\r
+      X := (longint(Random(2*RADIUS))-RADIUS);\r
+      Y := (longint(Random(2*RADIUS))-RADIUS);\r
+      if( X*X+Y*Y > RADIUS*RADIUS ) then goto Retry;\r
+      Z := Toggle( Round( Sqrt( Abs( RADIUS*RADIUS-X*X-Y*Y ) ) ) );\r
+      case Random(3) of\r
+        0: Swap( X, Z );\r
+        1: Swap( Y, Z );\r
+      end;\r
+      X := X * $10000; Y := Y * $10000; Z := Z * $10000;\r
+    end;\r
+  end;\r
+  (* Initialize morphing *)\r
+  Move( CubeVtx^, Vtx^, SizeOf(Vtx^) );\r
+  Status := 0;\r
+  Count := WAITCOUNT;\r
+end;\r
+\r
+procedure Morph;\r
+var\r
+  I: integer;\r
+begin\r
+  (* Fully unoptimized, slowest loop I could think of! *)\r
+  for I:=0 to MAXVTX-1 do begin\r
+    Vtx^[I].X := ((CubeVtx^[I].X * Morph1)+(SphereVtx^[I].X * Morph2)) div MS;\r
+    Vtx^[I].Y := ((CubeVtx^[I].Y * Morph1)+(SphereVtx^[I].Y * Morph2)) div MS;\r
+    Vtx^[I].Z := ((CubeVtx^[I].Z * Morph1)+(SphereVtx^[I].Z * Morph2)) div MS;\r
+  end;\r
+end;\r
+\r
+var\r
+  AX, AY, AZ: byte;\r
+  I: word;\r
+  C: char;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;          (* Start with hidden page *)\r
+\r
+  AX := 0;\r
+  AY := 0;\r
+  AZ := 0;\r
+  (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+  tdSetTranslation( Trans );\r
+  tdSetPerspective( 400*$10000, $10000, $10000 );\r
+  C := #0;\r
+  repeat\r
+    tdSetRotation( AX, AY, AZ );                (* Set new angles *)\r
+    tdTransform( Vtx^, XVtx^, MAXVTX );         (* 3D transform points *)\r
+    tdTransformToImage( XVtx^, VVtx, MAXVTX, 160, 120+Page );\r
+    Inc( AX, 1 );                               (* Bump angles *)\r
+    Inc( AY, 1 );\r
+    Inc( AZ, 2 );\r
+    mxSetClipRegion( 0, Page, 320, 240 );       (* Set clip to new page *)\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+    (* Draw points *)\r
+    for I:=0 to MAXVTX-1 do\r
+      mxPutPixel( VVtx[I].X, VVtx[I].Y, 128 + XVtx^[I].Z shr 18 );\r
+    mxStartLine( Page );                        (* Flip pages *)\r
+    Page := 240-Page;\r
+    (* Morph *)\r
+    if( Odd(Status) ) then begin\r
+      Morph;\r
+      Inc( Morph1, Delta1 );\r
+      Inc( Morph2, Delta2 );\r
+      if( Morph1 < 0 )or( Morph2 < 0 ) then Inc( Status );\r
+      if( Status = 4 ) then Status := 0;\r
+    end\r
+    else begin\r
+      Dec( Count );\r
+      if( Count < 0 ) then begin\r
+        Inc( Status );\r
+        Count :=  WAITCOUNT;\r
+        Morph1 := InitMorph1[Status];\r
+        Morph2 := InitMorph2[Status];\r
+        Delta1 := InitDelta1[Status];\r
+        Delta2 := InitDelta2[Status];\r
+      end;\r
+    end;\r
+  until( KeyPressed );\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/x_/modex/DEMO04.DAT b/16/x_/modex/DEMO04.DAT
new file mode 100755 (executable)
index 0000000..72aaad0
Binary files /dev/null and b/16/x_/modex/DEMO04.DAT differ
diff --git a/16/x_/modex/DEMO04.EXE b/16/x_/modex/DEMO04.EXE
new file mode 100755 (executable)
index 0000000..1fec5e8
Binary files /dev/null and b/16/x_/modex/DEMO04.EXE differ
diff --git a/16/x_/modex/DEMO04.PAS b/16/x_/modex/DEMO04.PAS
new file mode 100755 (executable)
index 0000000..1a94631
--- /dev/null
@@ -0,0 +1,198 @@
+(*\r
+    DEMO04 - Multiple textures and triple buffering (3 pages)\r
+    (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+const\r
+  MAXVTX = 256;\r
+  MAXCUB = 2;\r
+  MAXTXT = 2;\r
+  Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+  TxtSunDial: array[ 0..7 ] of word = (\r
+    $7F80,$0080, $0080,$0080, $0080,$7E80, $7F80,$7E80 );\r
+  TxtSapphire : array[ 0..7 ] of word = (\r
+    $0080,$0080, $0080,$1F80, $1F80,$1F80, $1F80,$0080 );\r
+  TxtMarble: array[ 0..7 ] of word = (\r
+    $0080,$8080, $0080,$FD80, $7F80,$FD80, $7F80,$8080 );\r
+type\r
+  T2DPoint = record\r
+    X, Y: integer;\r
+  end;\r
+  TTexture = record\r
+    Desc   : array[ 0..3 ] of record X, Y: word end;\r
+    Width  : word;\r
+    Data   : pointer;\r
+  end;\r
+  TQuad = record\r
+    Vtx    : array[ 0..3 ] of word;\r
+    Texture: word;\r
+  end;\r
+  TCube    = record\r
+    Face   : array[ 0..5 ] of TQuad;\r
+    Base   : integer;\r
+  end;\r
+var\r
+  Vtx, XVtx: array[ 0..MAXVTX ] of TPoint;\r
+  VVtx     : array[ 0..MAXVTX ] of T2DPoint;\r
+  Cube     : array[ 0..MAXCUB ] of TCube;\r
+  ZList    : array[ 0..MAXCUB ] of integer;\r
+  VtxCnt   : word;\r
+  Txts     : array[ 0..MAXTXT ] of TTexture;\r
+  Page     : word;\r
+  Palette  : array[ byte ] of record R, G, B: byte; end;\r
+  TxtDat1, TxtDat2: pointer;\r
+\r
+(* Add a new entry to the vertex array *)\r
+procedure AddVtx( PX, PY, PZ: longint );\r
+begin\r
+  with Vtx[VtxCnt] do begin X:=PX*$10000; Y:=PY*$10000; Z:=PZ*$10000; end;\r
+  Inc( VtxCnt );\r
+end;\r
+\r
+procedure MakeCube( var C: TCube; X1,Y1,Z1, X2,Y2,Z2, TX,TY,TZ, Texture: integer );\r
+const\r
+  FaceIdx: array[ 0..23 ] of integer = (\r
+    0,1,2,3, 0,4,5,1, 1,5,6,2, 2,6,7,3, 3,7,4,0, 6,5,4,7 );\r
+var\r
+  I, VC: integer;\r
+begin\r
+  VC := VtxCnt;\r
+  C.Base := VC;\r
+  AddVtx( X1+TX, Y1+TY, Z1+TZ );\r
+  AddVtx( X2+TX, Y1+TY, Z1+TZ );\r
+  AddVtx( X2+TX, Y2+TY, Z1+TZ );\r
+  AddVtx( X1+TX, Y2+TY, Z1+TZ );\r
+  AddVtx( X1+TX, Y1+TY, Z2+TZ );\r
+  AddVtx( X2+TX, Y1+TY, Z2+TZ );\r
+  AddVtx( X2+TX, Y2+TY, Z2+TZ );\r
+  AddVtx( X1+TX, Y2+TY, Z2+TZ );\r
+  for I:=0 to 23 do C.Face[I shr 2].Vtx[I and 3] := VC+FaceIdx[I];\r
+  for I:=0 to 5 do C.Face[I].Texture := Texture;\r
+end;\r
+\r
+procedure MakeTexture( Idx: integer; var VtxData );\r
+var\r
+  P: ^word;\r
+  I: integer;\r
+begin\r
+  P := @VtxData;\r
+  with Txts[Idx] do begin\r
+    for I:=0 to 3 do begin\r
+      Desc[I].X := P^; Inc( P );\r
+      Desc[I].Y := P^; Inc( P );\r
+    end;\r
+    Width := 129;\r
+    Data := TxtDat1;\r
+  end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+  I: integer;\r
+  V: integer;\r
+  F: file;\r
+  P: array[ 1..768 ] of byte;\r
+begin\r
+  (* Initialize objects *)\r
+  VtxCnt := 0;\r
+  MakeCube( Cube[0], -64,-64,8, 64,64,-8, 0,0,0, 1 );   (* Sundial *)\r
+  Cube[0].Face[0].Texture := 0;\r
+  V := VtxCnt;\r
+  MakeCube( Cube[1], -16,-16,16, 16,16,-16, 0,0,0, 2 ); (* Sapphire *)\r
+  tdSetTranslation( Trans );\r
+  tdSetRotation( 32, 32, 00 );\r
+  tdRotate( Vtx[V], XVtx[V], 8 );       (* Got to rotate this cube *)\r
+  for I:=V to V+7 do begin\r
+    Vtx[I].X := XVtx[I].X;\r
+    Vtx[I].Y := XVtx[I].Y;\r
+    Vtx[I].Z := XVtx[I].Z + 100*$10000;\r
+  end;\r
+  MakeCube( Cube[2], -64,-4,48, 64,4,-48, 0,68,56, 1 ); (* Marble *)\r
+  (* Load texture and palette *)\r
+  Assign( F, 'DEMO04.DAT' );\r
+  Reset( F, 1 );\r
+  BlockRead( F, P, SizeOf(P) );\r
+  mxSetPalette( @P, 0, 256 );\r
+  GetMem( TxtDat1, 63*1024 );\r
+  BlockRead( F, TxtDat1^, 129*286 );\r
+  Close( F );\r
+  TxtDat2 := Ptr( Seg(TxtDat1^), Ofs(TxtDat1^)+129*254 );\r
+  (* Init textures *)\r
+  MakeTexture( 0, TxtSundial );\r
+  MakeTexture( 1, TxtMarble );\r
+  MakeTexture( 2, TxtSapphire );\r
+  Txts[2].Data := TxtDat2;\r
+end;\r
+\r
+(* Sort procedure, not worth optimizing with only a few objects *)\r
+procedure SortObjects;\r
+var\r
+  I, J, K: integer;\r
+  ZMax: array[ 0..MAXCUB ] of longint;\r
+  ZI: integer;\r
+  L: longint;\r
+begin\r
+  for I:=0 to MAXCUB do begin\r
+    L := XVtx[Cube[I].Base].Z;\r
+    for J:=1 to 7 do\r
+      if( L > XVtx[Cube[I].Base+J].Z ) then L := XVtx[Cube[I].Base+J].Z;\r
+    ZMax[I] := L;\r
+    ZList[I] := I;\r
+  end;\r
+  for I:=0 to MAXCUB-1 do begin\r
+    ZI := I;\r
+    for J:=I+1 to MAXCUB do\r
+      if( ZMax[ZList[J]] > ZMax[ZList[ZI]] ) then ZI := J;\r
+    if( ZI <> I ) then begin\r
+      K := ZList[I];\r
+      ZList[I] := ZList[ZI];\r
+      ZList[ZI] := K;\r
+    end;\r
+  end;\r
+end;\r
+\r
+var\r
+  AX, AY, AZ: byte;\r
+  I, J, K: word;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;          (* Start with hidden page *)\r
+\r
+  (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+  AX := 0; AY := 0; AZ := 0;\r
+  tdSetTranslation( Trans );\r
+  tdSetPerspective( 600*$10000, $10000, $10000 );\r
+  (* Main loop, all magic here! *)\r
+  while( not KeyPressed ) do begin\r
+    tdSetRotation( AX, AY, AZ );                (* Set new angles *)\r
+    tdTransform( Vtx, XVtx, VtxCnt );           (* 3D transform points *)\r
+    tdTransformToImage( XVtx, VVtx, VtxCnt, 160, 120+Page );\r
+    Inc( AX, 1 );                               (* Bump angles *)\r
+    Inc( AY, 2 );\r
+    Inc( AZ, 1 );\r
+    mxSetClipRegion( 0, Page, 320, 240 );       (* Set clip to new page *)\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+    (* Draw objects *)\r
+    SortObjects;\r
+    for I:=0 to MAXCUB do with Cube[ZList[I]] do begin\r
+      for J:=0 to 5 do begin\r
+        K := Face[J].Texture;\r
+        mxTexturePoly( 4, Face[J].Vtx, VVtx, Txts[K].Desc, Txts[K].Data^, Txts[K].Width );\r
+      end;\r
+    end;\r
+    (* Flip page: at 320x240 the Start Address Register Low is always zero *)\r
+    case Page of\r
+      0  : begin PortW[$3D4] := $000C; Page := 240; end;\r
+      240: begin PortW[$3D4] := $4B0C; Page := 480; end;\r
+      480: begin PortW[$3D4] := $960C; Page := 0; end;\r
+    end;\r
+    mxWaitRetrace; (* If the frame rate seems low, try to remove this line *)\r
+  end;\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/x_/modex/DEMO05.EXE b/16/x_/modex/DEMO05.EXE
new file mode 100755 (executable)
index 0000000..21a7c20
Binary files /dev/null and b/16/x_/modex/DEMO05.EXE differ
diff --git a/16/x_/modex/DEMO05.PAS b/16/x_/modex/DEMO05.PAS
new file mode 100755 (executable)
index 0000000..819c5cf
--- /dev/null
@@ -0,0 +1,131 @@
+(*\r
+   DEMO05 - A Gouraud-shaded rotating torus\r
+   (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+(* Define ALTPAL for alternate palette *)\r
+{$define ALTPAL}\r
+\r
+const\r
+  MAXVTX1 = 15; RADIUS1 = 70;   (* MAXVTX1+1 must be multiple of 4 *)\r
+  MAXVTX2 = 15; RADIUS2 = 30;\r
+  MAXVTX  = (MAXVTX1+1)*(MAXVTX2+1)-1;\r
+  MAXFACE = MAXVTX;\r
+  Trans : TPoint = ( X:0; Y:0; Z:0 );           (* Object translation *)\r
+  Light : TPoint = ( X:0; Y:0; Z:-63*$10000 );  (* Light direction *)\r
+type\r
+  TQuad   = record\r
+    QVtx  : array[ 0..3 ] of integer;\r
+  end;\r
+var\r
+  Vtx, XVtx : array[ 0..MAXVTX ] of TPoint;     (* Points *)\r
+  VVtx      : array[ 0..MAXVTX ] of record X, Y: integer end;\r
+  Face      : array[ 0..MAXFACE ] of TQuad;     (* Polys *)\r
+  Culled    : array[ 0..MAXFACE ] of integer;\r
+  GNrm,XGNrm: array[ 0..MAXVTX ] of TVector;    (* Gouraud normals *)\r
+  VtxLight  : array[ 0..MAXVTX ] of integer;    (* Points brightness *)\r
+  Page      : word;\r
+\r
+function GetVtx( I1, I2: integer ): integer;\r
+begin\r
+  GetVtx := (I1 mod (MAXVTX1+1))*(MAXVTX2+1) + I2 mod (MAXVTX2+1);\r
+end;\r
+\r
+procedure Init;\r
+var\r
+  R, N, X, Y, Z: real;\r
+  I, J, K, V: integer;\r
+begin\r
+  (* Build vertexes *)\r
+  for I:=0 to MAXVTX1 do begin\r
+    K := (I + (MAXVTX1+1) shr 2) mod (MAXVTX1+1);\r
+    R := RADIUS1 + RADIUS2*Cos( 2*K*Pi / (MAXVTX1+1) );\r
+    for J:=0 to MAXVTX2 do begin\r
+      V := I*(MAXVTX2+1)+J;                     (* Index of current vertex *)\r
+      (* Compute coordinates of current vertex *)\r
+      X := R*Cos(2*J*Pi / (MAXVTX2+1));         (* Get coordinates *)\r
+      Y := R*Sin(2*J*Pi / (MAXVTX2+1));\r
+      Z := RADIUS2*Sin(2*K*Pi / (MAXVTX1+1));\r
+      Vtx[V].X := Round( X )*$10000;            (* Save coordinates *)\r
+      Vtx[V].Y := Round( Y )*$10000;\r
+      Vtx[V].Z := Round( Z )*$10000;\r
+      (* Compute direction of Gouraud normal thru current vertex *)\r
+      X := X - RADIUS1*Cos(2*J*Pi / (MAXVTX2+1));\r
+      Y := Y - RADIUS1*Sin(2*J*Pi / (MAXVTX2+1));\r
+      N := Sqrt( X*X + Y*Y + Z*Z );             (* Get vector length *)\r
+      GNrm[V].X := Trunc( X*$10000/N );         (* Save normal vector *)\r
+      GNrm[V].Y := Trunc( Y*$10000/N );\r
+      GNrm[V].Z := Trunc( Z*$10000/N );\r
+    end;\r
+  end;\r
+  (* Generate faces so that depth-sorting is not needed: there are still *)\r
+  (* some *very* little errors, but this is the best I could devise *)\r
+  J := 0;\r
+  K := 0;\r
+  for I:=0 to MAXFACE do with Face[I] do begin\r
+    QVtx[0] := GetVtx( J, K );\r
+    QVtx[1] := GetVtx( J, K+1 );\r
+    QVtx[2] := GetVtx( J+1, K+1 );\r
+    QVtx[3] := GetVtx( J+1, K );\r
+    Inc( K );\r
+    if( K > MAXVTX2 ) then begin\r
+      K := 0;\r
+      Inc( J );\r
+    end;\r
+  end;\r
+{$ifndef ALTPAL}\r
+  for I:=0 to 63 do mxSetColor( I+64, 0, 0, I );     (* Blue palette *)\r
+{$else}\r
+  for I:=0 to 31 do mxSetColor(I+64, 0, I shl 1, 0); (* Green neon palette *)\r
+  for I:=32 to 63 do mxSetColor ( I+64, (I-32) shl 1, 63, (I-32) shl 1 );\r
+{$endif}\r
+end;\r
+\r
+var\r
+  AX, AY, AZ: byte;\r
+  I: word;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;          (* Start with hidden page *)\r
+\r
+  AX := 0;\r
+  AY := 0;\r
+  AZ := 0;\r
+  (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+  tdSetTranslation( Trans );\r
+  tdSetLight( Light );\r
+  tdSetPerspective( 400*$10000, $10000, $10000 );\r
+  (* Main loop, all magic here! *)\r
+  while( not KeyPressed ) do begin\r
+    tdSetRotation( AX, AY, AZ );                (* Set new angles *)\r
+    tdTransform( Vtx, XVtx, MAXVTX+1 );         (* 3D transform points *)\r
+    tdTransformToImage( XVtx, VVtx, MAXVTX+1, 160, 120+Page );\r
+    tdRotate( GNrm, XGNrm, MAXVTX+1 );          (* Rotate Gouraud normals *)\r
+    tdTransformLight( XGNrm, VtxLight, MAXVTX+1 );\r
+    (* Backplane culling is not really needed here! *)\r
+    FillChar( Culled, SizeOf(Culled), 0 );\r
+    tdBackPlaneCull( Face, XVtx, Culled, MAXFACE+1, SizeOf(TQuad) );\r
+    Inc( AX, 1 );                               (* Bump angles *)\r
+    Inc( AY, 2 );\r
+    Inc( AZ, 3 );\r
+    mxSetClipRegion( 0, Page, 320, 240 );       (* Set clip to new page *)\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+    (* Draw polygons *)\r
+    for I:=0 to MAXFACE do with Face[I] do\r
+      if( Culled[I] >= 0 ) then mxGouraudPoly( 4, QVtx, VVtx, VtxLight, 64 );\r
+    (* Flip page: at 320x240 the Start Address Register Low is always zero *)\r
+    case Page of\r
+      0  : begin PortW[$3D4] := $000C; Page := 240; end;\r
+      240: begin PortW[$3D4] := $4B0C; Page := 480; end;\r
+      480: begin PortW[$3D4] := $960C; Page := 0; end;\r
+    end;\r
+    mxWaitRetrace; (* Uncomment this instruction if screen flickers *)\r
+  end;\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/x_/modex/DEMO06.DAT b/16/x_/modex/DEMO06.DAT
new file mode 100755 (executable)
index 0000000..1ac2c2b
Binary files /dev/null and b/16/x_/modex/DEMO06.DAT differ
diff --git a/16/x_/modex/DEMO06.EXE b/16/x_/modex/DEMO06.EXE
new file mode 100755 (executable)
index 0000000..f1308e8
Binary files /dev/null and b/16/x_/modex/DEMO06.EXE differ
diff --git a/16/x_/modex/DEMO06.PAS b/16/x_/modex/DEMO06.PAS
new file mode 100755 (executable)
index 0000000..f26af06
--- /dev/null
@@ -0,0 +1,135 @@
+(*\r
+    DEMO06 - Magnifying glass\r
+    (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+  R = 40;               (* Lens radius *)\r
+  K : real = 1.8;       (* Magnifying factor, less makes a stronger lens *)\r
+type\r
+  TLine   = array[ 0..319 ] of byte;\r
+  PLine   = ^TLine;\r
+  TScreen = array[ 0..239 ] of PLine;\r
+var\r
+  VScreen: TScreen;                             (* Virtual screen *)\r
+  BallX  : array[ 0..R, 0..R ] of integer;\r
+  BallY  : array[ 0..R, 0..R ] of integer;\r
+  Sprite : array[ -R..R, -R..R ] of byte;\r
+  Page   : word;\r
+\r
+(* Returns "lens-view" coordinates of X,Y *)\r
+procedure GetCoords( var X, Y: integer );\r
+var\r
+  LR, Z, SinA, SinB, TgB, Q: real;\r
+begin\r
+  LR := Sqrt( X*X + Y*Y );\r
+  if( LR = 0 ) then Exit;\r
+  if( LR < R ) then begin\r
+    Z := Sqrt( R*R - LR*LR );\r
+    SinA := LR / R;\r
+    SinB := SinA / K;\r
+    TgB := SinB / Sqrt( 1-SinB*SinB );\r
+    Q := LR - TgB*Z;\r
+    X := Round( X * ( Q/LR ) );\r
+    Y := Round( Y * ( Q/LR ) );\r
+  end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+  F      : file;\r
+  Palette: array[ 0..767 ] of record R, G, B: byte; end;\r
+  X, Y,\r
+  X2, Y2 : integer;\r
+begin\r
+  (* Load background image *)\r
+  Assign( F, 'demo06.dat' );\r
+  Reset( F, 1 );\r
+  BlockRead( F, Palette, 768 );\r
+  mxSetPalette( @Palette, 0, 256 );\r
+  for Y:=0 to 239 do begin\r
+    New( VScreen[Y] );\r
+    BlockRead( F, VScreen[Y]^, 320 );\r
+    mxPutImage( VScreen[Y], 0, 480+Y, 320, 1, OP_MOVE );\r
+  end;\r
+  Close( F );\r
+  (* Build lens *)\r
+  for X:=0 to R do begin\r
+    for Y:=0 to R do begin\r
+      X2 := X;\r
+      Y2 := Y;\r
+      GetCoords( X2, Y2 );\r
+      BallX[X, Y] := X2;\r
+      BallY[X, Y] := Y2;\r
+    end;\r
+  end;\r
+end;\r
+\r
+procedure PutLens( OX, OY: integer );\r
+var\r
+  X, Y: integer;\r
+begin\r
+  for X:=0 to R do begin\r
+    for Y:=0 to R do begin\r
+      Sprite[Y][X] := VScreen[ OY+BallY[X,Y] ]^[ OX+BallX[X,Y] ];\r
+      Sprite[Y][-X] := VScreen[ OY+BallY[X,Y] ]^[ OX-BallX[X,Y] ];\r
+      Sprite[-Y][X] := VScreen[ OY-BallY[X,Y] ]^[ OX+BallX[X,Y] ];\r
+      Sprite[-Y][-X] := VScreen[ OY-BallY[X,Y] ]^[ OX-BallX[X,Y] ];\r
+    end;\r
+  end;\r
+  (* Draw the sprite *)\r
+  mxPutImage( @Sprite, OX-R, OY-R+Page, 2*R+1, 2*R+1, OP_MOVE );\r
+end;\r
+\r
+function Delta: integer;\r
+begin\r
+  Delta := Random(3)+2;\r
+end;\r
+\r
+procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer );\r
+begin\r
+  if( Cond ) then begin\r
+    Coord := NewCoord;\r
+    DeltaC := Sign*Delta;\r
+  end;\r
+end;\r
+\r
+var\r
+  X, Y, DX, DY: integer;\r
+  C: char;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;\r
+  X := R;\r
+  Y := R;\r
+  Randomize;\r
+  DX := Delta;\r
+  DY := Delta;\r
+\r
+  (* Main loop *)\r
+  repeat\r
+    (* Update video *)\r
+    mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+    PutLens( X, Y );\r
+    mxCircle( X, Page+Y, R, 0 );\r
+    (* Update lens coordinates *)\r
+    Inc( X, DX );\r
+    Check( X+R >= 319, X, DX, 319-R, -1 );\r
+    Check( X <= R, X, DX, R, +1 );\r
+    Inc( Y, DY );\r
+    Check( Y+R >= 239, Y, DY, 239-R, -1 );\r
+    Check( Y <= R, Y, DY, R, +1 );\r
+    (* Flip pages: double buffering, avoid wait for display *)\r
+    case Page of\r
+      0  : begin PortW[$3D4] := $000C; Page := 240; end;\r
+      240: begin PortW[$3D4] := $4B0C; Page := 0; end;\r
+    end;\r
+    mxWaitRetrace; (* Wait for hidden page to show *)\r
+  until( KeyPressed );\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/x_/modex/DEMO07.EXE b/16/x_/modex/DEMO07.EXE
new file mode 100755 (executable)
index 0000000..8a40116
Binary files /dev/null and b/16/x_/modex/DEMO07.EXE differ
diff --git a/16/x_/modex/DEMO07.PAS b/16/x_/modex/DEMO07.PAS
new file mode 100755 (executable)
index 0000000..04fff79
--- /dev/null
@@ -0,0 +1,68 @@
+(*\r
+    DEMO07 - Hardware scrolling\r
+    Copyright (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+  (* Change this if scrolling seems jerky (this simple program does *)\r
+  (* not handle vertical retrace/display very well) *)\r
+  STEPS = 5;\r
+\r
+procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer );\r
+begin\r
+  if( Cond ) then begin\r
+    Coord := NewCoord;\r
+    DeltaC := Sign*(Random(3)+2);\r
+  end;\r
+end;\r
+\r
+var\r
+  I, X, Y, DX, DY: integer;\r
+begin\r
+  (* Initialize library and graphics mode *)\r
+  mxInit;\r
+  mxSetMode( MX_320x200 );\r
+  (* Set a 640x400 virtual screen *)\r
+  mxSetVirtualScreen( 640, 400 );\r
+  mxSetClip( TRUE );\r
+\r
+  X := 0;\r
+  Y := 0;\r
+  DX := 1;\r
+  DY := 1;\r
+\r
+  (* Main loop: draw lines, circles, points and rectangles in separate *)\r
+  (* 320x200 windows, while smoothly panning virtual screen *)\r
+  while( not KeyPressed ) do begin\r
+    (* Points *)\r
+    mxSetClipRegion( 0, 0, 320, 200 );\r
+    for I:=1 to STEPS do\r
+      mxPutPixel( Random(320), Random(200), Random(16) );\r
+    (* Lines *)\r
+    mxSetClipRegion( 0, 200, 320, 200 );\r
+    for I:=1 to STEPS do\r
+      mxLine( Random(320), Random(200)+200, Random(320), Random(200)+200, Random(16), OP_SET );\r
+    (* Circles *)\r
+    mxSetClipRegion( 320, 0, 320, 200 );\r
+    for I:=1 to STEPS do\r
+      mxCircle( Random(320)+320, Random(200), Random(100), Random(16) );\r
+    (* Boxes *)\r
+    mxSetClipRegion( 320, 200, 320, 200 );\r
+    for I:=1 to STEPS do\r
+      mxFillBox( Random(320)+320, Random(200)+200, Random(100)+1, Random(100)+1, Random(16), OP_SET );\r
+    (* Pan *)\r
+    Inc( X, DX );\r
+    Check( X+320 >= 639, X, DX, 319, -1 );\r
+    Check( X < 0, X, DX, 0, +1 );\r
+    Inc( Y, DY );\r
+    Check( Y+200 >= 399, Y, DY, 199, -1 );\r
+    Check( Y < 0, Y, DY, 0, +1 );\r
+    mxPan( X, Y );\r
+    mxWaitRetrace;\r
+  end;\r
+\r
+  (* Shutdown *)\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/x_/modex/MATH.INC b/16/x_/modex/MATH.INC
new file mode 100755 (executable)
index 0000000..742af41
--- /dev/null
@@ -0,0 +1,34 @@
+;\r
+; MATH.INC - Include file for THREED.ASM\r
+;\r
+\r
+; 3-dimensional point, coordinates in fixed format (16:16)\r
+;\r
+TPOINT  STRUC\r
+        X       DD      ?\r
+        Y       DD      ?\r
+        Z       DD      ?\r
+TPOINT  ENDS\r
+\r
+; 2-dimensional point, coordinates in integer format\r
+;\r
+TIMAGEPOINT     STRUC\r
+        IX      DW      ?\r
+        IY      DW      ?\r
+TIMAGEPOINT     ENDS\r
+\r
+; Fixed-point divide: EAX = EAX / arg\r
+;\r
+.xdiv   MACRO   arg\r
+        xor     edx, edx\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    arg\r
+ENDM\r
+\r
+; Fixed-point multiply: EAX = EAX * arg\r
+;\r
+.xmul   MACRO   arg\r
+        imul    arg\r
+        shrd    eax, edx, 16\r
+ENDM\r
diff --git a/16/x_/modex/PLASMA.PAS b/16/x_/modex/PLASMA.PAS
new file mode 100755 (executable)
index 0000000..237e292
--- /dev/null
@@ -0,0 +1,103 @@
+unit Plasma;\r
+interface\r
+\r
+const\r
+  PAL_RGB       = 0;\r
+  PAL_CLOUDS    = 1;\r
+  PAL_LANDSCAPE = 2;\r
+\r
+procedure MakePlasma( X, Y: integer; W, H: word; C1, C2, C3, C4: byte );\r
+procedure MakePlasmaPalette( var Palette; What: word );\r
+\r
+implementation uses Modex;\r
+\r
+procedure NewColor( XA, YA, X, Y, XB, YB: integer );\r
+var\r
+  Color: longint;\r
+begin\r
+  Color := Abs( XA-XB )+Abs( YA-YB );\r
+  Color := Random( Color shl 1 )-Color;\r
+  Color := (Color+mxGetPixel( XA, YA )+mxGetPixel( XB, YB )+1) shr 1;\r
+  if( Color < 1 ) then Color := 1;\r
+  if( Color > 192 ) then Color := 192;\r
+  if( mxGetPixel( X, Y ) = 0 ) then\r
+    mxPutPixel( X, Y, Lo(Color) );\r
+end;\r
+\r
+procedure Divide( X1, Y1, X2, Y2: integer );\r
+var\r
+  X, Y, Color: integer;\r
+begin\r
+  if not( (X2-X1<2)and(Y2-Y1<2) ) then begin\r
+    X := (X1+X2) shr 1;\r
+    Y := (Y1+Y2) shr 1;\r
+    NewColor( X1, Y1, X, Y1, X2, Y1 );\r
+    NewColor( X2, Y1, X2, Y, X2, Y2 );\r
+    NewColor( X1, Y2, X, Y2, X2, Y2 );\r
+    NewColor( X1, Y1, X1, Y, X1, Y2 );\r
+    Color := (mxGetPixel( X1, Y1 )+mxGetPixel( X2, Y1 )+\r
+              mxGetPixel( X2, Y2 )+mxGetPixel( X1, Y2 )) shr 2;\r
+    mxPutPixel( X, Y, Color );\r
+    Divide( X1, Y1, X, Y );\r
+    Divide( X, Y1, X2, Y );\r
+    Divide( X, Y, X2, Y2 );\r
+    Divide( X1, Y, X, Y2 );\r
+  end;\r
+end;\r
+\r
+procedure MakePlasma;\r
+begin\r
+  Dec( W );\r
+  Dec( H );\r
+  mxPutPixel( X, Y, C1 );\r
+  mxPutPixel( X, Y+H, C2 );\r
+  mxPutPixel( X+W, Y+H, C3 );\r
+  mxPutPixel( X+W, Y, C4 );\r
+  Divide( X, Y, X+W, Y+H );\r
+end;\r
+\r
+procedure MakePlasmaPalette;\r
+type\r
+  TPal = array[ byte ] of record R, G, B: byte end;\r
+var\r
+  I: word;\r
+begin\r
+  FillChar( TPal(Palette)[1], 192*3, 0 );\r
+  case What of\r
+    PAL_CLOUDS:\r
+      for I:=1 to 192 do begin\r
+        TPal(Palette)[I].R := Abs( I-96 )*63 div 96;\r
+        TPal(Palette)[I].G := Abs( I-96 )*63 div 96;\r
+        TPal(Palette)[I].B := 63;\r
+      end;\r
+    PAL_LANDSCAPE:\r
+      begin\r
+        for I:=0 to 31 do begin\r
+          TPal(Palette)[I+1].R := I;\r
+          TPal(Palette)[I+1].G := I;\r
+          TPal(Palette)[I+1].B := I + I shr 1+15;\r
+        end;\r
+        for I:=32 to 63 do begin\r
+          TPal(Palette)[I+1].R := 0;\r
+          TPal(Palette)[I+1].G := I;\r
+          TPal(Palette)[I+1].B := 0;\r
+        end;\r
+        for I:=64 to 191 do begin\r
+          TPal(Palette)[I+1].R := (I-64) div 3 + 15;\r
+          TPal(Palette)[I+1].G := (I-64) div 3 + 15;\r
+          TPal(Palette)[I+1].B := (I-64) div 3 + 15;\r
+        end;\r
+      end;\r
+    else\r
+      for I:=1 to 64 do begin\r
+        TPal(Palette)[I].G := I-1;\r
+        TPal(Palette)[I].B := 64-I;\r
+        TPal(Palette)[I+64].R := I-1;\r
+        TPal(Palette)[I+64].G := 64-I;\r
+        TPal(Palette)[I+128].B := I-1;\r
+        TPal(Palette)[I+128].R := 64-I;\r
+      end;\r
+  end;\r
+end;\r
+\r
+end.
\ No newline at end of file
diff --git a/16/x_/modex/QIX2.EXE b/16/x_/modex/QIX2.EXE
new file mode 100755 (executable)
index 0000000..a10d7db
Binary files /dev/null and b/16/x_/modex/QIX2.EXE differ
diff --git a/16/x_/modex/QIX2.PAS b/16/x_/modex/QIX2.PAS
new file mode 100755 (executable)
index 0000000..d1b5979
--- /dev/null
@@ -0,0 +1,210 @@
+{$E-,N+}\r
+uses Crt, Modex;\r
+\r
+const\r
+  DEFVERT = 12;         (* Vertex count *)\r
+  DEFREPL = 3;          (* Repetition count *)\r
+  DEFQIXS = 2;          (* Qixs *)\r
+  FADESPEED = 48;\r
+type\r
+  TPoint = record\r
+    X, Y : integer;\r
+  end;\r
+  TRGB = record\r
+    R, G, B: byte;\r
+  end;\r
+  TQix = record\r
+    Color: integer;\r
+    Vert : array[ 0..DEFVERT-1, 0..DEFREPL-1 ] of TPoint;\r
+    Delta: array[ 0..DEFVERT-1 ] of TPoint;\r
+  end;\r
+var\r
+  Page : integer;\r
+  MaxX,\r
+  MaxY : word;\r
+  Qix  : array[ 0..DEFQIXS-1 ] of TQix;\r
+  Pal  : array[ byte ] of TRGB;\r
+\r
+type\r
+  TReal = double;\r
+  TRPoint = record\r
+    X, Y: TReal;\r
+  end;\r
+  TMatrix = array[ 0..3, 0..3 ] of TReal;\r
+var\r
+  M: TMatrix;\r
+  G: array[ 0..DEFVERT-1 ] of TRPoint;\r
+  C: array[ 0..DEFVERT-1 ] of TRPoint;\r
+\r
+procedure BumpPal( Idx, DR, DG, DB, Steps: integer );\r
+var\r
+  I: integer;\r
+begin\r
+  for I:=1 to Steps do begin\r
+    Pal[Idx+1].R := Pal[Idx].R + DR;\r
+    Pal[Idx+1].G := Pal[Idx].G + DG;\r
+    Pal[Idx+1].B := Pal[Idx].B + DB;\r
+    Inc( Idx );\r
+  end;\r
+end;\r
+\r
+procedure InitPalette;\r
+begin\r
+  with Pal[0] do begin R:=0; G:=0; B:=0; end;\r
+  with Pal[1] do begin R:=0; G:=0; B:=62; end;\r
+  BumpPal( 1,   0, 2, -2,  31 );\r
+  BumpPal( 32,  2, -2, 0,  31 );\r
+  BumpPal( 63,  -2, 2, 2,  31 );\r
+  BumpPal( 94,  2, 0, -2,  31 );\r
+  BumpPal( 125, -2, -2, 2, 31 );\r
+end;\r
+\r
+procedure Init( var Qix: TQix; Color: integer );\r
+var\r
+  I: integer;\r
+begin\r
+  FillChar( Qix.Vert, SizeOf(Qix.Vert), 0 );\r
+  for I:=0 to DEFVERT-1 do begin\r
+    Qix.Vert[I, DEFREPL-1].X := Random( MaxX );\r
+    Qix.Vert[I, DEFREPL-1].Y := Random( MaxY );\r
+    Qix.Delta[I].X := Random(5)+1;\r
+    Qix.Delta[I].Y := Random(5)+1;\r
+  end;\r
+  Qix.Color := Color;\r
+\r
+  (* Initialize matrix (Catmull-Rom) *)\r
+  M[0,0] := -1/2; M[0,1] := 3/2; M[0,2] := -3/2; M[0,3] := 1/2;\r
+  M[1,0] := 1; M[1,1] := -5/2; M[1,2] := 2; M[1,3] := -1/2;\r
+  M[2,0] := -1/2; M[2,1] := 0; M[2,2] := 1/2; M[2,3] := 0;\r
+  M[3,0] := 0; M[3,1] := 1; M[3,2] := 0; M[3,3] := 0;\r
+end;\r
+\r
+procedure mxBezier( var Qix: TQix; I0, Idx, N: integer );\r
+var\r
+  I, J: integer;\r
+  T, T2, T3: TReal;\r
+  X0, Y0, X, Y: TReal;\r
+  Delta: TReal;\r
+begin\r
+  (* Compute coefficients *)\r
+  for I:=0 to 3 do begin\r
+    C[I].X := 0;\r
+    for J:=0 to 3 do C[I].X := C[I].X + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].X;\r
+    C[I].Y := 0;\r
+    for J:=0 to 3 do C[I].Y := C[I].Y + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].Y;\r
+  end;\r
+  X0 := C[3].X;\r
+  Y0 := C[3].Y;\r
+  Delta := 1 / N;\r
+  T := 0;\r
+  for I:=1 to N do begin\r
+    T := T + Delta;\r
+    T2 := T*T;\r
+    T3 := T*T2;\r
+    X := C[0].X*T3 + C[1].X*T2 + C[2].X*T + C[3].X;\r
+    Y := C[0].Y*T3 + C[1].Y*T2 + C[2].Y*T + C[3].Y;\r
+    mxLine( Round(X0), Page+Round(Y0), Round(X), Page+Round(Y), Qix.Color, OP_SET );\r
+    X0 := X;\r
+    Y0 := Y;\r
+  end;\r
+end;\r
+\r
+procedure Plot( var Qix: TQix; Idx: integer );\r
+var\r
+  I, J: integer;\r
+begin\r
+  for I:=0 to DEFVERT-1 do begin\r
+    mxBezier( Qix, I, Idx, 12 );\r
+  end;\r
+end;\r
+\r
+procedure Update( var Qix: TQix; Idx: integer );\r
+var\r
+  I: integer;\r
+begin\r
+  for I:=0 to DEFVERT-1 do with Qix do begin\r
+    Inc( Vert[I,Idx].X, Delta[I].X );\r
+    if( Vert[I,Idx].X < 0 ) then begin\r
+      Vert[I,Idx].X := 0;\r
+      Delta[I].X := Random( 5 )+1;\r
+    end;\r
+    if( Vert[I,Idx].X > MaxX ) then begin\r
+      Vert[I,Idx].X := MaxX;\r
+      Delta[I].X := -Random( 5 )-1;\r
+    end;\r
+    Inc( Vert[I,Idx].Y, Delta[I].Y );\r
+    if( Vert[I,Idx].Y < 0 ) then begin\r
+      Vert[I,Idx].Y := 0;\r
+      Delta[I].Y := Random( 5 )+1;\r
+    end;\r
+    if( Vert[I,Idx].Y > MaxY ) then begin\r
+      Vert[I,Idx].Y := MaxY;\r
+      Delta[I].Y := -Random( 5 )-1;\r
+    end;\r
+  end;\r
+end;\r
+\r
+procedure Copy( var Qix: TQix; Dest, Src: integer );\r
+var\r
+  I: integer;\r
+begin\r
+  for I:=0 to DEFVERT-1 do with Qix do begin\r
+    Vert[I,Dest].X := Vert[I,Src].X;\r
+    Vert[I,Dest].Y := Vert[I,Src].Y;\r
+  end;\r
+end;\r
+\r
+procedure AnimateQix;\r
+var\r
+  Q, Idx, I, J, P, Count: integer;\r
+begin\r
+  Count := 0;\r
+  P := DEFREPL-1;\r
+  I := 0;\r
+  J := 1;\r
+  repeat\r
+    mxSetClipRegion( 0, Page, MaxX+1, MaxY+1 );\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, MaxX+1, MaxY+1, 0, OP_SET );\r
+    for Q:=0 to DEFQIXS-1 do begin\r
+      Copy( Qix[Q], I, P );\r
+      Update( Qix[Q], I );\r
+      for Idx:=0 to DEFREPL-1 do begin\r
+        Plot( Qix[Q], Idx );\r
+      end;\r
+    end;\r
+    I := (I+1) mod DEFREPL;\r
+    J := (J+1) mod DEFREPL;\r
+    P := (P+1) mod DEFREPL;\r
+    Inc( Count );\r
+    mxStartLine( Page );\r
+    if( Count >= FADESPEED ) then begin\r
+      for Q:=0 to DEFQIXS-1 do begin\r
+        Inc( Qix[Q].Color );\r
+        if( Qix[Q].Color > 156 ) then\r
+          Qix[Q].Color := 1;\r
+      end;\r
+      Count := 0;\r
+    end;\r
+    Page := 240-Page;\r
+  until( KeyPressed );\r
+end;\r
+\r
+var\r
+  I: integer;\r
+begin\r
+  Randomize;\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  mxGetScreenSize( MaxX, MaxY );\r
+  for I:=0 to DEFQIXS-1 do\r
+    Init( Qix[I], (I*(155 div DEFQIXS)) mod 155 + 1 );\r
+  InitPalette;\r
+  mxSetPalette( @Pal, 0, 157 );\r
+  Page := 240;\r
+  Dec( MaxX );\r
+  Dec( MaxY );\r
+  AnimateQix;\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/x_/modex/README.TXT b/16/x_/modex/README.TXT
new file mode 100755 (executable)
index 0000000..306e8b9
--- /dev/null
@@ -0,0 +1,8 @@
+ModeX - A graphical library for DOS programs\r
+Copyright (c) 1993-1994 Alessandro Scotti\r
+http://www.ascotti.org/\r
+\r
+Please look at the above site in the "Art of..." and\r
+then in the "Old programs" section for more information.\r
+\r
+\r
diff --git a/16/x_/modex/SINCOS.INC b/16/x_/modex/SINCOS.INC
new file mode 100755 (executable)
index 0000000..6986eee
--- /dev/null
@@ -0,0 +1,518 @@
+;\r
+; SINCOS.INC - Sin/cos tables for THREED.ASM\r
+;\r
+\r
+tblSin  LABEL DWORD\r
+  DD    0\r
+  DD    411733\r
+  DD    823219\r
+  DD    1234209\r
+  DD    1644455\r
+  DD    2053710\r
+  DD    2461729\r
+  DD    2868265\r
+  DD    3273072\r
+  DD    3675909\r
+  DD    4076531\r
+  DD    4474698\r
+  DD    4870169\r
+  DD    5262706\r
+  DD    5652074\r
+  DD    6038037\r
+  DD    6420363\r
+  DD    6798821\r
+  DD    7173184\r
+  DD    7543226\r
+  DD    7908725\r
+  DD    8269459\r
+  DD    8625213\r
+  DD    8975771\r
+  DD    9320922\r
+  DD    9660458\r
+  DD    9994176\r
+  DD    10321873\r
+  DD    10643353\r
+  DD    10958422\r
+  DD    11266890\r
+  DD    11568571\r
+  DD    11863283\r
+  DD    12150850\r
+  DD    12431097\r
+  DD    12703856\r
+  DD    12968963\r
+  DD    13226258\r
+  DD    13475586\r
+  DD    13716797\r
+  DD    13949745\r
+  DD    14174291\r
+  DD    14390298\r
+  DD    14597637\r
+  DD    14796184\r
+  DD    14985817\r
+  DD    15166424\r
+  DD    15337895\r
+  DD    15500126\r
+  DD    15653022\r
+  DD    15796488\r
+  DD    15930439\r
+  DD    16054795\r
+  DD    16169479\r
+  DD    16274424\r
+  DD    16369565\r
+  DD    16454846\r
+  DD    16530216\r
+  DD    16595628\r
+  DD    16651044\r
+  DD    16696429\r
+  DD    16731757\r
+  DD    16757007\r
+  DD    16772163\r
+  DD    16777216\r
+  DD    16772163\r
+  DD    16757007\r
+  DD    16731757\r
+  DD    16696429\r
+  DD    16651044\r
+  DD    16595628\r
+  DD    16530216\r
+  DD    16454846\r
+  DD    16369565\r
+  DD    16274424\r
+  DD    16169479\r
+  DD    16054795\r
+  DD    15930439\r
+  DD    15796488\r
+  DD    15653022\r
+  DD    15500126\r
+  DD    15337895\r
+  DD    15166424\r
+  DD    14985817\r
+  DD    14796184\r
+  DD    14597637\r
+  DD    14390298\r
+  DD    14174291\r
+  DD    13949745\r
+  DD    13716797\r
+  DD    13475586\r
+  DD    13226258\r
+  DD    12968963\r
+  DD    12703856\r
+  DD    12431097\r
+  DD    12150850\r
+  DD    11863283\r
+  DD    11568571\r
+  DD    11266890\r
+  DD    10958422\r
+  DD    10643353\r
+  DD    10321873\r
+  DD    9994176\r
+  DD    9660458\r
+  DD    9320922\r
+  DD    8975771\r
+  DD    8625213\r
+  DD    8269459\r
+  DD    7908725\r
+  DD    7543226\r
+  DD    7173184\r
+  DD    6798821\r
+  DD    6420363\r
+  DD    6038037\r
+  DD    5652074\r
+  DD    5262706\r
+  DD    4870169\r
+  DD    4474698\r
+  DD    4076531\r
+  DD    3675909\r
+  DD    3273072\r
+  DD    2868265\r
+  DD    2461729\r
+  DD    2053710\r
+  DD    1644455\r
+  DD    1234209\r
+  DD    823219\r
+  DD    411733\r
+  DD    0\r
+  DD    -411733\r
+  DD    -823219\r
+  DD    -1234209\r
+  DD    -1644455\r
+  DD    -2053710\r
+  DD    -2461729\r
+  DD    -2868265\r
+  DD    -3273072\r
+  DD    -3675909\r
+  DD    -4076531\r
+  DD    -4474698\r
+  DD    -4870169\r
+  DD    -5262706\r
+  DD    -5652074\r
+  DD    -6038037\r
+  DD    -6420363\r
+  DD    -6798821\r
+  DD    -7173184\r
+  DD    -7543226\r
+  DD    -7908725\r
+  DD    -8269459\r
+  DD    -8625213\r
+  DD    -8975771\r
+  DD    -9320922\r
+  DD    -9660458\r
+  DD    -9994176\r
+  DD    -10321873\r
+  DD    -10643353\r
+  DD    -10958422\r
+  DD    -11266890\r
+  DD    -11568571\r
+  DD    -11863283\r
+  DD    -12150850\r
+  DD    -12431097\r
+  DD    -12703856\r
+  DD    -12968963\r
+  DD    -13226258\r
+  DD    -13475586\r
+  DD    -13716797\r
+  DD    -13949745\r
+  DD    -14174291\r
+  DD    -14390298\r
+  DD    -14597637\r
+  DD    -14796184\r
+  DD    -14985817\r
+  DD    -15166424\r
+  DD    -15337895\r
+  DD    -15500126\r
+  DD    -15653022\r
+  DD    -15796488\r
+  DD    -15930439\r
+  DD    -16054795\r
+  DD    -16169479\r
+  DD    -16274424\r
+  DD    -16369565\r
+  DD    -16454846\r
+  DD    -16530216\r
+  DD    -16595628\r
+  DD    -16651044\r
+  DD    -16696429\r
+  DD    -16731757\r
+  DD    -16757007\r
+  DD    -16772163\r
+  DD    -16777216\r
+  DD    -16772163\r
+  DD    -16757007\r
+  DD    -16731757\r
+  DD    -16696429\r
+  DD    -16651044\r
+  DD    -16595628\r
+  DD    -16530216\r
+  DD    -16454846\r
+  DD    -16369565\r
+  DD    -16274424\r
+  DD    -16169479\r
+  DD    -16054795\r
+  DD    -15930439\r
+  DD    -15796488\r
+  DD    -15653022\r
+  DD    -15500126\r
+  DD    -15337895\r
+  DD    -15166424\r
+  DD    -14985817\r
+  DD    -14796184\r
+  DD    -14597637\r
+  DD    -14390298\r
+  DD    -14174291\r
+  DD    -13949745\r
+  DD    -13716797\r
+  DD    -13475586\r
+  DD    -13226258\r
+  DD    -12968963\r
+  DD    -12703856\r
+  DD    -12431097\r
+  DD    -12150850\r
+  DD    -11863283\r
+  DD    -11568571\r
+  DD    -11266890\r
+  DD    -10958422\r
+  DD    -10643353\r
+  DD    -10321873\r
+  DD    -9994176\r
+  DD    -9660458\r
+  DD    -9320922\r
+  DD    -8975771\r
+  DD    -8625213\r
+  DD    -8269459\r
+  DD    -7908725\r
+  DD    -7543226\r
+  DD    -7173184\r
+  DD    -6798821\r
+  DD    -6420363\r
+  DD    -6038037\r
+  DD    -5652074\r
+  DD    -5262706\r
+  DD    -4870169\r
+  DD    -4474698\r
+  DD    -4076531\r
+  DD    -3675909\r
+  DD    -3273072\r
+  DD    -2868265\r
+  DD    -2461729\r
+  DD    -2053710\r
+  DD    -1644455\r
+  DD    -1234209\r
+  DD    -823219\r
+  DD    -411733\r
+tblCos  LABEL DWORD\r
+  DD    16777216\r
+  DD    16772163\r
+  DD    16757007\r
+  DD    16731757\r
+  DD    16696429\r
+  DD    16651044\r
+  DD    16595628\r
+  DD    16530216\r
+  DD    16454846\r
+  DD    16369565\r
+  DD    16274424\r
+  DD    16169479\r
+  DD    16054795\r
+  DD    15930439\r
+  DD    15796488\r
+  DD    15653022\r
+  DD    15500126\r
+  DD    15337895\r
+  DD    15166424\r
+  DD    14985817\r
+  DD    14796184\r
+  DD    14597637\r
+  DD    14390298\r
+  DD    14174291\r
+  DD    13949745\r
+  DD    13716797\r
+  DD    13475586\r
+  DD    13226258\r
+  DD    12968963\r
+  DD    12703856\r
+  DD    12431097\r
+  DD    12150850\r
+  DD    11863283\r
+  DD    11568571\r
+  DD    11266890\r
+  DD    10958422\r
+  DD    10643353\r
+  DD    10321873\r
+  DD    9994176\r
+  DD    9660458\r
+  DD    9320922\r
+  DD    8975771\r
+  DD    8625213\r
+  DD    8269459\r
+  DD    7908725\r
+  DD    7543226\r
+  DD    7173184\r
+  DD    6798821\r
+  DD    6420363\r
+  DD    6038037\r
+  DD    5652074\r
+  DD    5262706\r
+  DD    4870169\r
+  DD    4474698\r
+  DD    4076531\r
+  DD    3675909\r
+  DD    3273072\r
+  DD    2868265\r
+  DD    2461729\r
+  DD    2053710\r
+  DD    1644455\r
+  DD    1234209\r
+  DD    823219\r
+  DD    411733\r
+  DD    0\r
+  DD    -411733\r
+  DD    -823219\r
+  DD    -1234209\r
+  DD    -1644455\r
+  DD    -2053710\r
+  DD    -2461729\r
+  DD    -2868265\r
+  DD    -3273072\r
+  DD    -3675909\r
+  DD    -4076531\r
+  DD    -4474698\r
+  DD    -4870169\r
+  DD    -5262706\r
+  DD    -5652074\r
+  DD    -6038037\r
+  DD    -6420363\r
+  DD    -6798821\r
+  DD    -7173184\r
+  DD    -7543226\r
+  DD    -7908725\r
+  DD    -8269459\r
+  DD    -8625213\r
+  DD    -8975771\r
+  DD    -9320922\r
+  DD    -9660458\r
+  DD    -9994176\r
+  DD    -10321873\r
+  DD    -10643353\r
+  DD    -10958422\r
+  DD    -11266890\r
+  DD    -11568571\r
+  DD    -11863283\r
+  DD    -12150850\r
+  DD    -12431097\r
+  DD    -12703856\r
+  DD    -12968963\r
+  DD    -13226258\r
+  DD    -13475586\r
+  DD    -13716797\r
+  DD    -13949745\r
+  DD    -14174291\r
+  DD    -14390298\r
+  DD    -14597637\r
+  DD    -14796184\r
+  DD    -14985817\r
+  DD    -15166424\r
+  DD    -15337895\r
+  DD    -15500126\r
+  DD    -15653022\r
+  DD    -15796488\r
+  DD    -15930439\r
+  DD    -16054795\r
+  DD    -16169479\r
+  DD    -16274424\r
+  DD    -16369565\r
+  DD    -16454846\r
+  DD    -16530216\r
+  DD    -16595628\r
+  DD    -16651044\r
+  DD    -16696429\r
+  DD    -16731757\r
+  DD    -16757007\r
+  DD    -16772163\r
+  DD    -16777216\r
+  DD    -16772163\r
+  DD    -16757007\r
+  DD    -16731757\r
+  DD    -16696429\r
+  DD    -16651044\r
+  DD    -16595628\r
+  DD    -16530216\r
+  DD    -16454846\r
+  DD    -16369565\r
+  DD    -16274424\r
+  DD    -16169479\r
+  DD    -16054795\r
+  DD    -15930439\r
+  DD    -15796488\r
+  DD    -15653022\r
+  DD    -15500126\r
+  DD    -15337895\r
+  DD    -15166424\r
+  DD    -14985817\r
+  DD    -14796184\r
+  DD    -14597637\r
+  DD    -14390298\r
+  DD    -14174291\r
+  DD    -13949745\r
+  DD    -13716797\r
+  DD    -13475586\r
+  DD    -13226258\r
+  DD    -12968963\r
+  DD    -12703856\r
+  DD    -12431097\r
+  DD    -12150850\r
+  DD    -11863283\r
+  DD    -11568571\r
+  DD    -11266890\r
+  DD    -10958422\r
+  DD    -10643353\r
+  DD    -10321873\r
+  DD    -9994176\r
+  DD    -9660458\r
+  DD    -9320922\r
+  DD    -8975771\r
+  DD    -8625213\r
+  DD    -8269459\r
+  DD    -7908725\r
+  DD    -7543226\r
+  DD    -7173184\r
+  DD    -6798821\r
+  DD    -6420363\r
+  DD    -6038037\r
+  DD    -5652074\r
+  DD    -5262706\r
+  DD    -4870169\r
+  DD    -4474698\r
+  DD    -4076531\r
+  DD    -3675909\r
+  DD    -3273072\r
+  DD    -2868265\r
+  DD    -2461729\r
+  DD    -2053710\r
+  DD    -1644455\r
+  DD    -1234209\r
+  DD    -823219\r
+  DD    -411733\r
+  DD    0\r
+  DD    411733\r
+  DD    823219\r
+  DD    1234209\r
+  DD    1644455\r
+  DD    2053710\r
+  DD    2461729\r
+  DD    2868265\r
+  DD    3273072\r
+  DD    3675909\r
+  DD    4076531\r
+  DD    4474698\r
+  DD    4870169\r
+  DD    5262706\r
+  DD    5652074\r
+  DD    6038037\r
+  DD    6420363\r
+  DD    6798821\r
+  DD    7173184\r
+  DD    7543226\r
+  DD    7908725\r
+  DD    8269459\r
+  DD    8625213\r
+  DD    8975771\r
+  DD    9320922\r
+  DD    9660458\r
+  DD    9994176\r
+  DD    10321873\r
+  DD    10643353\r
+  DD    10958422\r
+  DD    11266890\r
+  DD    11568571\r
+  DD    11863283\r
+  DD    12150850\r
+  DD    12431097\r
+  DD    12703856\r
+  DD    12968963\r
+  DD    13226258\r
+  DD    13475586\r
+  DD    13716797\r
+  DD    13949745\r
+  DD    14174291\r
+  DD    14390298\r
+  DD    14597637\r
+  DD    14796184\r
+  DD    14985817\r
+  DD    15166424\r
+  DD    15337895\r
+  DD    15500126\r
+  DD    15653022\r
+  DD    15796488\r
+  DD    15930439\r
+  DD    16054795\r
+  DD    16169479\r
+  DD    16274424\r
+  DD    16369565\r
+  DD    16454846\r
+  DD    16530216\r
+  DD    16595628\r
+  DD    16651044\r
+  DD    16696429\r
+  DD    16731757\r
+  DD    16757007\r
+  DD    16772163\r
diff --git a/16/x_/modex/THREED.ASM b/16/x_/modex/THREED.ASM
new file mode 100755 (executable)
index 0000000..5ecd3ba
--- /dev/null
@@ -0,0 +1,872 @@
+COMMENT /\r
+        Fixed-point math functions and 3D transforms\r
+        Copyright (c) 1993,94 by Alessandro Scotti\r
+/\r
+WARN    PRO\r
+P386\r
+JUMPS\r
+LOCALS\r
+\r
+INCLUDE MATH.INC\r
+\r
+PUBLIC  tdFixedMul\r
+PUBLIC  tdGetNormal\r
+PUBLIC  tdRotate\r
+PUBLIC  tdGetSurfaceLight\r
+PUBLIC  tdSetLight\r
+PUBLIC  tdSetRotation\r
+PUBLIC  tdSetTranslation\r
+PUBLIC  tdTransform\r
+PUBLIC  tdTransformToImage\r
+PUBLIC  tdTransformLight\r
+PUBLIC  tdBackPlaneCull\r
+PUBLIC  tdSetPerspective\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Data segment\r
+;\r
+MATH_DATA       SEGMENT USE16 PARA PUBLIC 'DATA'\r
+                ASSUME ds:MATH_DATA\r
+\r
+INCLUDE         SINCOS.INC              ; Fixed 8:24 sin/cos table\r
+\r
+XRotation       TPOINT  <>              ; 3x3 rotation matrix\r
+YRotation       TPOINT  <>\r
+ZRotation       TPOINT  <>\r
+\r
+Translation     TPOINT  <>              ; Translation vector\r
+\r
+Light           TPOINT  <>              ; Light vector\r
+AmbientLight    DW      00              ; Ambient light\r
+\r
+XScale                  DD      10000h  ; Scaling factor for X coordinate\r
+YScale                  DD      10000h  ; Scaling factor for Y coordinate\r
+PerspectiveDistance     DD      20000000h\r
+\r
+MATH_DATA       ENDS\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Code segment\r
+;\r
+MATH_TEXT       SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MATH_TEXT, es:NOTHING, fs:NOTHING\r
+\r
+tdSetPerspective        PROC PASCAL FAR\r
+        ARG     Perspective:DWORD,      \\r
+                ScaleX:DWORD,           \\r
+                ScaleY:DWORD\r
+        USES    ds\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        mov     eax, [Perspective]\r
+        mov     [PerspectiveDistance], eax\r
+        mov     eax, [ScaleX]\r
+        mov     [XScale], eax\r
+        mov     eax, [ScaleY]\r
+        mov     [YScale], eax\r
+\r
+        ret\r
+tdSetPerspective        ENDP\r
+\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the rotation matrix.\r
+;\r
+; Input:\r
+;       RX      = X-axis rotation angle\r
+;       RY      = X-axis rotation angle\r
+;       RZ      = X-axis rotation angle\r
+; Output:\r
+;       none\r
+;\r
+tdSetRotation   PROC PASCAL FAR\r
+        ARG     RX:WORD,        \\r
+                RY:WORD,        \\r
+                RZ:WORD\r
+        USES    ds, si, di\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        mov     bx, [RZ]\r
+        mov     si, [RY]\r
+        mov     di, [RX]\r
+        shl     bx, 2\r
+        shl     si, 2\r
+        shl     di, 2\r
+\r
+        push    ebp                     ; We use EBP as a scratch register\r
+\r
+; Set X rotation\r
+        mov     eax, tblCos[bx]\r
+        imul    tblCos[si]\r
+        mov     [XRotation.X], edx\r
+\r
+        mov     eax, tblSin[bx]\r
+        imul    tblCos[si]\r
+        mov     [XRotation.Y], edx\r
+\r
+        mov     eax, tblSin[si]\r
+        sar     eax, 8                  ; Convert fixed 8:24 to fixed 16:16\r
+        mov     [XRotation.Z], eax\r
+\r
+; Set Y rotation\r
+        mov     eax, tblCos[bx]\r
+        imul    tblSin[si]              ; EDX:EAX = fixed 16:48\r
+        shrd    eax, edx, 24            ; EAX = fixed 8:24\r
+        imul    tblSin[di]              ; EDX:EAX = fixed 16:48\r
+        mov     ebp, eax\r
+        mov     ecx, edx\r
+        mov     eax, tblSin[bx]\r
+        imul    tblCos[di]\r
+        add     eax, ebp\r
+        adc     edx, ecx                ; EDX:EAX = fixed 16:48\r
+        neg     edx\r
+        mov     [YRotation.X], edx\r
+\r
+        mov     eax, tblSin[bx]\r
+        imul    tblSin[si]\r
+        shrd    eax, edx, 24\r
+        imul    tblSin[di]\r
+        mov     ebp, eax\r
+        mov     ecx, edx\r
+        mov     eax, tblCos[bx]\r
+        imul    tblCos[di]\r
+        sub     eax, ebp\r
+        sbb     edx, ecx\r
+        mov     [YRotation.Y], edx\r
+\r
+        mov     eax, tblCos[si]\r
+        imul    tblSin[di]\r
+        mov     [YRotation.Z], edx\r
+\r
+; Set Z rotation\r
+        mov     eax, tblCos[bx]\r
+        imul    tblSin[si]\r
+        shrd    eax, edx, 24\r
+        imul    tblCos[di]\r
+        mov     ebp, eax\r
+        mov     ecx, edx\r
+        mov     eax, tblSin[bx]\r
+        imul    tblSin[di]\r
+        sub     eax, ebp\r
+        sbb     edx, ecx\r
+        mov     [ZRotation.X], edx\r
+\r
+        mov     eax, tblSin[bx]\r
+        imul    tblSin[si]\r
+        shrd    eax, edx, 24\r
+        imul    tblCos[di]\r
+        mov     ebp, eax\r
+        mov     ecx, edx\r
+        mov     eax, tblCos[bx]\r
+        imul    tblSin[di]\r
+        add     eax, ebp\r
+        add     edx, ecx\r
+        neg     edx\r
+        mov     [ZRotation.Y], edx\r
+\r
+        mov     eax, tblCos[si]\r
+        imul    tblCos[di]\r
+        mov     [ZRotation.Z], edx\r
+\r
+        pop     ebp                     ; Restore EBP\r
+\r
+        ret\r
+tdSetRotation   ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the translation vector.\r
+;\r
+; Input:\r
+;       TV      = pointer to translation vector\r
+; Output:\r
+;       none\r
+;\r
+tdSetTranslation        PROC PASCAL FAR\r
+        ARG     TV:DWORD\r
+        USES    ds, es, di\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        les     di, [TV]\r
+        mov     eax, es:[di].X\r
+        mov     [Translation.X], eax\r
+        mov     eax, es:[di].Y\r
+        mov     [Translation.Y], eax\r
+        mov     eax, es:[di].Z\r
+        mov     [Translation.Z], eax\r
+\r
+        ret\r
+tdSetTranslation        ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Transforms an array of TPOINT.\r
+;\r
+; Input:\r
+;       Source  = pointer to source array of TPOINT\r
+;       Dest    = pointer to destination array of TPOINT\r
+;       Count   = number of entries to transform\r
+; Output:\r
+;       none\r
+;\r
+tdTransform     PROC PASCAL FAR\r
+        ARG     Source:DWORD,   \\r
+                Dest:DWORD,     \\r
+                Count:WORD\r
+        LOCAL   Adjust:DWORD\r
+        USES    ds, si, es, di, fs\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        lfs     si, [Source]\r
+        les     di, [Dest]\r
+\r
+        ALIGN   DWORD\r
+@@Loop:\r
+; Transform Z coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [ZRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [ZRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [ZRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        mov     ebx, eax\r
+        shrd    eax, edx, 16\r
+        add     eax, [Translation.Z]    ; EAX = new Z coord (fixed 16:16)\r
+        mov     es:[di].Z, eax\r
+; Get perspective factor\r
+        mov     ebx, [PerspectiveDistance]\r
+        sub     eax, ebx\r
+        neg     eax                     ; EAX = PD - Z\r
+        xor     edx, edx\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    ebx                     ; EAX = fixed 16:16 result\r
+        mov     [Adjust], eax\r
+\r
+; Transform X coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [XRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [XRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [XRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        add     eax, [Translation.X]\r
+        imul    [Adjust]\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].X, eax\r
+\r
+; Transform Y coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [YRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [YRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [YRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        add     eax, [Translation.Y]\r
+        imul    [Adjust]\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].Y, eax\r
+\r
+        add     si, SIZE TPOINT\r
+        add     di, SIZE TPOINT\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        ret\r
+tdTransform     ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Transforms an array of TPOINT into an array of TIMAGEPOINT.\r
+;\r
+; Input:\r
+;       Source  = pointer to source array of TPOINT\r
+;       Dest    = pointer to destination array of TIMAGEPOINT\r
+;       Count   = number of entries to transform\r
+;       DeltaX  = translation distance for the X coordinate\r
+;       DeltaY  = translation distance for the Y coordinate\r
+; Output:\r
+;       the maximum Z value\r
+;\r
+tdTransformToImage      PROC PASCAL FAR\r
+        ARG     Source:DWORD,   \\r
+                Dest:DWORD,     \\r
+                Count:WORD,     \\r
+                DeltaX:WORD,    \\r
+                DeltaY:WORD\r
+        LOCAL   Adjust:DWORD,   \\r
+                Max:DWORD\r
+        USES    ds, si, es, di, fs\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        lfs     si, [Source]\r
+        les     di, [Dest]\r
+        mov     [Max], 80000000h\r
+\r
+@@Loop:\r
+; Check max Z\r
+        mov     eax, fs:[si].Z\r
+        cmp     eax, [Max]\r
+        jle     @@1\r
+        mov     [Max], eax\r
+@@1:\r
+\r
+; Transform X coordinate\r
+        mov     ax, WORD PTR fs:[si].X[2]\r
+        add     ax, [DeltaX]\r
+        mov     es:[di].IX, ax\r
+\r
+; Transform Y coordinate\r
+        mov     ax, WORD PTR fs:[si].Y[2]\r
+        add     ax, [DeltaY]\r
+        mov     es:[di].IY, ax\r
+\r
+        add     si, SIZE TPOINT\r
+        add     di, SIZE TIMAGEPOINT\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        mov     eax, [Max]\r
+        shld    edx, eax, 16\r
+        ret\r
+tdTransformToImage      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the light source.\r
+;\r
+; Input:\r
+;       Light   = pointer to light vector\r
+; Output:\r
+;       none\r
+;\r
+tdSetLight      PROC PASCAL FAR\r
+        ARG     L:DWORD\r
+        USES    ds, es, di\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        les     di, [L]\r
+        mov     eax, es:[di].X\r
+        mov     [Light.X], eax\r
+        mov     eax, es:[di].Y\r
+        mov     [Light.Y], eax\r
+        mov     eax, es:[di].Z\r
+        mov     [Light.Z], eax\r
+\r
+        ret\r
+tdSetLight      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Computes light intensity for an array of surfaces.\r
+;\r
+; Input:\r
+;       Normals = pointer to an array of surface normals\r
+;       Lights  = pointer to an array of integer to be filled with\r
+;                 light intensity\r
+;       Count   = number of elements to transform\r
+; Output:\r
+;       none\r
+;\r
+tdTransformLight        PROC PASCAL FAR\r
+        ARG     Normals:DWORD,  \\r
+                Lights:DWORD,   \\r
+                Count:WORD\r
+        USES    ds, si, es, di, fs\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     fs, ax\r
+        ASSUME  fs:MATH_DATA\r
+\r
+        lds     si, [Normals]\r
+        les     di, [Lights]\r
+        ASSUME  ds:NOTHING\r
+\r
+; Intensity is given by the dot product between the Light vector and\r
+; the surface normal\r
+@@Loop:\r
+        mov     eax, ds:[si].Z\r
+        imul    [Light.Z]\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, ds:[si].Y\r
+        imul    [Light.Y]\r
+        add     ebx, eax\r
+        adc     ecx, edx\r
+        mov     eax, ds:[si].X\r
+        imul    [Light.X]\r
+        add     eax, ebx\r
+        adc     edx, ecx                ; EDX:EAX = fixed 32:32 intensity\r
+        add     dx, [AmbientLight]\r
+        test    dx, dx\r
+        jg      @@1\r
+        xor     dx, dx                  ; Return 0 for no light\r
+@@1:\r
+        mov     es:[di], dx\r
+        inc     di\r
+        inc     di\r
+        add     si, SIZE TPOINT\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        ASSUME  fs:NOTHING\r
+        ret\r
+tdTransformLight        ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the light value given the normal to a surface.\r
+;\r
+; Input:\r
+;       Normal  = pointer to TPOINT surface normal vector\r
+; Output:\r
+;       AX      = light intensity (>=0)\r
+; Notes:\r
+;       the normal is rotated according to the current setting.\r
+;\r
+tdGetSurfaceLight       PROC PASCAL FAR\r
+        ARG     Normal:DWORD\r
+        USES    ds, esi, es, di\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        les     di, [Normal]\r
+\r
+; Transform Z coordinate\r
+        mov     eax, es:[di].X\r
+        imul    [ZRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, es:[di].Y\r
+        imul    [ZRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, es:[di].Z\r
+        imul    [ZRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        imul    [Light.Z]\r
+        shrd    eax, edx, 16\r
+        mov     esi, eax\r
+\r
+; Transform X coordinate\r
+        mov     eax, es:[di].X\r
+        imul    [XRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, es:[di].Y\r
+        imul    [XRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, es:[di].Z\r
+        imul    [XRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        imul    [Light.X]\r
+        shrd    eax, edx, 16\r
+        add     esi, eax\r
+\r
+; Transform Y coordinate\r
+        mov     eax, es:[di].X\r
+        imul    [YRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, es:[di].Y\r
+        imul    [YRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, es:[di].Z\r
+        imul    [YRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        imul    [Light.X]\r
+        shrd    eax, edx, 16\r
+        add     eax, esi\r
+        shr     eax, 16\r
+\r
+; Add ambient light\r
+        add     ax, [AmbientLight]\r
+        test    ax, ax\r
+        jge     @@Exit\r
+        xor     ax, ax\r
+\r
+@@Exit:\r
+        ret\r
+tdGetSurfaceLight       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Rotates an array of TPOINT.\r
+;\r
+; Input:\r
+;       Source  = pointer to source array of TPOINT\r
+;       Dest    = pointer to destination array of TPOINT\r
+;       Count   = number of entries to transform\r
+; Output:\r
+;       none\r
+;\r
+tdRotate        PROC PASCAL FAR\r
+        ARG     Source:DWORD,   \\r
+                Dest:DWORD,     \\r
+                Count:WORD\r
+        USES    ds, si, es, di, fs\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        lfs     si, [Source]\r
+        les     di, [Dest]\r
+\r
+@@Loop:\r
+; Transform Z coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [ZRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [ZRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [ZRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].Z, eax\r
+\r
+; Transform X coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [XRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [XRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [XRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].X, eax\r
+\r
+; Transform Y coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [YRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [YRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [YRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].Y, eax\r
+\r
+        add     si, SIZE TPOINT\r
+        add     di, SIZE TPOINT\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        ret\r
+tdRotate        ENDP\r
+\r
+tdFixedMul      PROC PASCAL FAR\r
+        ARG     F1:DWORD,       \\r
+                F2:DWORD\r
+\r
+        mov     eax, [F1]\r
+        imul    [F2]\r
+        shr     eax, 16\r
+\r
+        ret\r
+tdFixedMul      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns in EAX the square root of EDX:EAX.\r
+;\r
+subSqrt PROC NEAR\r
+        push    esi\r
+        push    edi\r
+\r
+        add     eax, eax\r
+        adc     edx, 0\r
+        mov     eax, edx                ; Just discard the low bits\r
+\r
+        mov     esi, eax\r
+        xor     edi, edi\r
+        shld    edi, esi, 16\r
+        shl     esi, 16\r
+@@Loop:\r
+        mov     ebx, eax\r
+        mul     eax\r
+        add     eax, esi\r
+        adc     edx, edi\r
+        shrd    eax, edx, 1\r
+        shr     edx, 1\r
+        div     ebx\r
+        cmp     eax, ebx\r
+        jne     @@Loop\r
+\r
+; Adjust EAX\r
+        shl     eax, 8\r
+\r
+        pop     edi\r
+        pop     esi\r
+        ret\r
+subSqrt ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Finds the unitary normal to a given surface.\r
+;\r
+; Input:\r
+;       Dest            = pointer to TPOINT (vector) result\r
+;       P1, P2, P3      = pointer to TPOINT points on surface\r
+; Output:\r
+;       none\r
+; Notes:\r
+;       the normal is given by the cross-product between (P3-P1) and\r
+;       (P2-P1), so its orientation depends on the parameters order.\r
+;\r
+tdGetNormal     PROC PASCAL FAR\r
+        ARG     Dest:DWORD,     \\r
+                P1:DWORD,       \\r
+                P2:DWORD,       \\r
+                P3:DWORD\r
+        LOCAL   V1:TPOINT,      \\r
+                V2:TPOINT,      \\r
+                N:TPOINT\r
+        USES    ds, si, es, di\r
+\r
+; Get vector V1\r
+        lds     si, [P1]\r
+        les     di, [P3]\r
+        mov     eax, es:[di].X\r
+        sub     eax, ds:[si].X\r
+        mov     [V1.X], eax\r
+        mov     eax, es:[di].Y\r
+        sub     eax, ds:[si].Y\r
+        mov     [V1.Y], eax\r
+        mov     eax, es:[di].Z\r
+        sub     eax, ds:[si].Z\r
+        mov     [V1.Z], eax\r
+\r
+; Get vector V2\r
+        les     di, [P2]\r
+        mov     eax, es:[di].X\r
+        sub     eax, ds:[si].X\r
+        mov     [V2.X], eax\r
+        mov     eax, es:[di].Y\r
+        sub     eax, ds:[si].Y\r
+        mov     [V2.Y], eax\r
+        mov     eax, es:[di].Z\r
+        sub     eax, ds:[si].Z\r
+        mov     [V2.Z], eax\r
+\r
+; Get normal vector (V1 x V2)\r
+        mov     eax, [V1.Z]\r
+        imul    [V2.Y]\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, [V1.Y]\r
+        imul    [V2.Z]\r
+        sub     eax, ebx\r
+        sbb     edx, ecx\r
+        shrd    eax, edx, 16\r
+        mov     [N.X], eax\r
+\r
+        mov     eax, [V1.X]\r
+        imul    [V2.Z]\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, [V1.Z]\r
+        imul    [V2.X]\r
+        sub     eax, ebx\r
+        sbb     edx, ecx\r
+        shrd    eax, edx, 16\r
+        mov     [N.Y], eax\r
+\r
+        mov     eax, [V1.Y]\r
+        imul    [V2.X]\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, [V1.X]\r
+        imul    [V2.Y]\r
+        sub     eax, ebx\r
+        sbb     edx, ecx\r
+        shrd    eax, edx, 16\r
+        mov     [N.Z], eax\r
+\r
+; Get normal length\r
+        mov     eax, [N.X]\r
+        imul    eax\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, [N.Y]\r
+        imul    eax\r
+        add     ebx, eax\r
+        adc     ecx, edx\r
+        mov     eax, [N.Z]\r
+        imul    eax\r
+        add     eax, ebx\r
+        adc     edx, ecx                ; EDX:EAX = N.X*N.X + N.Y*N.Y + N.Z*N.Z\r
+        call    subSqrt                 ; EAX = normal length\r
+        mov     ebx, eax\r
+\r
+; Adjust vector and save it\r
+        les     di, [Dest]\r
+        mov     eax, [N.X]\r
+        cdq\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    ebx\r
+        mov     es:[di].X, eax\r
+        mov     eax, [N.Y]\r
+        cdq\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    ebx\r
+        mov     es:[di].Y, eax\r
+        mov     eax, [N.Z]\r
+        cdq\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    ebx\r
+        mov     es:[di].Z, eax\r
+\r
+        ret\r
+tdGetNormal     ENDP\r
+\r
+TPOLY   STRUC\r
+        Vtx     DW      4 DUP(?)\r
+TPOLY   ENDS\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Performs surface removal on an array of polygons.\r
+;\r
+; Input:\r
+;       Poly    = pointer to an array of TPOLY\r
+;       Vertex  = pointer to an array of TPOINT\r
+;       Dest    = pointer to an array of integer\r
+;       Count   = number of polygons to check\r
+;       Step    = size of TPOLY structure\r
+; Output:\r
+;       if the n-th polygon is invisible the n-th entry of the\r
+;       Dest array is set to -1, other entries are not modified\r
+;       (so it's possible to use the Light array for Dest, because\r
+;       the light intensity is always >= 0)\r
+;\r
+tdBackPlaneCull PROC PASCAL FAR\r
+        ARG     Step:WORD,      \\r
+                Poly:DWORD,     \\r
+                Vertex:DWORD,   \\r
+                Dest:DWORD,     \\r
+                Count:WORD\r
+        USES    ds, si, es, di, fs\r
+        ASSUME  ds:NOTHING\r
+\r
+        mov     ds, WORD PTR Vertex[2]\r
+        les     di, [Poly]\r
+        mov     fs, WORD PTR Dest[2]\r
+\r
+@@Loop:\r
+        mov     ax, es:[di].Vtx[2]      ; Index of 2nd vertex\r
+        shl     ax, 2\r
+        mov     bx, ax\r
+        shl     ax, 1\r
+        add     bx, ax                  ; BX = index*SIZE TPOINT\r
+        add     bx, WORD PTR [Vertex]   ; BX = offset of 2nd vertex\r
+        mov     ax, es:[di].Vtx[4]      ; Index of 3rd vertex\r
+        shl     ax, 2\r
+        mov     si, ax\r
+        shl     ax, 1\r
+        add     si, ax\r
+        add     si, WORD PTR [Vertex]   ; SI = offset of 3rd vertex\r
+        mov     ecx, ds:[si].X\r
+        sub     ecx, ds:[bx].X          ; ECX = V3.X-V2.X\r
+        mov     edx, ds:[si].Y\r
+        sub     edx, ds:[bx].Y          ; EDX = V3.Y-V2.Y\r
+        mov     ax, es:[di].Vtx[0]      ; Index of 1st vertex\r
+        shl     ax, 2\r
+        mov     si, ax\r
+        shl     ax, 1\r
+        add     si, ax\r
+        add     si, WORD PTR [Vertex]   ; SI = offset of 1st vertex\r
+        mov     eax, ds:[si].X\r
+        sub     eax, ds:[bx].X          ; EAX = V1.X-V2.X\r
+        mov     esi, ds:[si].Y\r
+        sub     esi, ds:[bx].Y          ; ESI = V1.Y-V2.Y\r
+        imul    edx\r
+        mov     ebx, eax\r
+        xchg    ecx, edx                ; ECX:EBX = (V1.X-V2.X)*(V3.Y-V2.Y)\r
+        mov     eax, esi\r
+        imul    edx                     ; EDX:EAX = (V1.Y-V2.Y)*(V3.X-V2.X)\r
+        sub     eax, ebx\r
+        sbb     edx, ecx\r
+        jl      @@Next                  ; Polygon is visible\r
+        mov     bx, WORD PTR [Dest]     ; FS:BX -> current Dest entry\r
+        mov     WORD PTR fs:[bx], -1    ; Remove polygon\r
+@@Next:\r
+        add     WORD PTR [Dest], 2      ; Next entry for dest\r
+        add     di, [Step]              ; Next polygon\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        ret\r
+tdBackPlaneCull ENDP\r
+\r
+MATH_TEXT       ENDS\r
+END\r
diff --git a/16/x_/modex/THREED.H b/16/x_/modex/THREED.H
new file mode 100755 (executable)
index 0000000..b993ef8
--- /dev/null
@@ -0,0 +1,32 @@
+typedef struct {\r
+    long    x, y, z;\r
+} TVECTOR;\r
+\r
+#define PVECTOR TVECTOR far *\r
+\r
+#define TPOINT  TVECTOR\r
+#define PPOINT  PVECTOR\r
+\r
+#define VPTR    void far *\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+long far pascal tdFixedMul( long, long );\r
+int  far pascal tdGetSurfaceLight( PPOINT );\r
+long far pascal tdTransformToImage( VPTR, VPTR, short, short, short );\r
+\r
+void far pascal tdBackPlaneCull( VPTR, VPTR, VPTR, short, short );\r
+void far pascal tdGetNormal( VPTR, PPOINT, PPOINT, PPOINT );\r
+void far pascal tdRotate( VPTR, VPTR, short );\r
+void far pascal tdSetLight( PVECTOR );\r
+void far pascal tdSetRotation( short, short, short );\r
+void far pascal tdSetTranslation( PVECTOR );\r
+void far pascal tdSetPerspective( long, long, long );\r
+void far pascal tdTransform( VPTR, VPTR, short );\r
+void far pascal tdTransformLight( VPTR, VPTR, short );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
diff --git a/16/x_/modex/THREED.PAS b/16/x_/modex/THREED.PAS
new file mode 100755 (executable)
index 0000000..8b712c9
--- /dev/null
@@ -0,0 +1,40 @@
+unit ThreeD;\r
+interface\r
+\r
+type\r
+  TVector       = record\r
+    X, Y, Z     : longint;\r
+  end;\r
+  TPoint        = TVector;\r
+\r
+function tdFixedMul( F1, F2: longint ): longint;\r
+function tdGetSurfaceLight( var Normal: TPoint ): integer;\r
+function tdTransformToImage( var Source, Dest; Count, DeltaX, DeltaY: integer ): longint;\r
+\r
+procedure tdBackPlaneCull( var Poly, Vertex, Dest; Count, Step: word );\r
+procedure tdGetNormal( var Dest, P1, P2, P3: TVector );\r
+procedure tdRotate( var Source, Dest; Count: word );\r
+procedure tdSetLight( var Light: TVector );\r
+procedure tdSetRotation( RX, RY, RZ: word );\r
+procedure tdSetTranslation( var TV: TVector );\r
+procedure tdSetPerspective( PD, XF, YF: longint );\r
+procedure tdTransform( var Source, Dest; Count: word );\r
+procedure tdTransformLight( var Source, Dest; Count: word );\r
+\r
+implementation\r
+\r
+function tdGetSurfaceLight;                             external;\r
+procedure tdSetRotation( RX, RY, RZ: word );            external;\r
+procedure tdGetNormal;                                  external;\r
+procedure tdSetTranslation( var TV: TVector );          external;\r
+procedure tdTransform( var Source, Dest; Count: word ); external;\r
+procedure tdRotate;                                     external;\r
+function  tdTransformToImage;                           external;\r
+procedure tdSetLight( var Light: TVector );             external;\r
+procedure tdSetPerspective;                             external;\r
+procedure tdTransformLight;                             external;\r
+function tdFixedMul( F1, F2: longint ): longint;        external;\r
+procedure tdBackPlaneCull;                              external;\r
+{$L THREED}\r
+\r
+end.\r
diff --git a/16/x_/mxbb.asm b/16/x_/mxbb.asm
new file mode 100755 (executable)
index 0000000..ac6668c
--- /dev/null
@@ -0,0 +1,278 @@
+;-----------------------------------------------------------\r
+;\r
+; MXBB.ASM - Bit block transfer\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxBitBlt\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   subHorizontalLineInfo   : NEAR\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Moves a block of video memory.\r
+;\r
+; Input:\r
+;       SX, SY  = source coordinates\r
+;       Width   = source width\r
+;       Height  = source height\r
+;       DX, DY  = destination coordinates\r
+; Output:\r
+;       none\r
+;\r
+; Note: overlapping regions are not allowed.\r
+;\r
+mxBitBlt        PROC    FAR\r
+        ARG     DestY:WORD,             \\r
+                DestX:WORD,             \\r
+                Height:WORD,            \\r
+                Width:WORD,             \\r
+                SY:WORD,                \\r
+                SX:WORD                 = ARG_SIZE\r
+        LOCAL   PlaneWidth:WORD:4,      \\r
+                SourceOffset:WORD,      \\r
+                DestOffset:WORD,        \\r
+                Count:BYTE,             \\r
+                ReadPlane:BYTE,         \\r
+                WritePlane:BYTE,        \\r
+                LeftMask:BYTE,          \\r
+                RightMask:BYTE          = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+\r
+; Exit now if null width\r
+        cmp     [Width], 0\r
+        je      @@Exit\r
+\r
+; Calls the proper procedure to handle transfer\r
+        mov     ax, [SX]\r
+        and     al, 03h                 ; AL = source plane\r
+        mov     dx, [DestX]\r
+        and     dl, 03h                 ; DL = destination plane\r
+        mov     bx, OFFSET subPlaneBlt\r
+        cmp     al, dl                  ; Same source and destination plane?\r
+        jne     @@BitBlt                ; No, use slow procedure\r
+        mov     bx, OFFSET subMoveBlt\r
+@@BitBlt:\r
+        call    bx\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+\r
+;-----------------------------------------------------------\r
+; Uses write mode 1 for maximum speed. Only works if source\r
+; and destination are plane-aligned.\r
+;\r
+subMoveBlt      PROC    NEAR\r
+; Get horizontal line info and address of destination\r
+        mov     bx, [DestX]\r
+        mov     ax, [DestY]\r
+        mov     cx, [Width]\r
+        call    subHorizontalLineInfo\r
+        mov     [LeftMask], al\r
+        mov     [RightMask], ah\r
+        mov     [Width], cx\r
+\r
+; Setup segments\r
+        mov     ax, [mx_VideoSegment]\r
+        mov     ds, ax\r
+        mov     es, ax\r
+\r
+; Get address of source pixel\r
+        mov     ax, [SY]\r
+        mul     [mx_BytesPerLine]\r
+        mov     si, [SX]\r
+        .shr    si, 2\r
+        add     si, ax\r
+\r
+; Set write mode 1\r
+        mov     dx, GDC\r
+        mov     ax, 4105h\r
+        out     dx, ax\r
+        cld\r
+\r
+; Move left block\r
+@@L0:\r
+        mov     ah, [LeftMask]\r
+        or      ah, ah\r
+        jz      @@C0\r
+        mov     dx, TS\r
+        mov     al, 02h\r
+        out     dx, ax                  ; Set write plane mask\r
+        mov     ax, [mx_BytesPerLine]\r
+        dec     ax\r
+        mov     cx, [Height]\r
+        .push   si, di\r
+@@L1:\r
+        movsb\r
+        add     si, ax\r
+        add     di, ax\r
+        dec     cx\r
+        jnz     @@L1\r
+        .pop    si, di\r
+        inc     si\r
+        inc     di\r
+\r
+; Move center block\r
+@@C0:\r
+        mov     bx, [Width]\r
+        test    bx, bx\r
+        jz      @@R0\r
+        mov     dx, TS\r
+        mov     ax, 0F02h\r
+        out     dx, ax                  ; Enable all planes\r
+        mov     ax, [mx_BytesPerLine]\r
+        sub     ax, bx\r
+        mov     dx, [Height]\r
+        .push   si, di\r
+@@C1:\r
+        mov     cx, bx                  ; CX = image width\r
+        rep     movsb                   ; Cannot use "movsw" here!\r
+        add     si, ax                  ; Next scan line\r
+        add     di, ax                  ; Next scan line\r
+        dec     dx                      ; All lines processed?\r
+        jnz     @@C1                    ; No, continue\r
+        .pop    si, di\r
+        add     si, bx\r
+        add     di, bx\r
+\r
+; Move right block\r
+@@R0:\r
+        mov     ah, [RightMask]\r
+        or      ah, ah\r
+        jz      @@Done\r
+        mov     dx, TS\r
+        mov     al, 02h\r
+        out     dx, ax                  ; Set write plane mask\r
+        mov     ax, [mx_BytesPerLine]\r
+        dec     ax\r
+        mov     cx, [Height]\r
+@@R1:\r
+        movsb\r
+        add     si, ax\r
+        add     di, ax\r
+        dec     cx\r
+        jnz     @@R1\r
+\r
+@@Done:\r
+        mov     dx, GDC\r
+        mov     ax, 4005h\r
+        out     dx, ax                  ; Restore write mode 0\r
+\r
+@@Exit:\r
+        ret\r
+subMoveBlt      ENDP\r
+\r
+;-----------------------------------------------------------\r
+; Moves one plane at a time.\r
+;\r
+subPlaneBlt     PROC    NEAR\r
+; Compute extra bytes and width count for each plane\r
+        mov     cx, [Width]\r
+        mov     bx, cx\r
+        shr     bx, 1\r
+        shr     bx, 1                   ; Width for each plane\r
+        and     cl, 03h\r
+        mov     al, 00001000b\r
+        shr     al, cl\r
+        mov     si, 3 SHL 1\r
+@@PatchLoop:\r
+        mov     PlaneWidth[si], bx\r
+        shr     al, 1\r
+        adc     bx, 0\r
+        dec     si\r
+        dec     si\r
+        jge     @@PatchLoop\r
+\r
+; Get pixel addresses\r
+        mov     ax, [mx_VideoSegment]\r
+        mov     ds, ax\r
+        mov     es, ax\r
+        mov     ax, [SY]\r
+        mul     [mx_BytesPerLine]\r
+        mov     si, [SX]\r
+        shr     si, 1\r
+        shr     si, 1\r
+        add     si, ax                  ; DS:SI points to source\r
+        mov     [SourceOffset], si\r
+        mov     ax, [DestY]\r
+        mul     [mx_BytesPerLine]\r
+        mov     di, [DestX]\r
+        shr     di, 1\r
+        shr     di, 1\r
+        add     di, ax                  ; ES:DI points to destination\r
+        mov     [DestOffset], di\r
+\r
+; Adjust plane for output to VGA registers\r
+        mov     ax, [SX]\r
+        and     al, 03h\r
+        mov     [ReadPlane], al\r
+        mov     cx, [DestX]\r
+        and     cl, 03h\r
+        mov     al, 00010001b\r
+        shl     al, cl\r
+        mov     [WritePlane], al\r
+\r
+; Ready to move now\r
+        cld\r
+        mov     [Count], 4              ; Four planes\r
+        lea     bx, PlaneWidth          ; SS:[BX] = width in bytes for plane\r
+@@PlaneLoop:\r
+        cmp     WORD PTR ss:[bx], 0\r
+        je      @@Done\r
+        mov     ah, [WritePlane]\r
+        and     ah, 0Fh\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax                  ; Select write plane\r
+        mov     ah, [ReadPlane]\r
+        mov     al, 04h\r
+        mov     dx, GDC\r
+        out     dx, ax                  ; Select read plane\r
+        mov     dx, [Height]\r
+        mov     ax, [mx_BytesPerLine]\r
+        sub     ax, ss:[bx]             ; AX = extra bytes per line\r
+@@Loop:\r
+        mov     cx, ss:[bx]\r
+        shr     cx, 1\r
+        rep     movsw\r
+        rcl     cx, 1\r
+        rep     movsb\r
+        add     si, ax\r
+        add     di, ax\r
+        dec     dx\r
+        jnz     @@Loop                  ; Repeat for all lines\r
+        inc     bx\r
+        inc     bx                      ; Select width for next plane\r
+        inc     [ReadPlane]\r
+        and     [ReadPlane], 03h        ; Should be faster on 386 using\r
+        jnz     @@ReadPlaneOk           ; BTR and ADC...\r
+        inc     [SourceOffset]\r
+@@ReadPlaneOk:\r
+        rol     [WritePlane], 1\r
+        adc     [DestOffset], 0\r
+        mov     si, [SourceOffset]\r
+        mov     di, [DestOffset]\r
+        dec     [Count]\r
+        jnz     @@PlaneLoop             ; Repeat for all planes\r
+\r
+@@Done:\r
+        ret\r
+subPlaneBlt     ENDP\r
+\r
+mxBitBlt        ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxcc.asm b/16/x_/mxcc.asm
new file mode 100755 (executable)
index 0000000..4f78adb
--- /dev/null
@@ -0,0 +1,644 @@
+;-----------------------------------------------------------\r
+;\r
+; MXCC.ASM - Fast clip line function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  xsubClipLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+        ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_VideoSegment : WORD\r
+\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+\r
+tblGroups       LABEL WORD\r
+        DW      10,     tbl00\r
+        DW      10,     tbl10\r
+        DW      9,      tbl20\r
+        DW      -1,     0\r
+        DW      10,     tbl40\r
+        DW      10,     tbl50\r
+        DW      9,      tbl60\r
+        DW      -1,     0\r
+        DW      6,      tbl80\r
+        DW      6,      tbl90\r
+        DW      5,      tblA0\r
+        DW      -1,     0\r
+        DW      -1,     0\r
+        DW      -1,     0\r
+        DW      -1,     0\r
+        DW      -1,     0\r
+tbl00   DW cc00, cc01, cc02, ccFF, cc04, cc05, cc06, ccFF, cc08, cc09, cc0A\r
+tbl10   DW cc10, ccFF, cc12, ccFF, cc14, ccFF, cc16, ccFF, cc18, ccFF, cc1A\r
+tbl20   DW cc20, cc21, ccFF, ccFF, cc24, cc25, ccFF, ccFF, cc28, cc29\r
+tbl40   DW cc40, cc41, cc42, ccFF, ccFF, ccFF, ccFF, ccFF, cc48, cc49, cc4A\r
+tbl50   DW cc50, ccFF, cc52, ccFF, ccFF, ccFF, ccFF, ccFF, cc58, ccFF, cc5A\r
+tbl60   DW cc60, cc61, ccFF, ccFF, ccFF, ccFF, ccFF, ccFF, cc68, cc69\r
+tbl80   DW cc80, cc81, cc82, ccFF, cc84, cc85, cc86\r
+tbl90   DW cc90, ccFF, cc92, ccFF, cc94, ccFF, cc96\r
+tblA0   DW ccA0, ccA1, ccFF, ccFF, ccA4, ccA5\r
+\r
+ccTT:   clc\r
+        ret\r
+ccFF:   stc\r
+        ret\r
+\r
+; Group 00 -------------------------------------------------\r
+;\r
+cc00:\r
+        clc\r
+        ret\r
+cc01:\r
+        jmp     ClipQLeft\r
+cc02:\r
+        jmp     ClipQRight\r
+cc04:\r
+        jmp     ClipQTop\r
+cc05:\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY1]\r
+        jge     ccTT\r
+        jmp     ClipQTop\r
+cc06:\r
+        call    ClipQRight\r
+        cmp     si, [mx_ClipY1]\r
+        jge     ccTT\r
+        jmp     ClipQTop\r
+cc08:\r
+        jmp     ClipQBottom\r
+cc09:\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY2]\r
+        jle     ccTT\r
+        jmp     ClipQBottom\r
+cc0A:\r
+        call    ClipQRight\r
+        cmp     si, [mx_ClipY2]\r
+        jle     ccTT\r
+        jmp     ClipQBottom\r
+\r
+; Group 10 -------------------------------------------------\r
+;\r
+cc10FF:\r
+        stc\r
+        ret\r
+cc10TT:\r
+        clc\r
+        ret\r
+cc10:\r
+        jmp     ClipPLeft\r
+cc12:\r
+        call    ClipPLeft\r
+        jmp     ClipQRight\r
+cc14:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      cc10FF\r
+        jmp     ClipQTop\r
+cc16:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      cc10FF\r
+        call    ClipQTop\r
+        cmp     cx, [mx_ClipX2]\r
+        jle     cc10TT\r
+        jmp     ClipQRight\r
+cc18:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      cc10FF\r
+        jmp     ClipQBottom\r
+cc1A:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      cc10FF\r
+        call    ClipQBottom\r
+        cmp     cx, [mx_ClipX2]\r
+        jle     cc10TT\r
+        jmp     ClipQRight\r
+\r
+; Group 20 -------------------------------------------------\r
+;\r
+cc20TT:\r
+        clc\r
+        ret\r
+cc20FF:\r
+        stc\r
+        ret\r
+cc20:\r
+        jmp     ClipPRight\r
+cc21:\r
+        call    ClipPRight\r
+        jmp     ClipQLeft\r
+cc24:\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      cc20FF\r
+        jmp     ClipQTop\r
+cc25:\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      cc20FF\r
+        call    ClipQTop\r
+        cmp     cx, [mx_ClipX1]\r
+        jge     cc20TT\r
+        jmp     ClipQLeft\r
+cc28:\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      cc20FF\r
+        jmp     ClipQBottom\r
+cc29:\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      cc20FF\r
+        call    ClipQBottom\r
+        cmp     cx, [mx_ClipX1]\r
+        jge     cc20TT\r
+        jmp     ClipQLeft\r
+\r
+; Group 40 -------------------------------------------------\r
+;\r
+cc40TT:\r
+        clc\r
+        ret\r
+cc40FF:\r
+        stc\r
+        ret\r
+cc40:\r
+        jmp     ClipPTop\r
+cc41:\r
+        call    ClipPTop\r
+        cmp     di, [mx_ClipX1]\r
+        jl      cc40FF\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY1]\r
+        jge     cc40TT\r
+        jmp     ClipQTop\r
+cc42:\r
+        call    ClipPTop\r
+        cmp     di, [mx_ClipX2]\r
+        jg      cc40FF\r
+        jmp     ClipQRight\r
+cc48:\r
+        call    ClipPTop\r
+        jmp     ClipQBottom\r
+cc49:\r
+        call    ClipPTop\r
+        cmp     di, [mx_ClipX1]\r
+        jl      cc40FF\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY2]\r
+        jle     cc40TT\r
+        jmp     ClipQBottom\r
+cc4A:\r
+        call    ClipPTop\r
+        cmp     di, [mx_ClipX2]\r
+        jg      cc40FF\r
+        call    ClipQRight\r
+        cmp     si, [mx_ClipY2]\r
+        jle     cc40TT\r
+        jmp     ClipQBottom\r
+\r
+\r
+; Group 50 -------------------------------------------------\r
+;\r
+cc50TT:\r
+        clc\r
+        ret\r
+cc50FF:\r
+        stc\r
+        ret\r
+cc50:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY1]\r
+        jge     cc50TT\r
+        jmp     ClipPTop\r
+cc52:\r
+        call    ClipQRight\r
+        cmp     si, [mx_ClipY1]\r
+        jl      cc50FF\r
+        call    ClipPTop\r
+        cmp     di, [mx_ClipX1]\r
+        jge     cc50TT\r
+        jmp     ClipPLeft\r
+cc58:\r
+        call    ClipQBottom\r
+        cmp     cx, [mx_ClipX1]\r
+        jl      cc50FF\r
+        call    ClipPTop\r
+        cmp     di, [mx_ClipX1]\r
+        jge     cc50TT\r
+        jmp     ClipPLeft\r
+cc5A:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      cc50FF\r
+        call    ClipQRight\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      cc50FF\r
+        cmp     si, [mx_ClipY2]\r
+        jle     cc50TT\r
+        jmp     ClipQBottom\r
+\r
+; Group 60 -------------------------------------------------\r
+;\r
+cc60TT:\r
+        clc\r
+        ret\r
+cc60FF:\r
+        stc\r
+        ret\r
+cc60:\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY1]\r
+        jge     cc60TT\r
+        jmp     ClipPTop\r
+cc61:\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY2]\r
+        jl      cc60FF\r
+        call    ClipPTop\r
+        cmp     di, [mx_ClipX2]\r
+        jle     cc60TT\r
+        jmp     ClipPRight\r
+cc68:\r
+        call    ClipQBottom\r
+        cmp     cx, [mx_ClipX2]\r
+        jg      cc60FF\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY1]\r
+        jge     cc60TT\r
+        jmp     ClipPTop\r
+cc69:\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY1]\r
+        jl      cc60FF\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      cc60FF\r
+        cmp     si, [mx_ClipY2]\r
+        jle     cc69_1\r
+        call    ClipQBottom\r
+cc69_1:\r
+        cmp     bx, [mx_ClipY1]\r
+        jge     cc60TT\r
+        jmp     ClipPTop\r
+\r
+; Group 80 -------------------------------------------------\r
+;\r
+cc80TT:\r
+        clc\r
+        ret\r
+cc80FF:\r
+        stc\r
+        ret\r
+cc80:\r
+        jmp     ClipPBottom\r
+cc81:\r
+        call    ClipPBottom\r
+        cmp     di, [mx_ClipX1]\r
+        jl      cc80FF\r
+        jmp     ClipQLeft\r
+cc82:\r
+        call    ClipPBottom\r
+        cmp     di, [mx_ClipX2]\r
+        jg      cc80FF\r
+        jmp     ClipQRight\r
+cc84:\r
+        call    ClipPBottom\r
+        jmp     ClipQTop\r
+cc85:\r
+        call    ClipPBottom\r
+        cmp     di, [mx_ClipX1]\r
+        jl      cc80FF\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY1]\r
+        jge     cc80FF\r
+        jmp     ClipQTop\r
+cc86:\r
+        call    ClipPBottom\r
+        cmp     di, [mx_ClipX2]\r
+        jg      cc80FF\r
+        call    ClipQRight\r
+        cmp     si, [mx_ClipY1]\r
+        jge     cc80TT\r
+        jmp     ClipQTop\r
+\r
+; Group 90 -------------------------------------------------\r
+;\r
+cc90TT:\r
+        clc\r
+        ret\r
+cc90FF:\r
+        stc\r
+        ret\r
+cc90:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY2]\r
+        jle     cc90TT\r
+        jmp     ClipPBottom\r
+cc92:\r
+        call    ClipQRight\r
+        cmp     si, [mx_ClipY2]\r
+        jg      cc90FF\r
+        call    ClipPBottom\r
+        cmp     di, [mx_ClipX1]\r
+        jge     cc90TT\r
+        jmp     ClipPLeft\r
+cc94:\r
+        call    ClipQTop\r
+        cmp     cx, [mx_ClipX1]\r
+        jl      cc90FF\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY2]\r
+        jle     cc90TT\r
+        jmp     ClipPBottom\r
+cc96:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      cc90FF\r
+        call    ClipQRight\r
+        cmp     si, [mx_ClipY2]\r
+        jg      cc90FF\r
+        cmp     bx, [mx_ClipY2]\r
+        jle     cc96_1\r
+        call    ClipPBottom\r
+cc96_1:\r
+        cmp     si, [mx_ClipY1]\r
+        jge     cc90TT\r
+        jmp     ClipQTop\r
+\r
+; Group A0 -------------------------------------------------\r
+;\r
+ccA0TT:\r
+        clc\r
+        ret\r
+ccA0FF:\r
+        stc\r
+        ret\r
+ccA0:\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY2]\r
+        jle     ccA0TT\r
+        jmp     ClipPBottom\r
+ccA1:\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY2]\r
+        jg      ccA0FF\r
+        call    ClipPBottom\r
+        cmp     di, [mx_ClipX2]\r
+        jle     ccA0TT\r
+        jmp     ClipPRight\r
+ccA4:\r
+        call    ClipQTop\r
+        cmp     cx, [mx_ClipX2]\r
+        jg      ccA0FF\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY2]\r
+        jle     ccA0TT\r
+        jmp     ClipPBottom\r
+ccA5:\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY2]\r
+        jg      ccA0FF\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      ccA0FF\r
+        cmp     si, [mx_ClipY1]\r
+        jge     ccA5_1\r
+        call    ClipQTop\r
+ccA5_1:\r
+        cmp     bx, [mx_ClipY2]\r
+        jle     ccA0TT\r
+        jmp     ClipPBottom\r
+\r
+; Y1 = (Y2-Y1)*(mx_ClipX1-X1)/(X2-X1)+Y1 = (SI-BX)*(mx_ClipX1-DI)/(CX-DI)+BX\r
+; X1 = mx_ClipX1\r
+ClipPLeft:\r
+        mov     ax, si\r
+        sub     ax, bx\r
+        mov     dx, [mx_ClipX1]\r
+        sub     dx, di\r
+        imul    dx\r
+        mov     bp, cx\r
+        sub     bp, di\r
+        idiv    bp\r
+        add     bx, ax\r
+        mov     di, [mx_ClipX1]\r
+        clc\r
+        ret\r
+\r
+; Y1 = (Y2-Y1)*(mx_ClipX2-X1)/(X2-X1)+Y1 = (SI-BX)*(mx_ClipX2-DI)/(CX-DI)+BX\r
+; X1 = mx_ClipX2\r
+ClipPRight:\r
+        mov     ax, si\r
+        sub     ax, bx\r
+        mov     dx, [mx_ClipX2]\r
+        sub     dx, di\r
+        imul    dx\r
+        mov     bp, cx\r
+        sub     bp, di\r
+        idiv    bp\r
+        add     bx, ax\r
+        mov     di, [mx_ClipX2]\r
+        clc\r
+        ret\r
+\r
+; X1 = (X2-X1)*(mx_ClipY2-Y1)/(Y2-Y1)+X1 = (CX-DI)*(mx_ClipY2-BX)/(SI-BX)+DI\r
+; Y1 = mx_ClipY2\r
+ClipPBottom:\r
+        mov     ax, cx\r
+        sub     ax, di\r
+        mov     dx, [mx_ClipY2]\r
+        sub     dx, bx\r
+        imul    dx\r
+        mov     bp, si\r
+        sub     bp, bx\r
+        idiv    bp\r
+        add     di, ax\r
+        mov     bx, [mx_ClipY2]\r
+        clc\r
+        ret\r
+\r
+; X1 = (X2-X1)*(mx_ClipY1-Y1)/(Y2-Y1)+X1 = (CX-DI)*(mx_ClipY1-BX)/(SI-BX)+DI\r
+; Y1 = mx_ClipY1\r
+ClipPTop:\r
+        mov     ax, cx\r
+        sub     ax, di\r
+        mov     dx, [mx_ClipY1]\r
+        sub     dx, bx\r
+        imul    dx\r
+        mov     bp, si\r
+        sub     bp, bx\r
+        idiv    bp\r
+        add     di, ax\r
+        mov     bx, [mx_ClipY1]\r
+        clc\r
+        ret\r
+\r
+; Y2 = (Y1-Y2)*(mx_ClipX1-X2)/(X1-X2)+Y2 = (BX-SI)*(mx_ClipX1-CX)/(DI-CX)+SI\r
+; X2 = mx_ClipX1\r
+ClipQLeft:\r
+        mov     ax, bx\r
+        sub     ax, si\r
+        mov     dx, [mx_ClipX1]\r
+        sub     dx, cx\r
+        imul    dx\r
+        mov     bp, di\r
+        sub     bp, cx\r
+        idiv    bp\r
+        add     si, ax\r
+        mov     cx, [mx_ClipX1]\r
+        clc\r
+        ret\r
+\r
+; Y2 = (Y1-Y2)*(mx_ClipX2-X2)/(X1-X2)+Y2 = (BX-SI)*(mx_ClipX2-CX)/(DI-CX)+SI\r
+; X2 = mx_ClipX1\r
+ClipQRight:\r
+        mov     ax, bx\r
+        sub     ax, si\r
+        mov     dx, [mx_ClipX2]\r
+        sub     dx, cx\r
+        imul    dx\r
+        mov     bp, di\r
+        sub     bp, cx\r
+        idiv    bp\r
+        add     si, ax\r
+        mov     cx, [mx_ClipX2]\r
+        clc\r
+        ret\r
+\r
+; X2 = (X1-X2)*(mx_ClipY2-Y2)/(Y1-Y2)+X2 = (DI-CX)*(mx_ClipY2-SI)/(BX-SI)+CX\r
+; Y2 = mx_ClipY1\r
+ClipQBottom:\r
+        mov     ax, di\r
+        sub     ax, cx\r
+        mov     dx, [mx_ClipY2]\r
+        sub     dx, si\r
+        imul    dx\r
+        mov     bp, bx\r
+        sub     bp, si\r
+        idiv    bp\r
+        add     cx, ax\r
+        mov     si, [mx_ClipY2]\r
+        clc\r
+        ret\r
+\r
+; X2 = (X1-X2)*(mx_ClipY1-Y2)/(Y1-Y2)+X2 = (DI-CX)*(mx_ClipY1-SI)/(BX-SI)+CX\r
+; Y2 = mx_ClipY1\r
+ClipQTop:\r
+        mov     ax, di\r
+        sub     ax, cx\r
+        mov     dx, [mx_ClipY1]\r
+        sub     dx, si\r
+        imul    dx\r
+        mov     bp, bx\r
+        sub     bp, si\r
+        idiv    bp\r
+        add     cx, ax\r
+        mov     si, [mx_ClipY1]\r
+        clc\r
+        ret\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Checks the coordinates of a line against the active\r
+; clip region.\r
+; Uses the Sobkow-Pospisil-Yang (SPY) algorithm: this was\r
+; supposed to be twice as fast as Cohen-Sutherland, but my\r
+; tests show only a very small increase in speed and a noticeable\r
+; increase of the program size! Maybe this is caused by the\r
+; slow speed of VGA cards, so probably a better test should\r
+; be performed with lines drawn in RAM.\r
+;\r
+; Input:\r
+;       AX, BX  = X1, Y1\r
+;       CX, DX  = X2, Y2\r
+; Output:\r
+;       CF      = set if line is full clipped\r
+;       AX, BX  = clipped X1, Y1\r
+;       CX, DX  = clipped X2, Y2\r
+; Note:\r
+;       destroys SI, DI\r
+;\r
+xsubClipLine     PROC    NEAR\r
+        push    bp\r
+        xor     si, si                  ; SPY code\r
+\r
+        cmp     dx, [mx_ClipY2]\r
+        jle     @@1\r
+        or      si, 08h\r
+        jmp     @@2\r
+@@1:\r
+        cmp     dx, [mx_ClipY1]\r
+        jge     @@2\r
+        or      si, 04h\r
+@@2:\r
+\r
+        cmp     cx, [mx_ClipX2]\r
+        jle     @@3\r
+        or      si, 02h\r
+        jmp     @@4\r
+@@3:\r
+        cmp     cx, [mx_ClipX1]\r
+        jge     @@4\r
+        or      si, 01h\r
+@@4:\r
+\r
+        cmp     bx, [mx_ClipY2]\r
+        jle     @@5\r
+        or      si, 80h\r
+        jmp     @@6\r
+@@5:\r
+        cmp     bx, [mx_ClipY1]\r
+        jge     @@6\r
+        or      si, 40h\r
+@@6:\r
+\r
+        cmp     ax, [mx_ClipX2]\r
+        jle     @@7\r
+        or      si, 20h\r
+        jmp     @@8\r
+@@7:\r
+        cmp     ax, [mx_ClipX1]\r
+        jge     @@8\r
+        or      si, 10h\r
+@@8:\r
+\r
+        mov     di, si\r
+        and     di, 000Fh               ; Index of procedure\r
+        and     si, 00F0h\r
+        .shr    si, 2                   ; Index of group (times 4)\r
+        cmp     di, cs:tblGroups[si]    ; Is index within range?\r
+        jg      @@Exit                  ; No, line is full clipped\r
+        mov     si, cs:tblGroups[si+2]  ; Get offset of group table\r
+        shl     di, 1                   ; We must index word elements\r
+        add     si, di                  ; Make full offset\r
+        mov     di, ax                  ; Move X1 to DI and free AX\r
+        mov     si, cs:[si]             ; Get subroutine address\r
+        xchg    dx, si                  ; Move Y2 to SI and free DX\r
+        call    dx                      ; Call the proper subroutine\r
+        mov     ax, di                  ; Restore AX to X1\r
+        mov     dx, si                  ; Restore DX to Y2\r
+        pop     bp\r
+        ret\r
+\r
+@@Exit:\r
+        pop     bp\r
+        stc\r
+        ret\r
+xsubClipLine     ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxcg.asm b/16/x_/mxcg.asm
new file mode 100755 (executable)
index 0000000..42163d7
--- /dev/null
@@ -0,0 +1,69 @@
+;-----------------------------------------------------------\r
+;\r
+; MXCG.ASM - Color to gray conversion\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxColorToGray\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Converts RGB colors to gray shades.\r
+;\r
+; Input:\r
+;       CPal    = pointer to color palette\r
+;       GPal    = pointer to destination (gray) palette\r
+;       Count   = number of colors to convert\r
+; Output:\r
+;       none\r
+;\r
+; Note: CPal and GPal may point to the same buffer.\r
+;\r
+mxColorToGray   PROC    FAR\r
+        ARG     Count:WORD,     \\r
+                DPal:DWORD,     \\r
+                SPal:DWORD      = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si, es, di\r
+\r
+        mov     cx, [Count]\r
+        jcxz    @@Exit\r
+        lds     si, [SPal]\r
+        les     di, [DPal]\r
+        cld\r
+; We use the standard formula\r
+;       gray=(red*30 + green*59 + blue*11)/100\r
+; in the equivalent form\r
+;       gray=(red*77 + green*151 + blue*28)/256\r
+; which doesn't need the last divide.\r
+        mov     bx, 77 SHL 8 + 151\r
+@@Loop:\r
+        lodsb                           ; Red\r
+        mul     bh\r
+        mov     dx, ax\r
+        lodsb                           ; Green\r
+        mul     bl\r
+        add     dx, ax\r
+        lodsb                           ; Blue\r
+        mov     ah, 28\r
+        mul     ah\r
+        add     ax, dx\r
+        mov     al, ah\r
+        stosw                           ; Save new RGB\r
+        stosb\r
+        loop    @@Loop\r
+\r
+@@Exit:\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxColorToGray   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxcl.asm b/16/x_/mxcl.asm
new file mode 100755 (executable)
index 0000000..aaa0bac
--- /dev/null
@@ -0,0 +1,151 @@
+;-----------------------------------------------------------\r
+;\r
+; MXCL.ASM - Bresenham circle\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxCircle\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Draws a circle using the Bresenham algorithm.\r
+;\r
+; Input:\r
+;       XC, YC  = center coordinates\r
+;       Radius  = circle radius\r
+;       Color   = circle color\r
+; Output:\r
+;       none\r
+; Note:\r
+;       computes only points in the first octant, all other\r
+;       points are obtained by symmetry.\r
+;\r
+mxCircle        PROC FAR\r
+        ARG     Color:BYTE:2,           \\r
+                Radius:WORD,            \\r
+                YC:WORD,                \\r
+                XC:WORD                 = ARG_SIZE\r
+        LOCAL   Delta:WORD              = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, di\r
+\r
+        xor     si, si                  ; X\r
+        mov     di, [Radius]            ; Y\r
+        mov     ax, 3\r
+        sub     ax, di\r
+        sub     ax, di\r
+        mov     [Delta], ax             ; Delta = 3-R*2\r
+\r
+        mov     ds, [mx_VideoSegment]\r
+\r
+@@Loop:\r
+        cmp     si, di                  ;\r
+        jg      @@Done                  ; Exit when X > Y\r
+; Draw points\r
+        mov     ax, si\r
+        mov     bx, di\r
+        call    @@subPutPixel\r
+        mov     ax, si\r
+        neg     ax\r
+        mov     bx, di\r
+        call    @@subPutPixel\r
+        mov     ax, si\r
+        mov     bx, di\r
+        neg     bx\r
+        call    @@subPutPixel\r
+        mov     ax, si\r
+        neg     ax\r
+        mov     bx, di\r
+        neg     bx\r
+        call    @@subPutPixel\r
+        mov     ax, di\r
+        mov     bx, si\r
+        call    @@subPutPixel\r
+        mov     ax, di\r
+        neg     ax\r
+        mov     bx, si\r
+        call    @@subPutPixel\r
+        mov     ax, di\r
+        mov     bx, si\r
+        neg     bx\r
+        call    @@subPutPixel\r
+        mov     ax, di\r
+        neg     ax\r
+        mov     bx, si\r
+        neg     bx\r
+        call    @@subPutPixel\r
+; Moves coordinates to next point\r
+        mov     ax, [Delta]\r
+        test    ax, ax\r
+        jl      @@Next\r
+        mov     ax, di\r
+        .shl    ax, 2\r
+        sub     ax, 4\r
+        sub     [Delta], ax\r
+        dec     di\r
+@@Next:\r
+        mov     ax, si\r
+        .shl    ax, 2\r
+        add     ax, 6\r
+        add     [Delta], ax\r
+        inc     si\r
+        jmp     @@Loop\r
+\r
+@@Done:\r
+        xor     ax, ax\r
+        .pop    ds, si, di\r
+        .leave  ARG_SIZE\r
+\r
+;---------------------------------------\r
+; Put pixel function.\r
+; Input:\r
+;       BX      = X coordinate (relative to center)\r
+;       AX      = Y coordinate (relative to center)\r
+;       DS      = video segment\r
+@@subPutPixel:\r
+        add     bx, [XC]                ; Get absolute coordinates\r
+        add     ax, [YC]\r
+\r
+        cmp     bx, [mx_ClipX1]         ; Clip pixel\r
+        jl      @@subExit\r
+        cmp     bx, [mx_ClipX2]\r
+        jg      @@subExit\r
+        cmp     ax, [mx_ClipY1]\r
+        jl      @@subExit\r
+        cmp     ax, [mx_ClipY2]\r
+        jg      @@subExit\r
+\r
+        mul     [mx_BytesPerLine]       ; Get pixel offset\r
+        mov     cx, bx                  ; Save X coordinate\r
+        .shr    bx, 2\r
+        add     bx, ax                  ; DS:BX = pixel offset\r
+\r
+        and     cl, 3                   ; Set write plane\r
+        mov     ax, 0102h\r
+        shl     ah, cl\r
+        mov     dx, TS\r
+        out     dx, ax\r
+\r
+        mov     al, [Color]             ; Write pixel\r
+        mov     ds:[bx], al\r
+\r
+@@subExit:\r
+        retn\r
+mxCircle        ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxcr.asm b/16/x_/mxcr.asm
new file mode 100755 (executable)
index 0000000..ca1fa7b
--- /dev/null
@@ -0,0 +1,380 @@
+;-----------------------------------------------------------\r
+;\r
+; MXCR.ASM - Clip functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxSetSysClipRegion\r
+PUBLIC  mxGetClipRegion\r
+PUBLIC  mxSetClipRegion\r
+PUBLIC  mxSetClip\r
+PUBLIC  mxGetClip\r
+\r
+PUBLIC  subClipBox\r
+PUBLIC  subClipImage\r
+\r
+PUBLIC  mx_ClipX1\r
+PUBLIC  mx_ClipY1\r
+PUBLIC  mx_ClipX2\r
+PUBLIC  mx_ClipY2\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_CodeSegment  : WORD\r
+\r
+mx_ClipX1       DW      ?               ; Clip coordinates\r
+mx_ClipY1       DW      ?\r
+mx_ClipX2       DW      ?\r
+mx_ClipY2       DW      ?\r
+\r
+mx_SysClipX1    DW      ?               ; System clip coordinates\r
+mx_SysClipY1    DW      ?               ; (active when mx_ClipStatus is FALSE)\r
+mx_SysClipX2    DW      ?\r
+mx_SysClipY2    DW      ?\r
+\r
+mx_UserClipX1   DW      ?               ; User clip coordinates\r
+mx_UserClipY1   DW      ?               ; (active when mx_ClipStatus is TRUE)\r
+mx_UserClipX2   DW      ?\r
+mx_UserClipY2   DW      ?\r
+\r
+mx_ClipStatus   DB      ?\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Toggles clipping between user and system regions.\r
+;\r
+; Input:\r
+;       ClipStatus      = TRUE (FALSE) to enable (disable) clipping\r
+; Output:\r
+;       AX      = old clip status\r
+;\r
+mxSetClip       PROC    FAR\r
+        ARG     ClipStatus:BYTE:2       = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, [mx_UserClipX1]\r
+        mov     bx, [mx_UserClipY1]\r
+        mov     cx, [mx_UserClipX2]\r
+        mov     dx, [mx_UserClipY2]\r
+        cmp     [ClipStatus], TRUE\r
+        je      @@Done\r
+        mov     ax, [mx_SysClipX1]\r
+        mov     bx, [mx_SysClipY1]\r
+        mov     cx, [mx_SysClipX2]\r
+        mov     dx, [mx_SysClipY2]\r
+@@Done:\r
+        mov     [mx_ClipX1], ax\r
+        mov     [mx_ClipY1], bx\r
+        mov     [mx_ClipX2], cx\r
+        mov     [mx_ClipY2], dx\r
+\r
+        mov     al, [ClipStatus]\r
+        xchg    al, [mx_ClipStatus]\r
+        xor     ah, ah\r
+\r
+        .pop    ds\r
+        .leave  ARG_SIZE\r
+mxSetClip       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current clipping status.\r
+;\r
+; Input:\r
+;       none\r
+; Output:\r
+;       TRUE (FALSE) if clipping enabled (disabled)\r
+;\r
+mxGetClip       PROC    FAR\r
+        ASSUME  ds:NOTHING\r
+        mov     al, [mx_ClipStatus]\r
+        xor     ah, ah\r
+        ret\r
+mxGetClip       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the system clip region and disables user clipping.\r
+;\r
+; Input:\r
+;       Width   = width in pixels of clip region\r
+;       Height  = height in pixels of clip region\r
+; Output:\r
+;       old clip status.\r
+;\r
+mxSetSysClipRegion      PROC    FAR\r
+        ARG     Height:WORD,            \\r
+                Width:WORD              = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        xor     ax, ax                  ; Sys clip region always starts at (0,0)\r
+        mov     [mx_SysClipX1], ax\r
+        mov     [mx_SysClipY1], ax\r
+        mov     ax, [Width]\r
+        dec     ax\r
+        mov     [mx_SysClipX2], ax\r
+        mov     ax, [Height]\r
+        dec     ax\r
+        mov     [mx_SysClipY2], ax\r
+\r
+    IF USE286 EQ TRUE\r
+        push    FALSE\r
+    ELSE\r
+        mov     ax, FALSE\r
+        push    ax\r
+    ENDIF\r
+        call    mxSetClip\r
+\r
+        .pop    ds\r
+        .leave  ARG_SIZE\r
+mxSetSysClipRegion      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the clip region.\r
+;\r
+; Input:\r
+;       X, Y    = coordinates of top left corner of clip region\r
+;       Width   = width in pixels of clip region\r
+;       Height  = height in pixels of clip region\r
+; Output:\r
+;       none (no checking on parameters)\r
+;\r
+mxSetClipRegion PROC    FAR\r
+        ARG     Height:WORD,            \\r
+                Width:WORD,             \\r
+                Y:WORD,                 \\r
+                X:WORD                  = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, [X]\r
+        mov     [mx_UserClipX1], ax\r
+        mov     ax, [Y]\r
+        mov     [mx_UserClipY1], ax\r
+        mov     ax, [Width]\r
+        add     ax, [X]\r
+        dec     ax\r
+        mov     [mx_UserClipX2], ax\r
+        mov     ax, [Height]\r
+        add     ax, [Y]\r
+        dec     ax\r
+        mov     [mx_UserClipY2], ax\r
+\r
+        mov     al, [mx_ClipStatus]\r
+        cmp     al, TRUE\r
+        jne     @@Exit\r
+        push    ax\r
+        call    mxSetClip\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds\r
+        .leave  ARG_SIZE\r
+mxSetClipRegion ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current user clip region.\r
+;\r
+; Input:\r
+;       X, Y    = pointers to integer coordinates of top left corner\r
+;       Width   = pointer to word width of clip region\r
+;       Height  = pointer to word height of clip region\r
+; Output:\r
+;       AX      = current clip status\r
+;\r
+mxGetClipRegion PROC    FAR\r
+        ARG     Height:DWORD,           \\r
+                Width:DWORD,            \\r
+                Y:DWORD,                \\r
+                X:DWORD                 = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   es, di\r
+\r
+        mov     ax, [mx_UserClipX1]\r
+        les     di, [X]\r
+        mov     es:[di], ax\r
+        mov     ax, [mx_UserClipY1]\r
+        les     di, [Y]\r
+        mov     es:[di], ax\r
+\r
+        mov     ax, [mx_UserClipX2]\r
+        sub     ax, [mx_UserClipX1]\r
+        inc     ax\r
+        les     di, [Width]\r
+        mov     es:[di], ax\r
+        mov     ax, [mx_UserClipY2]\r
+        sub     ax, [mx_UserClipY1]\r
+        inc     ax\r
+        les     di, [Height]\r
+        mov     es:[di], ax\r
+\r
+        mov     al, [mx_ClipStatus]\r
+        xor     ah, ah\r
+        .pop    es, di\r
+        .leave  ARG_SIZE\r
+mxGetClipRegion ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Internal use: checks the coordinates of a rectangle against\r
+; the active clip region.\r
+; This function assumes that a "raw" image has to be clipped,\r
+; so it returns in SI the number of "raw" bytes to skip if\r
+; X, Y were clipped.\r
+;\r
+; Input:\r
+;       BX, AX  = X, Y coordinates of rectangle (signed)\r
+;       CX      = box width\r
+;       DX      = box height\r
+; Output:\r
+;       CF      = set if rectangle is full clipped\r
+;       BX, AX  = new X, Y coordinates of rectangle\r
+;       CX, DX  = clipped width and height\r
+;       SI      = number of bytes to skip before copying a buffer\r
+;       DI destroyed\r
+;\r
+subClipImage    PROC    NEAR\r
+        ASSUME  ds:NOTHING\r
+        xor     si, si\r
+\r
+; Check clip height\r
+        mov     di, [mx_ClipY1]\r
+        cmp     ax, di\r
+        jge     @@CheckBottom\r
+        sub     di, ax                  ; Number of lines to clip\r
+        sub     dx, di                  ; New box height\r
+        jle     @@Exit\r
+        mov     ax, di\r
+        mov     di, dx                  ; Save box height into DI\r
+        mul     cx                      ; DX:AX = number of bytes to skip\r
+        mov     si, ax\r
+        mov     dx, di                  ; Restore box height\r
+        mov     ax, [mx_ClipY1]\r
+@@CheckBottom:\r
+        mov     di, [mx_ClipY2]\r
+        cmp     ax, di\r
+        jg      @@Exit\r
+        inc     di\r
+        sub     di, dx\r
+        sub     di, ax\r
+        jge     @@DoneHeight            ; None, continue\r
+        add     dx, di                  ; Clip lines\r
+@@DoneHeight:\r
+\r
+; Check clip width\r
+@@CheckLeft:\r
+        mov     di, [mx_ClipX1]\r
+        cmp     bx, di\r
+        jge     @@CheckRight\r
+        sub     di, bx                  ; Number of columns to clip left\r
+        sub     cx, di\r
+        jle     @@Exit\r
+        add     si, di                  ; Update skip count\r
+        mov     bx, [mx_ClipX1]\r
+@@CheckRight:\r
+        mov     di, [mx_ClipX2]\r
+        cmp     bx, di\r
+        jg      @@Exit\r
+        inc     di\r
+        sub     di, bx\r
+        sub     di, cx\r
+        jge     @@DoneWidth             ; None, exit\r
+        add     cx, di                  ; New box width\r
+@@DoneWidth:\r
+\r
+; Set return flag and exit\r
+@@Done:\r
+        clc\r
+        ret\r
+@@Exit:\r
+        stc\r
+        ret\r
+subClipImage    ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Internal use: checks the coordinates of a rectangle against\r
+; the active clip region.\r
+;\r
+; Input:\r
+;       BX, AX  = X, Y coordinates of rectangle (signed)\r
+;       CX      = box width\r
+;       DX      = box height\r
+; Output:\r
+;       CF      = set if rectangle is full clipped\r
+;       BX, AX  = new X, Y coordinates of rectangle\r
+;       CX, DX  = clipped width and height\r
+;       DI destroyed\r
+;\r
+subClipBox      PROC    NEAR\r
+        ASSUME  ds:NOTHING\r
+\r
+; Check clip height\r
+        mov     di, [mx_ClipY1]\r
+        cmp     ax, di\r
+        jge     @@CheckBottom\r
+        sub     di, ax                  ; Number of lines to clip\r
+        sub     dx, di                  ; New box height\r
+        jle     @@Exit\r
+        mov     ax, [mx_ClipY1]\r
+@@CheckBottom:\r
+        mov     di, [mx_ClipY2]\r
+        cmp     ax, di\r
+        jg      @@Exit\r
+        inc     di\r
+        sub     di, dx\r
+        sub     di, ax                  ; Clipped some point?\r
+        jge     @@DoneHeight            ; No, continue\r
+        add     dx, di                  ; Clip lines (DI is negative)\r
+@@DoneHeight:\r
+\r
+; Check clip width\r
+@@CheckLeft:\r
+        mov     di, [mx_ClipX1]\r
+        cmp     bx, di\r
+        jge     @@CheckRight\r
+        sub     di, bx                  ; Number of columns to clip left\r
+        sub     cx, di\r
+        jle     @@Exit\r
+        mov     bx, [mx_ClipX1]\r
+@@CheckRight:\r
+        mov     di, [mx_ClipX2]\r
+        cmp     bx, di\r
+        jg      @@Exit\r
+        inc     di\r
+        sub     di, bx\r
+        sub     di, cx                  ; Clipped some point?\r
+        jge     @@DoneWidth             ; No, exit\r
+        add     cx, di                  ; New box width (DI is negative)\r
+@@DoneWidth:\r
+\r
+; Set return flag and exit\r
+@@Done:\r
+        clc\r
+        ret\r
+@@Exit:\r
+        stc\r
+        ret\r
+subClipBox      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxel.asm b/16/x_/mxel.asm
new file mode 100755 (executable)
index 0000000..2c9dda2
--- /dev/null
@@ -0,0 +1,167 @@
+;-----------------------------------------------------------\r
+;\r
+; MXEL.ASM - Mid-point ellipse\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxEllipse\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Draws an ellipse using the mid-point algorithm.\r
+;\r
+; Input:\r
+;       XC, YC  = center coordinates\r
+;       A       = horizontal radius\r
+;       B       = vertical radius\r
+;       Color   = ellipse color\r
+; Output:\r
+;       none\r
+; Note:\r
+;       computes only points in the first quadrant, all other\r
+;       points are obtained by symmetry.\r
+;\r
+mxEllipse       PROC FAR\r
+        ARG     Color:BYTE:2,   \\r
+                B:WORD,         \\r
+                A:WORD,         \\r
+                YC:WORD,        \\r
+                XC:WORD         = ARG_SIZE\r
+        LOCAL   A2:DWORD,       \\r
+                B2:DWORD,       \\r
+                CC:DWORD,       \\r
+                DD:DWORD,       \\r
+                X:DWORD,        \\r
+                Y:DWORD         = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, di\r
+\r
+        .chk386 mxEllipse, @@Exit\r
+\r
+; Initialize variables\r
+        xor     eax, eax\r
+        mov     [X], ax         ; X = 0\r
+        mov     ax, [A]\r
+        mul     eax             ; EAX = A*A\r
+        mov     [DD], eax       ; DD = A*A\r
+        shl     eax, 1\r
+        mov     [CC], eax       ; CC = 2*A*A\r
+        shl     eax, 1\r
+        mov     [A2], eax       ; A2 = 4*A*A\r
+        movzx   edx, [B]\r
+        mov     [Y], edx\r
+        mul     edx             ; EAX = 4*A*A*B\r
+        sub     [DD], eax       ; DD = A*A - 4*A*A*B\r
+        movzx   eax, [B]\r
+        mul     eax             ; EAX = B*B\r
+        shl     eax, 2          ; EAX = 4*B*B\r
+        mov     [B2], eax       ; B2 = 4*B*B\r
+        add     [CC], eax       ; CC = 2*A*A + 4*B*B\r
+        add     [D1], eax       ; DD = A*A - 4*A*A*B + 4*B*B\r
+\r
+; Draw initial points\r
+        call    subPlot4\r
+\r
+; First loop\r
+@@Loop1:\r
+        mov     eax, [X]        ; Check slope\r
+        mul     [B2]\r
+        mov     ecx, eax\r
+        mov     eax, [Y]\r
+        mul     [A2]\r
+        sub     eax, ecx\r
+        sub     eax, [CC]       ; EAX = Y*A2 - X*B2 - CC\r
+        jle     @@Done1         ; Crossed critical point, jump to next loop\r
+\r
+        mov     ecx, [DD]       ; Get error\r
+        test    ecx, ecx        ; Positive?\r
+        jl      @@Draw1         ; No, use default step\r
+\r
+        mov     eax, 1\r
+        sub     eax, [Y]\r
+        mul     [A2]\r
+        shl     eax, 1\r
+        add     ecx, eax        ; Bump error\r
+        dec     WORD PTR [Y]    ; Decrement Y coordinate\r
+\r
+@@Draw1:\r
+        mov     eax, [X]\r
+        shl     eax, 1\r
+        add     eax, 3\r
+        mul     [B2]\r
+        add     ecx, eax        ; Bump error\r
+        mov     [DD], ecx       ; Save error\r
+        inc     WORD PTR [X]    ; Increment X coordinate\r
+\r
+        call    subPlot4        ; Draw points\r
+        jmp     @@Loop1\r
+@@Done1:\r
+\r
+; Initialize variables\r
+        shr     [B2], 2\r
+        mov     eax, [X]\r
+        mul     eax\r
+        add     [X]\r
+        shl     eax, 2\r
+        inc     eax\r
+        mul     [B2]\r
+        mov     [DD], eax\r
+        mov     eax, [Y]\r
+        mul     eax\r
+        add     [Y]\r
+        dec     eax\r
+        add     [Y]\r
+        sub     eax, [B2]\r
+        add     [DD], eax\r
+        shl     [B2], 3\r
+        inc     WORD PTR [X]\r
+\r
+; Second loop\r
+@@Loop2:\r
+        cmp     WORD PTR [Y], 0\r
+        ja      @@Done2\r
+\r
+        mov     ecx, [DD]\r
+        test    ecx, ecx\r
+        jge     @@Draw2\r
+\r
+        mov     eax, [X]\r
+        inc     eax\r
+        mul     [B2]\r
+        add     ecx, eax\r
+        inc     WORD PTR [X]\r
+\r
+@@Draw2:\r
+        mov     eax, [Y]\r
+        shl     eax, 1\r
+        sub     eax, 3\r
+        neg     eax\r
+        imul    [A2]\r
+        add     ecx, eax\r
+        dec     WORD PTR [Y]\r
+\r
+        call    subPlot4\r
+        jmp     @@Loop2\r
+@@Done2:\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .leave  ARG_SIZE\r
+mxEllipse       ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxfb.asm b/16/x_/mxfb.asm
new file mode 100755 (executable)
index 0000000..41ea5de
--- /dev/null
@@ -0,0 +1,194 @@
+;-----------------------------------------------------------\r
+;\r
+; MXFB.ASM - Fill box function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxFillBox\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine         : WORD\r
+EXTRN   mx_VideoSegment         : WORD\r
+EXTRN   subClipBox              : NEAR\r
+EXTRN   subHorizontalLineInfo   : NEAR\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Raster op functions. Raster op is limited to OP_MOVE,\r
+; OP_AND, OP_OR and OP_XOR. The VGA hardware is used to\r
+; perform the selected logical functions on up to four\r
+; pixel at a time.\r
+;\r
+subRepFill      PROC    NEAR\r
+        mov     ah, al\r
+        shr     cx, 1\r
+        rep     stosw\r
+        rcl     cx, 1\r
+        rep     stosb\r
+        ret\r
+subRepFill      ENDP\r
+;\r
+subFill         PROC    NEAR\r
+@@Loop:\r
+        mov     ds:[bx], al\r
+        add     bx, dx\r
+        loop    @@Loop\r
+        ret\r
+subFill         ENDP\r
+;\r
+subRepMove      PROC    NEAR\r
+        mov     si, di\r
+@@Loop:\r
+        mov     ah, ds:[si]             ; Dummy read to latch the data\r
+        mov     ds:[si], al\r
+        inc     si\r
+        loop    @@Loop\r
+        ret\r
+subRepMove      ENDP\r
+;\r
+subMove         PROC    NEAR\r
+@@Loop:\r
+        mov     ah, ds:[bx]             ; Dummy read to latch the data\r
+        mov     ds:[bx], al\r
+        add     bx, dx\r
+        loop    @@Loop\r
+        ret\r
+subMove         ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a rectangle with a specified color.\r
+;\r
+; Input:\r
+;       X, Y            = X, Y coordinates of rectangle\r
+;       Width           = width of rectangle\r
+;       Height          = height of rectangle\r
+;       Color           = fill color\r
+;       Op              = raster operator\r
+; Output:\r
+;       none\r
+;\r
+; Note: raster op is limited to OP_MOVE, OP_AND, OP_OR and OP_XOR.\r
+;\r
+mxFillBox       PROC    FAR\r
+        ARG     Op:WORD,                \\r
+                Color:BYTE:2,           \\r
+                Height:WORD,            \\r
+                Width:WORD,             \\r
+                Y:WORD,                 \\r
+                X:WORD                  = ARG_SIZE\r
+        LOCAL   LeftMask:BYTE,          \\r
+                RightMask:BYTE,         \\r
+                FillFunction:WORD,      \\r
+                RepFillFunction:WORD    = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+        ASSUME  ds:NOTHING\r
+\r
+; Clip rectangle\r
+        mov     bx, [X]\r
+        mov     ax, [Y]\r
+        mov     cx, [Width]\r
+        mov     dx, [Height]\r
+        call    subClipBox\r
+        jc      @@Exit                  ; Full clipped\r
+\r
+        mov     [Height], dx            ; Save clipped height\r
+        call    subHorizontalLineInfo   ; Get additional info, init DI\r
+        mov     [Width], cx\r
+        mov     [LeftMask], al\r
+        mov     [RightMask], ah\r
+\r
+; Initialize segments\r
+        mov     ax, [mx_VideoSegment]\r
+        mov     es, ax                  ; ES:DI points to pixel\r
+        mov     ds, ax\r
+        cld                             ; Clear direction flag\r
+\r
+; Select fill functions\r
+        mov     [FillFunction], OFFSET subFill\r
+        mov     [RepFillFunction], OFFSET subRepFill\r
+        mov     ax, [Op]                ; Get raster op\r
+        cmp     al, OP_XOR\r
+        ja      @@1                     ; Assume it's a fill\r
+        cmp     al, OP_MOVE\r
+        je      @@1\r
+        .shl    al, 3\r
+        mov     ah, al\r
+        mov     al, 03h\r
+        mov     dx, GDC\r
+        out     dx, ax                  ; Set GDC logical function\r
+        mov     [FillFunction], OFFSET subMove\r
+        mov     [RepFillFunction], OFFSET subRepMove\r
+@@1:\r
+\r
+; Fill left block\r
+@@L0:\r
+        mov     ah, [LeftMask]\r
+        or      ah, ah\r
+        jz      @@C0                    ; Nothing to do, go to center block\r
+        mov     dx, TS\r
+        mov     al, 02h\r
+        out     dx, ax                  ; Set write plane mask\r
+        mov     dx, [mx_BytesPerLine]\r
+        mov     cx, [Height]\r
+        mov     bx, di\r
+        mov     al, [Color]\r
+        call    [FillFunction]          ; Fill this column\r
+        inc     di                      ; Update starting video offset\r
+\r
+; Fill center block\r
+@@C0:\r
+        mov     cx, [Width]\r
+        jcxz    @@R0                    ; Nothing to do, go to right block\r
+        mov     dx, TS\r
+        mov     ax, 0F02h\r
+        out     dx, ax                  ; Write to all planes\r
+        mov     al, [Color]\r
+        mov     bx, di\r
+        mov     dx, [Height]\r
+        push    di                      ; Save pixel address\r
+@@C1:\r
+        mov     di, bx                  ; Update video offset\r
+        call    [RepFillFunction]       ; Fill current scan line\r
+        mov     cx, [Width]             ; Restore byte count\r
+        add     bx, [mx_BytesPerLine]   ; Bump to next scan line\r
+        dec     dx                      ; Done all lines?\r
+        jnz     @@C1                    ; No, continue\r
+        pop     di                      ; Restore pixel address\r
+        add     di, [Width]             ; Go to right block\r
+\r
+; Fill right block\r
+@@R0:\r
+        mov     ah, [RightMask]\r
+        or      ah, ah\r
+        jz      @@Done                  ; Nothing to do, exit\r
+        mov     dx, TS\r
+        mov     al, 02h\r
+        out     dx, ax                  ; Set write plane mask\r
+        mov     dx, [mx_BytesPerLine]\r
+        mov     cx, [Height]\r
+        mov     bx, di\r
+        mov     al, [Color]\r
+        call    [FillFunction]          ; Fill this column\r
+\r
+; Restore VGA registers\r
+@@Done:\r
+        mov     dx, GDC\r
+        mov     ax, 0003h\r
+        out     dx, ax                  ; Set logical function to "move"\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxFillBox       ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxfp.asm b/16/x_/mxfp.asm
new file mode 100755 (executable)
index 0000000..8eea25b
--- /dev/null
@@ -0,0 +1,326 @@
+;-----------------------------------------------------------\r
+;\r
+; MXFP.ASM - Fade palette function\r
+; Copyright (c) 1992-1994 ARTIS s.r.l.\r
+; Author: Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxFadePalette\r
+\r
+MAXCOLOR        EQU     256\r
+FADE_IN         EQU     0\r
+FADE_OUT        EQU     1\r
+\r
+; The actual speed of fading depends on the number of passes (FADE_SPEED) and\r
+; the delay between two consecutive passes (FADE_DELAY). Below are the\r
+; default values, used when no parameters are specified.\r
+;\r
+FADE_DELAY      EQU     1               ; Vert. retraces between video updates\r
+FADE_SPEED      EQU     48              ; Speed of effect (max 127)\r
+\r
+; Bit field record for fade commands\r
+;\r
+FADE_COMMAND    RECORD  fpDELAY:8,fpSPEED:7,fpDIRECTION:1\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+DB      'Copyright (c) 1992-1994 ARTIS s.r.l. All rights reserved.'\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fades a VGA palette.\r
+;\r
+; Input:\r
+;       Buffer          = pointer to source/destination palette\r
+;       Command         = fading direction and optional parameters\r
+;       Start           = index of first color to fade\r
+;       Count           = number of color to fade\r
+;       Red             = destination red\r
+;       Green           = destination green\r
+;       Blue            = destination blue\r
+; Output:\r
+;       none\r
+; Notes:\r
+;    -  about 1.5 Kbytes of stack space are needed for internal buffers;\r
+;    -  the Command argument usually is 0 to fade in and 1 to fade out,\r
+;       however additional parameters may be specified. To set the effect\r
+;       speed, i.e. the number of iterations needed to completely fade a\r
+;       palette, shift the value one bit left and "or" it with the\r
+;       direction bit (range is 0..127). To set the delay between two\r
+;       consecutive passes, shift it eight bits left (range is 0..255).\r
+;\r
+mxFadePalette   PROC FAR\r
+        ARG     bBlue:WORD,                     \\r
+                bGreen:WORD,                    \\r
+                bRed:WORD,                      \\r
+                wCount:WORD,                    \\r
+                wStartIdx:WORD,                 \\r
+                wCommand:WORD,                  \\r
+                vfpPalette:DWORD = ARG_SIZE\r
+        LOCAL   bSPalette:BYTE:MAXCOLOR*3,      \\r
+                bDPalette:BYTE:MAXCOLOR*3,      \\r
+                bLoopIndex:BYTE,                \\r
+                bLoopStep:BYTE,                 \\r
+                bLoopCount:BYTE,                \\r
+                wDelay:WORD,                    \\r
+                wSpeed:WORD     = AUTO_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  AUTO_SIZE\r
+        .push   si, di, ds, es                  ; Save registers\r
+;\r
+; Check parameters and setup variables\r
+;\r
+@@GetDelay:\r
+        mov     [wDelay], FADE_DELAY            ; Set default delay\r
+        mov     ax, [wCommand]                  ; Get command word\r
+        and     ax, MASK fpDELAY                ; Mask delay command\r
+        jz      @@GetSpeed                      ; No command, get speed\r
+    IF USE286 EQ TRUE\r
+        shr     ax, fpDELAY\r
+    ELSE\r
+        mov     cl, fpDELAY                     ; Get size of delay field\r
+        shr     ax, cl                          ; Right justify the field\r
+    ENDIF\r
+        mov     [wDelay], ax                    ; Set new delay\r
+\r
+@@GetSpeed:\r
+        mov     ax, [wCommand]                  ; Get command\r
+        and     ax, MASK fpSPEED                ; Mask speed\r
+    IF USE286 EQ TRUE\r
+        shr     ax, fpSPEED\r
+    ELSE\r
+        mov     cl, fpSPEED                     ; Get size of speed field\r
+        shr     ax, cl                          ; Right justify the field\r
+    ENDIF\r
+        or      ax, ax                          ; Any speed specified?\r
+        jnz     @@SetVariables                  ; Yes, set variables\r
+        mov     ax, FADE_SPEED                  ; Set default speed\r
+\r
+@@SetVariables:\r
+        mov     [wSpeed], ax                    ; Set speed\r
+        inc     ax                              ; Number of iterations\r
+        mov     [bLoopCount], al                ; Set loop count\r
+        mov     [bLoopStep], 1                  ; Assume we're fading in\r
+        mov     [bLoopIndex], 0\r
+;\r
+; Check bounds for bad values\r
+;\r
+        mov     ax, [wStartIdx]                 ; Get first index\r
+        cmp     ax, MAXCOLOR                    ; Is in the valid range?\r
+        jae     @@Exit                          ; No, exit\r
+        add     ax, [wCount]                    ; Get last index\r
+        cmp     ax, MAXCOLOR                    ; Is in the valid range?\r
+        jbe     @@BoundsOk                      ; Yes, continue\r
+        mov     ax, MAXCOLOR\r
+        sub     ax, [wStartIdx]\r
+        mov     [wCount], ax                    ; Set count to maximum value\r
+        or      ax, ax\r
+        jz      @@Exit                          ; Nothing to do, exit\r
+@@BoundsOk:\r
+;\r
+; Copy the source palette in a local array: if we fade in it's ready to\r
+; use, otherwise we'll overwrite it later\r
+;\r
+        mov     cx, [wCount]\r
+        mov     ax, cx\r
+        shl     ax, 1\r
+        add     cx, ax                          ; CX = wCount * 3\r
+        mov     ax, ss\r
+        mov     es, ax\r
+        lea     di, [bSPalette]                 ; ES:DI points to local palette\r
+        mov     ax, [wStartIdx]\r
+        mov     si, ax\r
+        shl     ax, 1\r
+        add     ax, si\r
+        lds     si, [vfpPalette]                ; DS:SI points to user palette\r
+        add     si, ax                          ; Skip unused entries\r
+        cld\r
+        shr     cx, 1\r
+        rep     movsw\r
+        rcl     cx, 1\r
+        rep     movsb\r
+;\r
+; Check direction\r
+;\r
+        test    [wCommand], MASK fpDIRECTION    ; Are we fading in?\r
+        jz      @@Main                          ; Yes, ok to continue\r
+        mov     ax, [wSpeed]                    ; Get speed\r
+        mov     [bLoopIndex], al                ; Exchange first and last index\r
+        mov     [bLoopStep], -1                 ; Move backward\r
+        mov     ax, ss                          ; Overwrite our copy of\r
+        mov     ds, ax                          ; user palette with the\r
+        mov     es, ax                          ; current active palette\r
+        lea     di, [bSPalette]\r
+        mov     ax, [wStartIdx]\r
+        mov     cx, [wCount]\r
+        call    ReadPalette                     ; Read current palette\r
+;\r
+; Prepare variables and registers for fading\r
+;\r
+@@Main:\r
+        mov     bh, BYTE PTR [bRed]             ; Destination red\r
+        and     bh, 00111111b                   ; Be sure it's a valid VGA value\r
+        mov     bl, BYTE PTR [bGreen]           ; Destination green\r
+        and     bl, 00111111b                   ; Be sure it's a valid VGA value\r
+        mov     dh, BYTE PTR [bBlue]            ; Destination blue\r
+        and     dh, 00111111b                   ; Be sure it's a valid VGA value\r
+        mov     dl, [bLoopIndex]                ; Loop index\r
+        mov     ax, ss                          ; All tables are stored\r
+        mov     ds, ax                          ; in the stack segment,\r
+        mov     es, ax                          ; set DS and ES\r
+;\r
+; Main loop\r
+;\r
+@@Loop:\r
+        mov     ax, [wCount]                    ; Store count in AX\r
+        mov     cx, [wSpeed]                    ; Set maximum speed in CX\r
+        lea     si, [bSPalette]                 ; DS:SI points to source palette\r
+        lea     di, [bDPalette]                 ; ES:DI points to dest. palette\r
+        call    RecalcPalette                   ; Build a faded palette\r
+\r
+        .push   bx, dx                          ; Save registers we need\r
+        lea     si, [bDPalette]                 ; DS:SI points to palette\r
+        mov     ax, [wStartIdx]                 ; First index to write\r
+        mov     bx, [wCount]                    ; Total entries to write\r
+        mov     cx, [wDelay]                    ; Fade delay between updates\r
+        call    WritePalette                    ; Write palette\r
+        .pop    bx, dx                          ; Restore BX and DX\r
+\r
+        add     dl, [bLoopStep]                 ; Change fade intensity\r
+        dec     [bLoopCount]                    ; Done?\r
+        jnz     @@Loop                          ; No, loop again\r
+\r
+@@Exit:\r
+        .pop    si, di, ds, es                  ; Restore registers\r
+        .leave  ARG_SIZE\r
+mxFadePalette   ENDP\r
+\r
+;------- INTERNAL USE ONLY ------------------------------------------------\r
+;\r
+; Calculates a partially faded palette.\r
+;\r
+; Input:\r
+;       AX      = number of entries in palette\r
+;       CX      = maximum fade intensity (same as fade speed)\r
+;       DS:SI   = pointer to source palette\r
+;       ES:DI   = pointer to destination palette\r
+;       BH      = destination red\r
+;       BL      = destination green\r
+;       DH      = destination blue\r
+;       DL      = relative intensity of destination palette\r
+; Note:\r
+;       it's important that a new palette can be calculated in less\r
+;       than 1/70th of second. Fading to any RGB value requires use\r
+;       of "imul" instructions: "idiv" may be replaced with faster\r
+;       "sar", but only when the number of passes is a power of two,\r
+;       thus reducing the range of selectable speeds.\r
+;       In both cases an extimate of CPU cycles required by this\r
+;       procedure shows that it's too slow to run on a 4.77 Mhz 8086\r
+;       CPU and a 256 color palette, so we keep "idiv" and hope\r
+;       the target machine to be at least a 6 Mhz 80286 (that's not\r
+;       asking too much...).\r
+;\r
+RecalcPalette   PROC NEAR\r
+        cld\r
+        push    bp                              ; Save BP\r
+        mov     bp, ax                          ; Copy counter in BP\r
+@@Loop:\r
+        lodsb                                   ; Red: read value\r
+        sub     al, bh                          ; Subtract destination value\r
+        imul    dl                              ; Scale to desired weight\r
+        idiv    cl                              ; Put value in AL\r
+        add     al, bh                          ; Add destination value...\r
+        stosb                                   ; ...and store it\r
+        lodsb                                   ; Green: read value\r
+        sub     al, bl                          ; Subtract destination value\r
+        imul    dl                              ; Scale to desired weight\r
+        idiv    cl                              ; Put value in AL\r
+        add     al, bl                          ; Add destination value...\r
+        stosb                                   ; ...and store it\r
+        lodsb                                   ; Blue: read value\r
+        sub     al, dh                          ; Subtract destination value\r
+        imul    dl                              ; Scale to desired weight\r
+        idiv    cl                              ; Put value in AL\r
+        add     al, dh                          ; Add destination value...\r
+        stosb                                   ; ...and store it\r
+        dec     bp\r
+        jnz     @@Loop\r
+        pop     bp                              ; Restore BP\r
+        ret\r
+RecalcPalette   ENDP\r
+\r
+;------- INTERNAL USE ONLY ------------------------------------------------\r
+;\r
+; Writes a 256 color palette.\r
+;\r
+; Input:\r
+;       AX      = index of first color to write\r
+;       BX      = number of colors to write (each color is an RGB triplet)\r
+;       CX      = number of vertical retraces to wait before writing to DACs\r
+;       DS:SI   = pointer to first entry of palette\r
+;\r
+WritePalette    PROC NEAR\r
+        ASSUME  ds:NOTHING\r
+        mov     ah, al                          ; Save index\r
+        mov     dx, 03DAh                       ; Input status register\r
+@@Delay1:\r
+        in      al, dx\r
+        test    al, 08h\r
+        jnz     @@Delay1                        ; Wait for display mode\r
+@@Delay2:\r
+        in      al, dx\r
+        test    al, 08h\r
+        jz      @@Delay2                        ; Wait for vertical retrace mode\r
+        loop    @@Delay1                        ; Repeat CX times\r
+@@Write:\r
+        mov     cx, bx                          ; Get number of colors\r
+        mov     dx, 03C8h                       ; PEL write address register\r
+        mov     al, ah                          ; Restore index\r
+        out     dx, al                          ; Select index of first color\r
+        inc     dx                              ; PEL data register\r
+        cld                                     ; Move forward\r
+        cli                                     ; Disable interrupts\r
+@@Loop:\r
+        lodsb\r
+        out     dx, al                          ; Red\r
+        lodsb\r
+        out     dx, al                          ; Green\r
+        lodsb\r
+        out     dx, al                          ; Blue\r
+        loop    @@Loop                          ; Loop until done\r
+        sti                                     ; Enable interrupts\r
+        ret\r
+WritePalette    ENDP\r
+\r
+;------- INTERNAL USE ONLY ------------------------------------------------\r
+;\r
+; Reads the current palette.\r
+;\r
+; Input:\r
+;       AX      = index of first color to read\r
+;       CX      = number of colors\r
+;       ES:DI   = pointer to destination buffer\r
+;\r
+ReadPalette     PROC    NEAR\r
+        mov     dx, 03C7h\r
+        out     dx, al\r
+        inc     dx\r
+        inc     dx\r
+        cld\r
+@@Loop:\r
+        in      al, dx\r
+        stosb\r
+        in      al, dx\r
+        stosb\r
+        in      al, dx\r
+        stosb\r
+        loop    @@Loop\r
+        ret\r
+ReadPalette     ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxgc.asm b/16/x_/mxgc.asm
new file mode 100755 (executable)
index 0000000..85edf7a
--- /dev/null
@@ -0,0 +1,54 @@
+;-----------------------------------------------------------\r
+;\r
+; MXGC.ASM - Get color function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxGetColor\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current setting of the selected DAC register.\r
+;\r
+; Input:\r
+;       Index   = color index (0-255)\r
+;       R, G, B = byte pointers to red, green and blue\r
+; Output:\r
+;       none\r
+;\r
+mxGetColor      PROC FAR\r
+        ARG     B:DWORD,        \\r
+                G:DWORD,        \\r
+                R:DWORD,        \\r
+                Index:WORD      = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+\r
+        mov     ax, [Index]\r
+        mov     dx, 3C7h                ; PEL read address register\r
+        out     dx, al\r
+        inc     dx\r
+        inc     dx\r
+\r
+        lds     si, [R]\r
+        in      al, dx\r
+        mov     ds:[si], al\r
+        lds     si, [G]\r
+        in      al, dx\r
+        mov     ds:[si], al\r
+        lds     si, [B]\r
+        in      al, dx\r
+        mov     ds:[si], al\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetColor      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxgi.asm b/16/x_/mxgi.asm
new file mode 100755 (executable)
index 0000000..7037d41
--- /dev/null
@@ -0,0 +1,132 @@
+;-----------------------------------------------------------\r
+;\r
+; MXGI.ASM - Get image\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxGetImage\r
+\r
+EXTRN   subClipImage            : NEAR\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies an image from screen to memory.\r
+;\r
+; Input:\r
+;       Image   = pointer to buffer for image\r
+;       X, Y    = coordinates of image on screen\r
+;       Width   = width of image in pixels\r
+;       Height  = height of image in pixels\r
+; Output:\r
+;       none\r
+;\r
+mxGetImage      PROC    FAR\r
+        ARG     Height:WORD,            \\r
+                Width:WORD,             \\r
+                Y:WORD,                 \\r
+                X:WORD,                 \\r
+                Image:DWORD             = ARG_SIZE\r
+        LOCAL   PlaneWidth:WORD:4,      \\r
+                PixelOffset:WORD,       \\r
+                MoveFunction:WORD,      \\r
+                ReadPlane:BYTE,         \\r
+                Count:BYTE              = AUTO_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+\r
+; Clip image\r
+        mov     bx, [X]\r
+        mov     ax, [Y]\r
+        mov     cx, [Width]\r
+        mov     dx, [Height]\r
+        call    subClipImage\r
+        jc      @@Exit                  ; Full clipped\r
+        mov     [Height], dx\r
+        add     WORD PTR Image[0], si   ; Skip clipped pixels\r
+\r
+; Get pixel address\r
+        mul     [mx_BytesPerLine]\r
+        mov     si, bx\r
+        shr     si, 1\r
+        shr     si, 1\r
+        add     si, ax\r
+        mov     [PixelOffset], si\r
+        mov     ds, [mx_VideoSegment]   ; DS:SI points to pixel\r
+        and     bl, 03h\r
+        mov     [ReadPlane], bl\r
+\r
+; Compute extra bytes and width count for each plane\r
+        mov     bx, cx\r
+        shr     bx, 1\r
+        shr     bx, 1                   ; Width for each plane\r
+        and     cl, 03h\r
+        mov     al, 00001000b\r
+        shr     al, cl\r
+        mov     di, 3 SHL 1\r
+@@PatchLoop:\r
+        mov     PlaneWidth[di], bx\r
+        shr     al, 1\r
+        adc     bx, 0\r
+        dec     di\r
+        dec     di\r
+        jge     @@PatchLoop\r
+\r
+; Get image\r
+        cld\r
+        mov     [Count], 4              ; Four planes\r
+        lea     bx, PlaneWidth          ; SS:[BX] = width in bytes for plane\r
+        mov     es, WORD PTR Image[2]   ; ES:DI will point to image\r
+        mov     ah, [ReadPlane]\r
+@@PlaneLoop:\r
+        cmp     WORD PTR ss:[bx], 0     ; Exit if nothing more to do\r
+        je      @@Exit                  ; (also, never try to move zero bytes!)\r
+        mov     di, WORD PTR Image[0]\r
+        mov     al, 04h\r
+        mov     dx, GDC\r
+        out     dx, ax                  ; Select read plane\r
+        mov     dx, [Height]\r
+        mov     si, [PixelOffset]       ; DS:SI points to video memory\r
+@@Loop:\r
+        .push   si, di\r
+        mov     cx, WORD PTR ss:[bx]    ; Number of bytes to move\r
+@@MoveLoop:\r
+        movsb\r
+        add     di, 3\r
+        dec     cx\r
+        jnz     @@MoveLoop\r
+        .pop    si, di\r
+        add     di, [Width]             ; Go to next image line\r
+        add     si, [mx_BytesPerLine]   ; Go to next screen row\r
+        dec     dx\r
+        jnz     @@Loop                  ; Repeat for all lines\r
+        inc     bx\r
+        inc     bx                      ; Select width for next plane\r
+        inc     ah\r
+        test    ah, 04h                 ; Plane wraparound?\r
+        jz      @@PlaneOk               ; No\r
+        inc     [PixelOffset]           ; Yes, bump video pointer\r
+        and     ah, 03h\r
+@@PlaneOk:\r
+        inc     WORD PTR Image[0]\r
+        dec     [Count]\r
+        jnz     @@PlaneLoop             ; Repeat for all planes\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxGetImage      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxgm.asm b/16/x_/mxgm.asm
new file mode 100755 (executable)
index 0000000..a67476a
--- /dev/null
@@ -0,0 +1,63 @@
+;-----------------------------------------------------------\r
+;\r
+; MXGM.ASM - Gamma correction\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxGammaCorrect\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+mx_tblGamma     LABEL BYTE\r
+    DB  00, 10, 14, 17, 19, 21, 23, 24, 26, 27, 28, 29, 31, 32, 33, 34\r
+    DB  35, 36, 37, 37, 38, 39, 40, 41, 41, 42, 43, 44, 44, 45, 46, 46\r
+    DB  47, 48, 48, 49, 49, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55\r
+    DB  56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Correct palette colors (gamma is 2.3).\r
+;\r
+; Input:\r
+;       CPal    = pointer to color palette\r
+;       GPal    = pointer to destination (gamma corrected) palette\r
+;       Count   = number of colors to convert\r
+; Output:\r
+;       none\r
+;\r
+; Note: CPal and GPal may point to the same buffer.\r
+;\r
+mxGammaCorrect  PROC    FAR\r
+        ARG     Count:WORD,     \\r
+                DPal:DWORD,     \\r
+                SPal:DWORD      = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si, es, di\r
+\r
+        mov     cx, [Count]\r
+        jcxz    @@Exit                  ; Exit now if nothing to do\r
+        lds     si, [SPal]\r
+        les     di, [DPal]\r
+        mov     bx, OFFSET mx_tblGamma  ; Setup BX for XLAT instruction\r
+        cld\r
+        mov     ax, cx                  ; AX = Count\r
+        add     cx, cx                  ; CX = Count*2\r
+        add     cx, ax                  ; CX = Count*3\r
+@@Loop:\r
+        lodsb\r
+        xlat    mx_tblGamma\r
+        stosb\r
+        loop    @@Loop\r
+\r
+@@Exit:\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxGammaCorrect  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxgp.asm b/16/x_/mxgp.asm
new file mode 100755 (executable)
index 0000000..6c14317
--- /dev/null
@@ -0,0 +1,56 @@
+;-----------------------------------------------------------\r
+;\r
+; MXGP.ASM - Get palette function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxGetPalette\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current setting of the VGA palette.\r
+;\r
+; Input:\r
+;       Buffer          = pointer to palette data (R,G,B)\r
+;       Start           = index of first color to get\r
+;       Count           = number of color to get\r
+; Output:\r
+;       none\r
+;\r
+mxGetPalette    PROC    FAR\r
+        ARG     Count:WORD,             \\r
+                Start:WORD,             \\r
+                Buffer:DWORD            = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   es, di\r
+\r
+        les     di, [Buffer]\r
+        mov     cx, [Count]\r
+        mov     ax, [Start]\r
+        mov     dx, 3C7h                ; PEL read address register\r
+        out     dx, al\r
+        inc     dx\r
+        inc     dx\r
+        cld\r
+@@Loop:\r
+        in      al, dx\r
+        stosb\r
+        in      al, dx\r
+        stosb\r
+        in      al, dx\r
+        stosb\r
+        loop    @@Loop                  ; Loop until done\r
+\r
+        .pop    es, di\r
+        .leave  ARG_SIZE\r
+mxGetPalette    ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxgv.asm b/16/x_/mxgv.asm
new file mode 100755 (executable)
index 0000000..2a54b1d
--- /dev/null
@@ -0,0 +1,25 @@
+;-----------------------------------------------------------\r
+;\r
+; MXGV.ASM - Get version function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxGetVersion\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the library version.\r
+;\r
+mxGetVersion    PROC    FAR\r
+        mov     ax, MXVERSION\r
+        ret\r
+mxGetVersion    ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxhl.asm b/16/x_/mxhl.asm
new file mode 100755 (executable)
index 0000000..049a056
--- /dev/null
@@ -0,0 +1,76 @@
+;-----------------------------------------------------------\r
+;\r
+; MXHL.ASM - Horizontal line mask utility\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  subHorizontalLineInfo\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+tblLeftSize     DW      00h, 03h, 02h, 01h\r
+tblLeftMask     DB      00h, 0Eh, 0Ch, 08h\r
+tblRightMask    DB      00h, 01h, 03h, 07h\r
+tblPatchMask    DB      02h, 06h\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Prepares register for fast horizontal line drawing.\r
+;\r
+; Input:\r
+;       BX, AX  = X, Y address of left pixel\r
+;       CX      = line width\r
+; Output:\r
+;       DI      = left pixel offset in video memory\r
+;       AL      = left block write plane mask (0 = none)\r
+;       AH      = right block write plane mask (0 = none)\r
+;       CX      = center block width in 4-pixel blocks\r
+;\r
+subHorizontalLineInfo   PROC NEAR\r
+        ASSUME  ds:NOTHING\r
+\r
+        mul     [mx_BytesPerLine]\r
+        mov     di, bx\r
+        shr     di, 1\r
+        shr     di, 1\r
+        add     di, ax                  ; Offset of left pixel\r
+\r
+        and     bx, 03h\r
+        mov     al, tblLeftMask[bx]\r
+        shl     bx, 1\r
+        sub     cx, tblLeftSize[bx]\r
+        jge     @@1                     ; Ok to continue\r
+\r
+; Special case: start and end in the middle of a 4-pixel block.\r
+; There are only three cases:\r
+;    Pixels     Left mask       CX      CX+2    Patch mask      Result\r
+; 1)  ..o.        ..xx          -1      1       .xx.            ..x.\r
+; 2)  .oo.        .xxx          -1      1       .xx.            .xx.\r
+; 3)  .o..        .xxx          -2      0       .x..            .x..\r
+; All other cases are automatically handled with the standard masks.\r
+        mov     bx, cx\r
+        inc     bx\r
+        inc     bx\r
+        and     al, tblPatchMask[bx]    ; Combine masks\r
+        xor     ah, ah                  ; No right block\r
+        xor     cx, cx                  ; No center block\r
+        jmp     @@Exit\r
+\r
+@@1:\r
+        mov     bx, cx\r
+        and     bx, 03h\r
+        mov     ah, tblRightMask[bx]\r
+        shr     cx, 2\r
+\r
+@@Exit:\r
+        ret\r
+subHorizontalLineInfo   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxit.asm b/16/x_/mxit.asm
new file mode 100755 (executable)
index 0000000..c0d9ced
--- /dev/null
@@ -0,0 +1,98 @@
+;-----------------------------------------------------------\r
+;\r
+; MXIT.ASM - Initialization/termination functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxInit\r
+PUBLIC  mxTerm\r
+\r
+PUBLIC  mx_VideoSegment\r
+PUBLIC  mx_CodeSegment\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+DB      'MODEX library - Copyright (c) 1992-1994 Alessandro Scotti'\r
+\r
+mx_VideoSegment DW      0A000h\r
+mx_CodeSegment  DW      SEG MX_TEXT\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Initialization.\r
+;\r
+; Input:\r
+;       none\r
+; Output:\r
+;       AX      = 0 on success\r
+;\r
+mxInit  PROC FAR\r
+        LOCAL   Result:WORD,            \\r
+                VideoSeg:WORD,          \\r
+                CStoDSalias:WORD        = AUTO_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+\r
+        mov     [Result], -1            ; Assume an error\r
+        mov     [VideoSeg], 0A000h      ; Real mode video segment\r
+        mov     [CStoDSalias], cs       ; Real mode data alias for CS\r
+\r
+; Check if running in protected mode under DPMI\r
+        mov     ax, 1686h\r
+        int     2Fh\r
+        or      ax, ax\r
+         jnz    @@1                     ; DPMI not found, continue in real mode\r
+\r
+; Get a data alias for CS\r
+        mov     ax, 000Ah               ; DMPI: create data alias\r
+        mov     bx, cs\r
+        int     31h\r
+         jc     @@Exit                  ; Exit if service failed\r
+        mov     [CStoDSalias], ax       ; Save data alias for CS\r
+; Get a protected-mode selector for the video segment\r
+        mov     ax, 0002h\r
+        mov     bx, 0A000h              ; Real mode segment of video\r
+        int     31h                     ; DPMI: get segment selector\r
+         jc     @@Exit                  ; Exit if service failed\r
+        mov     [VideoSeg], ax          ; Save protected mode video selector\r
+\r
+; Initialize variables\r
+@@1:\r
+        mov     ds, [CStoDSalias]\r
+        ASSUME  ds:MX_TEXT\r
+        mov     [mx_CodeSegment], ds\r
+        mov     ax, [VideoSeg]\r
+        mov     [mx_VideoSegment], ax\r
+\r
+; Don't bother with VGA check for now...\r
+\r
+        mov     [Result], 0\r
+\r
+@@Exit:\r
+        mov     ax, [Result]\r
+        .pop    ds, si, es, di\r
+        .leave\r
+mxInit  ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Termination.\r
+;\r
+; Input:\r
+;       none\r
+; Output:\r
+;       always 0.\r
+;\r
+mxTerm  PROC FAR\r
+        ASSUME  ds:NOTHING\r
+        xor     ax, ax\r
+        ret\r
+mxTerm  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxll.asm b/16/x_/mxll.asm
new file mode 100755 (executable)
index 0000000..34fec04
--- /dev/null
@@ -0,0 +1,82 @@
+;-----------------------------------------------------------\r
+;\r
+; MXLL.ASM - Load latches\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxLoadLatches\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Loads the specified value into the VGA latches.\r
+;\r
+; Input:\r
+;       BL      = value to load into latches\r
+; Output:\r
+;       none\r
+; Changes:\r
+;       bit mask register to FFh;\r
+;       function select register to "move";\r
+;       write mode to 00h.\r
+; Note:\r
+;       this is for internal use only.\r
+;\r
+mxLoadLatches   PROC    NEAR\r
+        ASSUME  ds:NOTHING\r
+\r
+        .push   ds, si\r
+        mov     dx, GDC\r
+        mov     ax, 0FF08h\r
+        out     dx, ax                  ; Set bit mask to FFh\r
+        mov     ax, 0003h\r
+        out     dx, ax                  ; Set function to "move"\r
+        mov     ax, 0005h\r
+        out     dx, ax                  ; Set write mode\r
+        mov     ax, [mx_VideoSegment]\r
+        mov     ds, ax\r
+        mov     si, 0FFFFh\r
+        mov     bh, 8                   ; BH = write plane mask\r
+        mov     cx, 3                   ; CX = count = read plane\r
+; Saves old values and force BL into latches\r
+@@SetLoop:\r
+        mov     dx, GDC\r
+        mov     al, 04h\r
+        mov     ah, cl\r
+        out     dx, ax                  ; Select read plane\r
+        mov     dx, TS\r
+        mov     al, 02h\r
+        mov     ah, bh\r
+        out     dx, ax                  ; Select write plane\r
+        mov     al, ds:[si]\r
+        push    ax\r
+        mov     ds:[si], bl\r
+        mov     al, ds:[di]             ; Force value into latch\r
+        shr     bh, 1                   ; Next write plane\r
+        loop    @@SetLoop\r
+; Restore previous values\r
+        mov     cx, 3\r
+        mov     bh, 8\r
+        mov     dx, TS\r
+@@ResetLoop:\r
+        mov     al, 02h\r
+        mov     ah, bh\r
+        out     dx, ax                  ; Select write plane\r
+        pop     ax\r
+        mov     ds:[si], al\r
+        shr     bh, 1                   ; Next write plane\r
+        loop    @@ResetLoop\r
+; Exit\r
+        .pop    ds, si\r
+        ret\r
+mxLoadLatches   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxln.asm b/16/x_/mxln.asm
new file mode 100755 (executable)
index 0000000..fbc4ab9
--- /dev/null
@@ -0,0 +1,414 @@
+;-----------------------------------------------------------\r
+;\r
+; MXLN.ASM - Line function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+        ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_VideoSegment : WORD\r
+\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+\r
+tblDrawFunc     LABEL   WORD\r
+        DW      subWidthMove\r
+        DW      subHeightMove\r
+        DW      subWidthOp\r
+        DW      subHeightOp\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Draws a line from (X1,Y1) to (X2,Y2) using the Bresenham\r
+; algorithm.\r
+;\r
+; Input:\r
+;       X1, Y1  = start point\r
+;       X2, Y2  = end point\r
+;       Color   = line color\r
+;       Op      = raster operator\r
+; Output:\r
+;       none\r
+;\r
+; Note: the end point (X2,Y2) *IS* drawed. I don't like this very much\r
+; but clipping is much simpler.\r
+;\r
+mxLine  PROC FAR\r
+        ARG     Op:WORD,        \\r
+                Color:WORD,     \\r
+                Y2:WORD,        \\r
+                X2:WORD,        \\r
+                Y1:WORD,        \\r
+                X1:WORD         = ARG_SIZE\r
+        LOCAL   Width:WORD,     \\r
+                Height:WORD,    \\r
+                ErrorAdd:WORD,  \\r
+                ErrorSub:WORD,  \\r
+                DeltaX:WORD,    \\r
+                DeltaY:WORD,    \\r
+                P1:BYTE,        \\r
+                P2:BYTE,        \\r
+                WritePlane:BYTE = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, di\r
+        ASSUME  ds:NOTHING\r
+\r
+        mov     ax, [X1]\r
+        mov     bx, [Y1]\r
+        mov     cx, [X2]\r
+        mov     dx, [Y2]\r
+        call    subClipLine\r
+        jc      @@Exit                  ; Line is full clipped\r
+\r
+; Get width\r
+        mov     si, cx\r
+        xchg    ax, si                  ; SI = X1, AX = X2\r
+        sub     ax, si\r
+        jge     @@1\r
+; Swap points, we want X1 < X2\r
+        xchg    si, cx                  ; Swap X1 and X2\r
+        xchg    bx, dx                  ; Swap Y1 and Y2\r
+        neg     ax\r
+@@1:\r
+        mov     [Width], ax\r
+\r
+; Get height\r
+        mov     cx, [mx_BytesPerLine]   ; We don't need X2 anymore\r
+        mov     ax, dx\r
+        sub     ax, bx\r
+        jge     @@2\r
+        neg     cx                      ; Move from bottom to top\r
+        neg     ax                      ; Get absolute value of AX\r
+@@2:\r
+        mov     [Height], ax\r
+        mov     [DeltaY], cx\r
+\r
+; Get pixel address and write plane\r
+        mov     ax, bx\r
+        mul     [mx_BytesPerLine]\r
+        mov     cx, si                  ; CX = X1\r
+        shr     si, 1\r
+        shr     si, 1\r
+        add     si, ax                  ; SI = pixel offset\r
+        and     cl, 03h\r
+        mov     ax, 1102h\r
+        shl     ah, cl\r
+        mov     [WritePlane], ah\r
+        mov     dx, TS\r
+        out     dx, ax                  ; Set write plane\r
+        mov     ax, [mx_VideoSegment]\r
+        mov     ds, ax                  ; DS:SI points to (X1,Y1)\r
+\r
+; Select the function to handle the drawing loop\r
+        xor     bx, bx\r
+        mov     al, BYTE PTR [Op]\r
+        cmp     al, OP_MOVE\r
+        je      @@3\r
+        and     al, 03h\r
+        shl     al, 1\r
+        shl     al, 1\r
+        shl     al, 1\r
+        mov     ah, al\r
+        mov     al, 03h\r
+        mov     dx, GDC\r
+        out     dx, ax                  ; Set logical function\r
+        inc     bx\r
+        inc     bx\r
+@@3:\r
+        mov     ax, [Width]\r
+        mov     cx, [Height]\r
+; Horizontal, vertical and diagonal lines are not optimized yet\r
+        cmp     ax, cx\r
+        jae     @@4\r
+        inc     bx\r
+@@4:\r
+        shl     bx, 1\r
+        call    tblDrawFunc[bx]\r
+\r
+; Reset logical function if needed\r
+        cmp     BYTE PTR [Op], OP_MOVE\r
+        je      @@Exit\r
+        mov     ax, 0003h\r
+        mov     dx, GDC\r
+        out     dx, ax\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, di\r
+        .leave  ARG_SIZE\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Checks the coordinates of a line against the active\r
+; clip region.\r
+; Uses a variation of the Cohen-Sutherland algorithm developed\r
+; by Victor Duvanenko.\r
+;\r
+; Input:\r
+;       AX, BX  = X1, Y1\r
+;       CX, DX  = X2, Y2\r
+; Output:\r
+;       CF      = set if line is full clipped\r
+;       AX, BX  = clipped X1, Y1\r
+;       CX, DX  = clipped X2, Y2\r
+; Note:\r
+;       destroys SI, DI\r
+;\r
+subClipLine     PROC    NEAR\r
+        mov     di, ax                  ; Copy X1 to DI and free AX\r
+        mov     si, dx                  ; Copy Y2 to SI and free DX\r
+; Compute clip codes for point (X2,Y2)=(CX,SI)\r
+        xor     al, al\r
+@@P2X1: cmp     cx, [mx_ClipX1]\r
+        jge     @@P2X2\r
+        or      al, 1\r
+@@P2X2: cmp     cx, [mx_ClipX2]\r
+        jle     @@P2Y1\r
+        or      al, 2\r
+@@P2Y1: cmp     si, [mx_ClipY1]\r
+        jge     @@P2Y2\r
+        or      al, 4\r
+@@P2Y2: cmp     si, [mx_ClipY2]\r
+        jle     @@P2XY\r
+        or      al, 8\r
+@@P2XY: mov     [P2], al\r
+; Compute clip codes for point (X1,Y1)=(DI,BX)\r
+        xor     al, al\r
+@@P1X1: cmp     di, [mx_ClipX1]\r
+        jge     @@P1X2\r
+        or      al, 1\r
+@@P1X2: cmp     di, [mx_ClipX2]\r
+        jle     @@P1Y1\r
+        or      al, 2\r
+@@P1Y1: cmp     bx, [mx_ClipY1]\r
+        jge     @@P1Y2\r
+        or      al, 4\r
+@@P1Y2: cmp     bx, [mx_ClipY2]\r
+        jle     @@P1XY\r
+        or      al, 8\r
+@@P1XY: mov     [P1], al\r
+; Check codes for trivial cases\r
+        mov     ah, [P2]\r
+        test    al, ah                  ; Is line invisible?\r
+        jnz     @@FullClip              ; Yes, exit\r
+        or      ah, al                  ; Both points clipped?\r
+        jz      @@Done                  ; Yes, exit\r
+; Calculate deltas\r
+        mov     ax, cx\r
+        sub     ax, di\r
+        mov     [DeltaX], ax\r
+        mov     ax, si\r
+        sub     ax, bx\r
+        mov     [DeltaY], ax\r
+        mov     al, [P1]                ; Init clipping code\r
+; Clipping loop\r
+@@ClipLoop:\r
+        test    al, al                  ; Is first point clipped?\r
+        jnz     @@ClipX1                ; No, continue\r
+        xchg    cx, di                  ; Swap points...\r
+        xchg    bx, si\r
+        xchg    al, [P2]                ; ...and codes\r
+; Clip left: Y1 = Y1 + DeltaY*(mx_ClipX1-X1)/DeltaX\r
+@@ClipX1:\r
+        test    al, 1\r
+        jz      @@ClipX2\r
+        mov     ax, [mx_ClipX1]\r
+        sub     ax, di\r
+        mov     di, [mx_ClipX1]\r
+        jmp     @@ClipX1X2\r
+; Clip right: Y1 = Y1 + DeltaY*(mx_ClipX2-X1)/DeltaX\r
+@@ClipX2:\r
+        test    al, 2\r
+        jz      @@ClipY1\r
+        mov     ax, [mx_ClipX2]\r
+        sub     ax, di\r
+        mov     di, [mx_ClipX2]\r
+@@ClipX1X2:\r
+        imul    [DeltaY]\r
+        idiv    [DeltaX]\r
+        add     bx, ax\r
+        mov     al, 8\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      @@CheckLoop\r
+        mov     al, 4\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      @@CheckLoop\r
+        xor     al, al\r
+        jmp     @@CheckLoop\r
+; Clip top: X1 = X1 + DeltaX*(mx_ClipY1-Y1)/DeltaY\r
+@@ClipY1:\r
+        test    al, 4\r
+        jz      @@ClipY2\r
+        mov     ax, [mx_ClipY1]\r
+        sub     ax, bx\r
+        mov     bx, [mx_ClipY1]\r
+        jmp     @@ClipY1Y2\r
+; Clip bottom: X1 = X1 + DeltaX*(mx_ClipY2-Y1)/DeltaY\r
+@@ClipY2:\r
+        mov     ax, [mx_ClipY2]\r
+        sub     ax, bx\r
+        mov     bx, [mx_ClipY2]\r
+@@ClipY1Y2:\r
+        imul    [DeltaX]\r
+        idiv    [DeltaY]\r
+        add     di, ax\r
+        mov     al, 1\r
+        cmp     di, [mx_ClipX1]\r
+        jl      @@CheckLoop\r
+        mov     al, 2\r
+        cmp     di, [mx_ClipX2]\r
+        jg      @@CheckLoop\r
+        xor     al, al\r
+@@CheckLoop:\r
+        mov     ah, [P2]\r
+        test    al, ah\r
+        jnz     @@FullClip\r
+        or      ah, al\r
+        jnz     @@ClipLoop\r
+\r
+@@Done:\r
+        mov     ax, di\r
+        mov     dx, si\r
+        clc\r
+        ret\r
+@@FullClip:\r
+        stc\r
+        ret\r
+subClipLine     ENDP\r
+\r
+; Called when Width >= Height and Op = OP_MOVE\r
+subWidthMove    PROC NEAR\r
+        mov     di, ax\r
+        neg     di                      ; Initialize error term\r
+        shl     cx, 1\r
+        mov     [ErrorAdd], cx\r
+        mov     cx, ax\r
+        shl     ax, 1\r
+        mov     [ErrorSub], ax\r
+        mov     al, 02h\r
+        mov     ah, [WritePlane]\r
+        mov     bl, BYTE PTR [Color]\r
+        mov     dx, TS\r
+        inc     cx\r
+@@Loop:\r
+        mov     ds:[si], bl\r
+        dec     cx\r
+        jz      @@Exit\r
+        rol     ah, 1\r
+        adc     si, 0\r
+        out     dx, ax\r
+        add     di, [ErrorAdd]\r
+        jl      @@Loop\r
+        add     si, [DeltaY]\r
+        sub     di, [ErrorSub]\r
+        jmp     @@Loop\r
+@@Exit:\r
+        ret\r
+subWidthMove    ENDP\r
+\r
+; Called when Width < Height and Op = OP_MOVE\r
+subHeightMove   PROC NEAR\r
+        mov     di, cx\r
+        neg     di                      ; Initialize error term\r
+        shl     ax, 1\r
+        mov     [ErrorAdd], ax\r
+        mov     ax, cx\r
+        shl     ax, 1\r
+        mov     [ErrorSub], ax\r
+        mov     bl, BYTE PTR [Color]\r
+        mov     ah, [WritePlane]\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        inc     cx\r
+@@Loop:\r
+        mov     ds:[si], bl\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, [DeltaY]\r
+        add     di, [ErrorAdd]\r
+        jl      @@Loop\r
+        rol     ah, 1                   ; Next write plane\r
+        adc     si, 0                   ; Bump video offset if plane overflows\r
+        out     dx, ax\r
+        sub     di, [ErrorSub]          ; Adjust error down\r
+        jmp     @@Loop\r
+@@Exit:\r
+        ret\r
+subHeightMove   ENDP\r
+\r
+; Called when Width >= Height and Op <> OP_MOVE\r
+subWidthOp      PROC NEAR\r
+        mov     di, ax\r
+        neg     di                      ; Initialize error term\r
+        shl     cx, 1\r
+        mov     [ErrorAdd], cx\r
+        mov     cx, ax\r
+        shl     ax, 1\r
+        mov     [ErrorSub], ax\r
+        mov     al, 02h\r
+        mov     ah, [WritePlane]\r
+        mov     bl, BYTE PTR [Color]\r
+        mov     dx, TS\r
+        inc     cx\r
+@@Loop:\r
+        mov     bh, ds:[si]             ; Latch data\r
+        mov     ds:[si], bl\r
+        dec     cx\r
+        jz      @@Exit\r
+        rol     ah, 1\r
+        adc     si, 0\r
+        out     dx, ax\r
+        add     di, [ErrorAdd]\r
+        jl      @@Loop\r
+        add     si, [DeltaY]\r
+        sub     di, [ErrorSub]\r
+        jmp     @@Loop\r
+@@Exit:\r
+        ret\r
+subWidthOp      ENDP\r
+\r
+; Called when Width < Height and Op <> OP_MOVE\r
+subHeightOp     PROC NEAR\r
+        mov     di, cx\r
+        neg     di                      ; Initialize error term\r
+        shl     ax, 1\r
+        mov     [ErrorAdd], ax\r
+        mov     ax, cx\r
+        shl     ax, 1\r
+        mov     [ErrorSub], ax\r
+        mov     bl, BYTE PTR [Color]\r
+        mov     ah, [WritePlane]\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        inc     cx\r
+@@Loop:\r
+        mov     bh, ds:[si]\r
+        mov     ds:[si], bl\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, [DeltaY]\r
+        add     di, [ErrorAdd]\r
+        jl      @@Loop\r
+        rol     ah, 1                   ; Next write plane\r
+        adc     si, 0                   ; Bump video offset if plane overflows\r
+        out     dx, ax\r
+        sub     di, [ErrorSub]          ; Adjust error down\r
+        jmp     @@Loop\r
+@@Exit:\r
+        ret\r
+subHeightOp     ENDP\r
+\r
+mxLine  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxot.asm b/16/x_/mxot.asm
new file mode 100755 (executable)
index 0000000..6254766
--- /dev/null
@@ -0,0 +1,330 @@
+;-----------------------------------------------------------\r
+;\r
+; MXOT.ASM - Text functions\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES                             ; We use the reserved name 'WIDTH'\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxOutChar\r
+PUBLIC  mxOutText\r
+PUBLIC  mxSetFont\r
+PUBLIC  mxSetTextColor\r
+PUBLIC  mxGetTextStep\r
+PUBLIC  mxSetTextStep\r
+\r
+MAX_WIDTH       EQU     16              ; Must be <= 16\r
+MAX_HEIGHT      EQU     32\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_CodeSegment  : WORD\r
+EXTRN   mxPutImage      : FAR\r
+\r
+; Default 8x8 font\r
+fnt_Default     LABEL\r
+        INCLUDE DEFAULT.FNT\r
+\r
+; Table of system fonts\r
+tbl_SystemFont   LABEL   WORD\r
+        DW      fnt_Default, 8, 8\r
+\r
+MX_MAXSYSFONT   EQU     ($-OFFSET tbl_SystemFont) SHR 2\r
+\r
+mx_FontPtr      DW      OFFSET fnt_Default, SEG MX_TEXT\r
+mx_FontWidth    DW      8               ; Font width in pixels\r
+mx_FontHeight   DW      8               ; Font height in pixels\r
+mx_FontCharSize DW      8               ; Size in bytes of a font character\r
+mx_FontColor    DW      00FFh           ; Color: foreground + background*256\r
+mx_FontOp       DW      OP_MOVE         ; Raster op\r
+mx_DeltaX       DW      8               ; Horizontal step\r
+mx_DeltaY       DW      0               ; Vertical step\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the current font.\r
+;\r
+; Input:\r
+;       Font    = pointer to font data\r
+;       Width   = width of font character in pixels\r
+;       Height  = height of font character in pixels\r
+; Output:\r
+;       AX = 0 on success, else invalid parameters\r
+;\r
+; Note: when the high word of Font (i.e. the segment) is zero, the low\r
+;       word is used to select one of the system fonts.\r
+;\r
+mxSetFont       PROC FAR\r
+        ARG     Height:WORD,    \\r
+                Width:WORD,     \\r
+                Font:DWORD      = ARG_SIZE\r
+        .enter  0\r
+        .push   ds\r
+\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, WORD PTR Font[2]    ; Get font segment\r
+        test    ax, ax                  ; Null segment?\r
+        jnz     @@UserFont              ; No, install user font\r
+\r
+; Install system font\r
+        mov     ax, WORD PTR Font[0]    ; Get font number\r
+        cmp     ax, MX_MAXSYSFONT       ; Check range\r
+        jb      @@SystemFont\r
+        xor     ax, ax                  ; Out of range, use default font\r
+@@SystemFont:\r
+        shl     ax, 1\r
+        shl     ax, 1\r
+        mov     bx, ax\r
+        mov     ax, tbl_SystemFont[bx]  ; Get font offset\r
+        mov     WORD PTR mx_FontPtr[0], ax\r
+        mov     WORD PTR mx_FontPtr[2], cs\r
+        mov     al, BYTE PTR tbl_SystemFont[bx+2]\r
+        xor     ah, ah\r
+        mov     [mx_FontWidth], ax\r
+        mov     [mx_DeltaX], ax\r
+        mov     dl, BYTE PTR tbl_SystemFont[bx+3]\r
+        xor     dh, dh\r
+        mov     [mx_FontHeight], dx\r
+        mul     dx\r
+        mov     [mx_FontCharSize], ax\r
+        mov     [mx_DeltaX], ax\r
+        xor     ax, ax\r
+        mov     [mx_DeltaY], ax\r
+        jmp     @@Exit\r
+\r
+; Install user font\r
+@@UserFont:\r
+        mov     ax, -1                  ; Assume an error\r
+        mov     bx, [Width]\r
+        cmp     bx, MAX_WIDTH\r
+        ja      @@Exit                  ; Invalid character width\r
+        mov     dx, [Height]\r
+        cmp     dx, MAX_HEIGHT\r
+        ja      @@Exit                  ; Invalid character height\r
+        mov     [mx_FontWidth], bx\r
+        mov     [mx_FontHeight], dx\r
+        mov     ax, bx\r
+        add     ax, 7\r
+        .shr    ax, 3\r
+        mul     dx\r
+        mov     [mx_FontCharSize], ax\r
+        mov     ax, WORD PTR Font[0]\r
+        mov     WORD PTR mx_FontPtr[0], ax\r
+        mov     ax, WORD PTR Font[2]\r
+        mov     WORD PTR mx_FontPtr[2], ax\r
+        xor     ax, ax\r
+\r
+@@Exit:\r
+        .pop    ds\r
+        ASSUME  ds:NOTHING\r
+        .leave  ARG_SIZE\r
+mxSetFont       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the text color and raster op.\r
+;\r
+; Input:\r
+;       Color   = text color (foreground + background*256)\r
+;       Op      = raster op\r
+; Output:\r
+;       none\r
+;\r
+mxSetTextColor  PROC FAR\r
+        ARG     Op:WORD,        \\r
+                Color:WORD      = ARG_SIZE\r
+        .enter  0\r
+        .push   ds\r
+\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, [Color]\r
+        mov     [mx_FontColor], ax\r
+        mov     ax, [Op]\r
+        mov     [mx_FontOp], ax\r
+\r
+        xor     ax, ax\r
+        .pop    ds\r
+        ASSUME  ds:NOTHING\r
+        .leave  ARG_SIZE\r
+mxSetTextColor  ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a character using the current font and attributes.\r
+;\r
+; Input:\r
+;       X, Y    = video coordinates\r
+;       C       = character to print\r
+; Output:\r
+;       none\r
+;\r
+mxOutChar       PROC FAR\r
+        ARG     C:BYTE:2,       \\r
+                Y:WORD,         \\r
+                X:WORD          = ARG_SIZE\r
+        LOCAL   Image:BYTE:MAX_WIDTH*MAX_HEIGHT,        \\r
+                Count:WORD                              = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+        ASSUME  ds:NOTHING\r
+\r
+; Gets the pointer to font data for the selected character\r
+        lds     si, DWORD PTR [mx_FontPtr]\r
+        mov     al, [C]\r
+        xor     ah, ah\r
+        mul     [mx_FontCharSize]       ; Offset into font\r
+        add     si, ax                  ; DS:SI -> font data for character\r
+\r
+; Converts font data into a 256-color linear image\r
+        mov     ax, ss\r
+        mov     es, ax\r
+        lea     di, [Image]\r
+        mov     dx, [mx_FontColor]\r
+        mov     ax, [mx_FontHeight]\r
+        mov     [Count], ax\r
+@@HeightLoop:\r
+        mov     cx, [mx_FontWidth]\r
+        mov     bh, ds:[si]\r
+        inc     si                      ; Get a byte from font data\r
+        cmp     cx, 8\r
+        jbe     @@WidthLoop             ; Ok for width <= 8\r
+        mov     bl, ds:[si]             ; Get another byte\r
+        inc     si\r
+@@WidthLoop:\r
+        mov     al, dl                  ; Assume foreground color\r
+        shl     bx, 1                   ; Is font bit set?\r
+        jc      @@1                     ; Yes, foreground is just great\r
+        mov     al, dh                  ; Get background color\r
+@@1:\r
+        mov     es:[di], al             ; Put pixel into image\r
+        inc     di\r
+        dec     cx\r
+        jnz     @@WidthLoop\r
+        dec     [Count]\r
+        jnz     @@HeightLoop\r
+\r
+; Now pass image to mx_PutImage\r
+        lea     ax, [Image]\r
+        push    es\r
+        push    ax                      ; Pointer to image\r
+        push    [X]\r
+        push    [Y]                     ; Image coordinates\r
+        push    [mx_FontWidth]\r
+        push    [mx_FontHeight]         ; Image size\r
+        push    [mx_FontOp]             ; Raster op\r
+        call    mxPutImage              ; Write character\r
+\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxOutChar       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a string at the coordinates specified.\r
+;\r
+; Input:\r
+;       X, Y    = text coordinates\r
+;       S       = pointer to ASCIIZ string\r
+; Output:\r
+;       none\r
+;\r
+mxOutText       PROC FAR\r
+        ARG     S:DWORD,        \\r
+                Y:WORD,         \\r
+                X:WORD          = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+        ASSUME  ds:NOTHING\r
+\r
+        lds     si, [S]\r
+@@Loop:\r
+        mov     al, ds:[si]\r
+        test    al, al                  ; End of string?\r
+        jz      @@Exit                  ; Yes, exit\r
+        inc     si\r
+        push    [X]                     ; Display character\r
+        push    [Y]\r
+        push    ax\r
+        call    mxOutChar\r
+        mov     ax, [mx_DeltaX]\r
+        add     [X], ax                 ; Bump X coordinate\r
+        mov     ax, [mx_DeltaY]\r
+        add     [Y], ax                 ; Bump Y coordinate\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+        ret\r
+mxOutText       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the distance between characters.\r
+;\r
+; Input:\r
+;       DeltaX  = horizontal distance in pixels\r
+;       DeltaY  = vertical distance in pixels\r
+; Output:\r
+;       none\r
+;\r
+; Note: this function may be used to set the text direction.\r
+;\r
+mxSetTextStep   PROC FAR\r
+        ARG     DeltaY:WORD,    \\r
+                DeltaX:WORD     = ARG_SIZE\r
+        .enter  0\r
+        .push   ds\r
+\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, [DeltaX]\r
+        mov     [mx_DeltaX], ax\r
+        mov     ax, [DeltaY]\r
+        mov     [mx_DeltaY], ax\r
+\r
+        .pop    ds\r
+        .leave  ARG_SIZE\r
+mxSetTextStep   ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Gets the current distance between characters.\r
+;\r
+; Input:\r
+;       DeltaX  = pointer to horizontal distance in pixels (integer)\r
+;       DeltaY  = pointer to vertical distance in pixels (integer)\r
+; Output:\r
+;       none\r
+;\r
+mxGetTextStep   PROC FAR\r
+        ARG     DeltaY:DWORD,   \\r
+                DeltaX:DWORD    = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+        ASSUME  ds:NOTHING\r
+\r
+        mov     ax, [mx_DeltaX]\r
+        lds     si, [DeltaX]\r
+        mov     ds:[si], ax\r
+        mov     ax, [mx_DeltaY]\r
+        lds     si, [DeltaY]\r
+        mov     ds:[si], ax\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetTextStep   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxpb.asm b/16/x_/mxpb.asm
new file mode 100755 (executable)
index 0000000..8c6aa44
--- /dev/null
@@ -0,0 +1,22 @@
+;-----------------------------------------------------------\r
+;\r
+; MXPB.ASM - Scan buffer for convex polygon fills\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mx_ScanBuffer\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+ALIGN   4\r
+\r
+mx_ScanBuffer   LABEL\r
+        DW      POLYSCANBUFSIZE DUP(?)\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxpf.asm b/16/x_/mxpf.asm
new file mode 100755 (executable)
index 0000000..db0da89
--- /dev/null
@@ -0,0 +1,420 @@
+;-----------------------------------------------------------\r
+;\r
+; MXPG.ASM - Convex polygon fill\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxFillPoly\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; "Local" definitions\r
+;\r
+TPOINT  STRUC\r
+        X       DW      ?\r
+        Y       DW      ?\r
+TPOINT  ENDS\r
+\r
+; Do NOT change order!\r
+TSCAN   STRUC\r
+        Y1      DW      ?\r
+        Y2      DW      ?\r
+TSCAN   ENDS\r
+\r
+MAXSCANCOLUMNS  EQU     POLYSCANBUFSIZE / SIZE TSCAN\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_CodeSegment  : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+EXTRN   mx_ScanBuffer   : NEAR\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Scans an edge using the DDA (digital differential analyzer) algorithm.\r
+;\r
+; Input:\r
+;       DS:BX   = pointer to start point (X1, Y1)\r
+;       DS:SI   = pointer to end point (X2, Y2)\r
+;       ES:DI   = pointer to edge buffer\r
+; Output:\r
+;       ES:DI   = updated pointer to edge buffer\r
+; Notes:\r
+;       must preserve DS:SI.\r
+;\r
+subScan         PROC NEAR\r
+        mov     cx, ds:[si].X\r
+        sub     cx, ds:[bx].X           ; Get width\r
+        jg      @@1\r
+        ret\r
+@@1:\r
+        push    bp                      ; Save BP\r
+\r
+        mov     ax, ds:[si].Y\r
+        mov     bx, ds:[bx].Y\r
+        sub     ax, bx                  ; Get height\r
+        jg      @@T2B                   ; Scan top to bottom\r
+        jl      @@B2T                   ; Scan bottom to top\r
+\r
+; Special case: vertical line\r
+        mov     ax, bx\r
+@@V:\r
+        mov     es:[di].Y1, ax\r
+        add     di, SIZE TSCAN\r
+        dec     cx\r
+       jnz     @@V\r
+        jmp     @@Exit\r
+\r
+; Scan top to bottom\r
+@@T2B:\r
+        cwd\r
+        div     cx\r
+        mov     bp, ax\r
+        xor     ax, ax\r
+        div     cx\r
+        xchg    ax, bx                  ; BP:BX = fixed 16:16 step\r
+        mov     dx, 8000h\r
+@@T2BLoop:\r
+        mov     es:[di].Y1, ax\r
+        add     di, SIZE TSCAN\r
+        add     dx, bx\r
+        adc     ax, bp\r
+        dec     cx\r
+        jnz     @@T2BLoop\r
+        jmp     @@Exit\r
+\r
+; Scan bottom to top\r
+@@B2T:\r
+        neg     ax\r
+        cwd\r
+        div     cx\r
+        mov     bp, ax\r
+        xor     ax, ax\r
+        div     cx\r
+        xchg    ax, bx\r
+        mov     dx, 8000h\r
+@@B2TLoop:\r
+        mov     es:[di].Y1, ax\r
+        add     di, SIZE TSCAN\r
+        sub     dx, bx\r
+        sbb     ax, bp\r
+        dec     cx\r
+        jnz     @@B2TLoop\r
+\r
+@@Exit:\r
+        pop     bp                      ; Restore BP\r
+        ret\r
+subScan         ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a convex polygon with the specified color.\r
+;\r
+; Input:\r
+;       Count   = number of vertexes\r
+;       Map     = indexes of points and colors (integer)\r
+;       Points  = array of points (integer X, Y coordinates)\r
+;       Color   = base color\r
+; Output:\r
+;       none\r
+; Notes:\r
+;       vertexes must be in counterclockwise order, arrays are 0-based.\r
+;\r
+mxFillPoly      PROC FAR\r
+        ARG     Color:WORD,     \\r
+                Points:DWORD,   \\r
+                Map:DWORD,      \\r
+                Count:WORD      = ARG_SIZE\r
+        LOCAL   WritePlane:BYTE:2,      \\r
+                ScanOffsetT:WORD,       \\r
+                ScanOffsetB:WORD,       \\r
+                ScanCount:WORD,         \\r
+                Holder:WORD,            \\r
+                Height:WORD,            \\r
+                MinIdxT:WORD,           \\r
+                MinIdxB:WORD,           \\r
+                MaxIdx:WORD,            \\r
+                Width:WORD,             \\r
+                BoxX1:WORD,             \\r
+                BoxY1:WORD,             \\r
+                BoxX2:WORD,             \\r
+                BoxY2::WORD             = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+        ASSUME  ds:NOTHING\r
+\r
+; Check that at least three vertexes are specified\r
+        mov     cx, [Count]\r
+        cmp     cx, 3\r
+        jb      @@Exit\r
+\r
+;------------------------------\r
+; Find bounding box for polygon\r
+        les     di, [Map]\r
+        lds     si, [Points]            ; Pointer to vertex array\r
+        mov     [BoxX1], 32767\r
+        mov     [BoxX2], -32768\r
+        mov     [BoxY1], 32767\r
+        mov     [BoxY2], -32768\r
+\r
+        xor     dx, dx\r
+@@MinMaxLoop:\r
+        mov     bx, es:[di]             ; Get index of vertex\r
+        .shl    bx, 2                   ; Get offset in point array\r
+        add     bx, si\r
+\r
+; Check X range\r
+@@CheckMinX:\r
+        mov     ax, ds:[bx].X           ; Get X coordinate\r
+        cmp     ax, [BoxX1]\r
+        jge     @@CheckMaxX\r
+        mov     [BoxX1], ax\r
+        mov     [MinIdxT], dx\r
+        mov     [MinIdxB], dx\r
+@@CheckMaxX:\r
+        cmp     ax, [BoxX2]\r
+        jle     @@CheckMinY\r
+        mov     [BoxX2], ax\r
+        mov     [MaxIdx], dx\r
+\r
+; Check Y range\r
+@@CheckMinY:\r
+        mov     ax, ds:[bx].Y\r
+        cmp     ax, [BoxY1]\r
+        jge     @@CheckMaxY\r
+        mov     [BoxY1], ax\r
+@@CheckMaxY:\r
+        cmp     ax, [BoxY2]\r
+        jle     @@CheckDone\r
+        mov     [BoxY2], ax\r
+\r
+; Repeat thru all points\r
+@@CheckDone:\r
+        inc     di                      ; Next map entry\r
+        inc     dx\r
+        inc     di\r
+        inc     dx\r
+        dec     cx\r
+        jnz     @@MinMaxLoop\r
+\r
+;---------------------------------\r
+; Check if polygon is full clipped\r
+        mov     ax, [BoxX2]\r
+        cmp     ax, [mx_ClipX1]         ; Is poly full clipped?\r
+        jl      @@Exit\r
+        mov     bx, [BoxX1]\r
+        cmp     bx, [mx_ClipX2]         ; Is poly full clipped?\r
+        jg      @@Exit\r
+        sub     ax, bx                  ; Get width\r
+        jle     @@Exit                  ; Exit if not positive\r
+        mov     ax, [BoxY2]\r
+        cmp     ax, [mx_ClipY1]         ; Is poly full clipped?\r
+        jl      @@Exit\r
+        mov     bx, [BoxY1]\r
+        cmp     bx, [mx_ClipY2]         ; Is poly full clipped?\r
+        jg      @@Exit\r
+        sub     ax, bx                  ; Get height\r
+        jle     @@Exit                  ; Exit if not positive\r
+\r
+        dec     [Count]\r
+        shl     [Count], 1              ; We'll work with word offsets\r
+        mov     es, [mx_CodeSegment]\r
+\r
+;--------------\r
+; Scan top edge\r
+        mov     ax, OFFSET mx_ScanBuffer\r
+        mov     [ScanOffsetT], ax\r
+        mov     si, [MinIdxT]           ; Offset of bottom point index\r
+@@STLoop:\r
+        lds     bx, [Map]               ; DS:BX -> map table\r
+        mov     di, ds:[bx+si]          ; Index of top point #1\r
+        dec     si                      ; Next point\r
+        dec     si\r
+        test    si, si\r
+        jnl     @@ST1\r
+        mov     si, [Count]\r
+@@ST1:\r
+        mov     [MinIdxT], si           ; Save new index of top point\r
+        mov     si, ds:[bx+si]          ; Get index of top point #2\r
+        .shl    di, 2                   ; Convert indexes to offsets\r
+        .shl    si, 2\r
+        lds     bx, [Points]            ; DS:BX -> point array\r
+        add     si, bx                  ; DS:SI -> top point #2\r
+        add     bx, di                  ; DS:BX -> top point #1\r
+        mov     di, [ScanOffsetT]\r
+        call    subScan                 ; Scan edge\r
+        mov     [ScanOffsetT], di\r
+        mov     si, [MinIdxT]\r
+        cmp     si, [MaxIdx]            ; End of edge?\r
+        jne     @@STLoop                ; No, continue\r
+\r
+;-----------------\r
+; Scan bottom edge\r
+        mov     ax, OFFSET mx_ScanBuffer + OFFSET Y2\r
+        mov     [ScanOffsetB], ax\r
+        mov     si, [MinIdxB]           ; Offset of bottom point index\r
+@@SBLoop:\r
+        lds     bx, [Map]               ; DS:BX -> map table\r
+        mov     di, ds:[bx+si]          ; Index of bottom point #1\r
+        inc     si                      ; Next bottom point\r
+        inc     si\r
+        cmp     si, [Count]\r
+        jbe     @@SB1\r
+        xor     si, si\r
+@@SB1:\r
+        mov     [MinIdxB], si           ; Save new index of bottom point\r
+        mov     si, ds:[bx+si]          ; Get index of bottom point #2\r
+        .shl    di, 2                   ; Convert indexes to offsets\r
+        .shl    si, 2\r
+        lds     bx, [Points]            ; DS:BX -> point array\r
+        add     si, bx                  ; DS:SI -> top point #2\r
+        add     bx, di                  ; DS:BX -> top point #1\r
+        mov     di, [ScanOffsetB]\r
+        call    subScan                 ; Scan edge\r
+        mov     [ScanOffsetB], di\r
+        mov     si, [MinIdxB]\r
+        cmp     si, [MaxIdx]            ; End of edge?\r
+        jne     @@SBLoop                ; No, continue\r
+\r
+;--------------------\r
+; Clip left and right\r
+        mov     si, OFFSET mx_ScanBuffer\r
+        mov     ax, [BoxX1]\r
+        mov     cx, [BoxX2]\r
+        sub     cx, ax                  ; CX = bounding box width\r
+        mov     bx, [mx_ClipX1]\r
+        sub     bx, ax\r
+        jle     @@ClipL1                ; No need to clip left\r
+        sub     cx, bx                  ; Update width\r
+        add     ax, bx                  ; BoxX1 = mx_ClipX1\r
+        mov     [BoxX1], ax\r
+        .shl    bx, 2                   ; Warning!!! This is an hand-coded\r
+        add     si, bx                  ; multiply by the size of TSCAN\r
+@@ClipL1:\r
+        mov     bx, ax\r
+        add     bx, cx                  ; Last scan column\r
+        sub     bx, [mx_ClipX2]\r
+        jle     @@ClipL2                ; No need to clip right\r
+        sub     cx, bx                  ; Clip right\r
+@@ClipL2:\r
+        test    cx, cx                  ; Is clipped width positive?\r
+        jle     @@Exit                  ; No, exit\r
+        mov     [ScanCount], cx         ; Save number of columns to draw\r
+        mov     [ScanOffsetT], si       ; Remember offset of (clipped) buffer\r
+        mov     ds, [mx_CodeSegment]    ; DS:SI -> scan buffer\r
+\r
+;------------------------------\r
+; Check if Y clipping is needed\r
+        mov     ax, [BoxY1]\r
+        cmp     ax, [mx_ClipY1]\r
+        jl      @@ClipTB                ; Need to clip top\r
+        mov     ax, [BoxY2]\r
+        cmp     ax, [mx_ClipY2]\r
+        jg      @@ClipTB                ; Need to clip bottom\r
+        jmp     @@ClipYExit             ; Skip Y clipping\r
+\r
+;--------------------\r
+; Clip top and bottom\r
+@@ClipTB:\r
+        mov     di, cx                  ; DI = scan count\r
+        inc     di                      ; Increment count for pre-loop test\r
+        sub     si, SIZE TSCAN\r
+@@ClipYLoop:\r
+        dec     di                      ; Any column left?\r
+        jz      @@ClipYExit             ; No, exit\r
+        add     si, SIZE TSCAN\r
+        mov     ax, ds:[si].Y1          ; Y1\r
+        mov     cx, ds:[si].Y2          ; Y2\r
+        mov     dx, [mx_ClipY2]\r
+        cmp     ax, dx                  ; Full clipped?\r
+        jg      @@ClipYClip             ; Yes, skip this column\r
+        cmp     cx, dx                  ; Need to clip bottom?\r
+        jle     @@ClipY1                ; No, continue\r
+; Clip bottom\r
+        mov     ds:[si].Y2, dx\r
+        mov     bx, cx\r
+        sub     bx, dx                  ; Clip distance\r
+        sub     cx, ax                  ; Height\r
+        jle     @@ClipYClip\r
+        mov     cx, ds:[si].Y2\r
+@@ClipY1:\r
+        mov     dx, [mx_ClipY1]\r
+        cmp     cx, dx                  ; Full top clipped?\r
+        jl      @@ClipYClip             ; Yes, skip\r
+        sub     cx, ax                  ; Get height\r
+        jle     @@ClipYClip             ; Skip if not positive\r
+        cmp     ax, dx                  ; Need to clip top?\r
+        jge     @@ClipYLoop             ; No, continue\r
+; Clip top\r
+        mov     ds:[si].Y1, dx          ; Y1 = mx_ClipY1\r
+        sub     dx, ax                  ; DX = number of pixels clipped\r
+        cmp     cx, dx\r
+        ja      @@ClipYLoop             ; Not clipped, continue\r
+@@ClipYClip:\r
+        mov     ds:[si].Y1, -1          ; Mark column as clipped\r
+        jmp     @@ClipYLoop\r
+@@ClipYExit:\r
+\r
+;-------------\r
+; Draw columns\r
+        mov     es, [mx_VideoSegment]\r
+        mov     si, [ScanOffsetT]\r
+        mov     cl, BYTE PTR [BoxX1]    ; Init write plane\r
+        and     cl, 03h\r
+        mov     al, 11h\r
+        shl     al, cl\r
+        mov     [WritePlane], al\r
+        .shr    [BoxX1], 2\r
+@@DrawLoop:\r
+        mov     ax, ds:[si].Y1\r
+        test    ax, ax                  ; Was column clipped?\r
+        js      @@DrawNext              ; Yes, skip\r
+        mov     cx, ds:[si].Y2\r
+        sub     cx, ax                  ; CX = height\r
+        jle     @@DrawNext\r
+        mul     [mx_BytesPerLine]       ; Get pixel address\r
+        add     ax, [BoxX1]\r
+        mov     di, ax\r
+        mov     ah, [WritePlane]\r
+        mov     dx, TS\r
+        mov     al, 02h\r
+        out     dx, ax\r
+        mov     ax, [Color]\r
+        mov     dx, [mx_BytesPerLine]\r
+        shr     cx, 1\r
+        jnc     @@FillScan\r
+        mov     es:[di], al\r
+        add     di, dx\r
+        jcxz    @@DrawNext\r
+@@FillScan:\r
+        mov     es:[di], al\r
+        add     di, dx\r
+        mov     es:[di], al\r
+        add     di, dx\r
+        dec     cx\r
+        jnz     @@FillScan\r
+@@DrawNext:\r
+        rol     [WritePlane], 1\r
+        adc     [BoxX1], 0              ; Bump pointer to video memory if needed\r
+        add     si, SIZE TSCAN\r
+        dec     [ScanCount]\r
+        jnz     @@DrawLoop\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxFillPoly      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxpg.asm b/16/x_/mxpg.asm
new file mode 100755 (executable)
index 0000000..caa7cf1
--- /dev/null
@@ -0,0 +1,589 @@
+;-----------------------------------------------------------\r
+;\r
+; MXPG.ASM - Convex polygon fill with Gouraud shading\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxGouraudPoly\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; "Local" definitions\r
+;\r
+TPOINT  STRUC\r
+        X       DW      ?\r
+        Y       DW      ?\r
+TPOINT  ENDS\r
+\r
+; Do NOT change order!\r
+TSCAN   STRUC\r
+        Y1      DW      ?\r
+        E1      DB      ?\r
+        C1      DB      ?\r
+        Y2      DW      ?\r
+        E2      DB      ?\r
+        C2      DB      ?\r
+TSCAN   ENDS\r
+\r
+MAXSCANCOLUMNS  EQU     POLYSCANBUFSIZE / SIZE TSCAN\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_CodeSegment  : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+EXTRN   mx_ScanBuffer   : NEAR\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Scans an edge using the DDA (digital differential analyzer) algorithm.\r
+; Also interpolates color for shading.\r
+;\r
+; Input:\r
+;       DS:BX   = pointer to start point (X1, Y1)\r
+;       DS:SI   = pointer to end point (X2, Y2)\r
+;       ES:DI   = pointer to edge buffer\r
+;       DX      = start color\r
+;       AX      = end color\r
+; Output:\r
+;       ES:DI   = updated pointer to edge buffer\r
+; Notes:\r
+;       must preserve DS:SI.\r
+;\r
+subScan         PROC NEAR\r
+        mov     cx, ds:[si].X\r
+        sub     cx, ds:[bx].X           ; Get width\r
+        jg      @@1\r
+        ret\r
+@@1:\r
+        push    bp                      ; Save BP\r
+        push    di                      ; Save scan info offset\r
+        push    cx                      ; Save height\r
+        push    ax                      ; Save colors\r
+        push    dx\r
+\r
+        mov     ax, ds:[si].Y\r
+        mov     bx, ds:[bx].Y\r
+        sub     ax, bx                  ; Get height\r
+        jg      @@T2B                   ; Scan top to bottom\r
+        jl      @@B2T                   ; Scan bottom to top\r
+\r
+; Special case: vertical line\r
+        mov     ax, bx\r
+@@V:\r
+        mov     es:[di].Y1, ax\r
+        add     di, SIZE TSCAN\r
+        dec     cx\r
+       jnz     @@V\r
+        jmp     @@GetColorInfo\r
+\r
+; Scan top to bottom\r
+@@T2B:\r
+        cwd\r
+        div     cx\r
+        mov     bp, ax\r
+        xor     ax, ax\r
+        div     cx\r
+        xchg    ax, bx                  ; BP:BX = fixed 16:16 step\r
+        mov     dx, 8000h\r
+@@T2BLoop:\r
+        mov     es:[di].Y1, ax\r
+        add     di, SIZE TSCAN\r
+        add     dx, bx\r
+        adc     ax, bp\r
+        dec     cx\r
+        jnz     @@T2BLoop\r
+        jmp     @@GetColorInfo\r
+\r
+; Scan bottom to top\r
+@@B2T:\r
+        neg     ax\r
+        cwd\r
+        div     cx\r
+        mov     bp, ax\r
+        xor     ax, ax\r
+        div     cx\r
+        xchg    ax, bx\r
+        mov     dx, 8000h\r
+@@B2TLoop:\r
+        mov     es:[di].Y1, ax\r
+        add     di, SIZE TSCAN\r
+        sub     dx, bx\r
+        sbb     ax, bp\r
+        dec     cx\r
+        jnz     @@B2TLoop\r
+\r
+; Now get the color info\r
+@@GetColorInfo:\r
+        pop     bx                      ; Restore colors\r
+        pop     ax\r
+        pop     cx                      ; Height\r
+        pop     di                      ; ES:DI -> scan info\r
+\r
+        sub     ax, bx                  ; Get color range\r
+        jg      @@CL2R\r
+        jl      @@CR2L\r
+\r
+; Special case: same color\r
+        mov     ah, bl\r
+        mov     al, 80h\r
+@@CV:\r
+        mov     WORD PTR es:[di].E1, ax\r
+        add     di, SIZE TSCAN\r
+        dec     cx\r
+        jnz     @@CV\r
+        jmp     @@Exit\r
+\r
+; Scan left to right\r
+@@CL2R:\r
+        cwd\r
+        div     cx\r
+        mov     bp, ax\r
+        xor     ax, ax\r
+        div     cx\r
+        xchg    ax, bx                  ; BP:BX = fixed 16:16 step\r
+        mov     dx, 8000h\r
+@@CL2RLoop:\r
+        mov     es:[di].C1, al\r
+        mov     es:[di].E1, dh\r
+        add     di, SIZE TSCAN\r
+        add     dx, bx\r
+        adc     ax, bp\r
+        dec     cx\r
+        jnz     @@CL2RLoop\r
+        jmp     @@Exit\r
+\r
+; Scan right to left\r
+@@CR2L:\r
+        neg     ax\r
+        cwd\r
+        div     cx\r
+        mov     bp, ax\r
+        xor     ax, ax\r
+        div     cx\r
+        xchg    ax, bx\r
+        mov     dx, 8000h\r
+\r
+@@CR2LLoop:\r
+        mov     es:[di].C1, al\r
+        mov     es:[di].E1, dh\r
+        add     di, SIZE TSCAN\r
+        sub     dx, bx\r
+        sbb     ax, bp\r
+        dec     cx\r
+        jnz     @@CR2LLoop\r
+\r
+@@Exit:\r
+        pop     bp\r
+        ret\r
+subScan         ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a scan column.\r
+;\r
+; Input:\r
+;       DS:SI   = current TSCAN\r
+;       ES:DI   = address of top pixel\r
+;       CX      = number of pixels to write\r
+;       DX      = base color\r
+; Output:\r
+;       none\r
+;\r
+subFillScan     PROC NEAR\r
+        mov     ax, WORD PTR ds:[si].E2\r
+        mov     bx, WORD PTR ds:[si].E1\r
+        cmp     ah, bh\r
+        jg      @@L2R                   ; Color increases\r
+        jl      @@R2L                   ; Color decreases\r
+\r
+; Special case: color doesn't change\r
+        add     ax, dx\r
+        mov     dx, [mx_BytesPerLine]\r
+@@V:\r
+        mov     es:[di], ah\r
+        add     di, dx\r
+        dec     cx\r
+        jnz     @@V\r
+        ret\r
+\r
+; Color increases\r
+@@L2R:\r
+        .push   bp, si\r
+        mov     si, bx\r
+        add     si, dx                  ; Relocate color\r
+        sub     ax, bx\r
+        xor     dx, dx\r
+        div     cx\r
+        mov     bp, ax                  ; BP = color step, integer part\r
+        xor     ax, ax\r
+        div     cx\r
+        mov     bx, ax                  ; BX = color step, fractional part\r
+        mov     dx, 8000h\r
+        mov     ax, [mx_BytesPerLine]\r
+        xchg    si, ax\r
+@@L2RLoop:\r
+        mov     es:[di], ah\r
+        add     dx, bx\r
+        adc     ax, bp\r
+        add     di, si\r
+        dec     cx\r
+        jnz     @@L2RLoop\r
+        .pop    bp, si\r
+        ret\r
+\r
+; Color decreases\r
+@@R2L:\r
+        .push   bp, si\r
+        mov     si, bx\r
+        add     si, dx                  ; Relocate color\r
+        sub     ax, bx\r
+        neg     ax\r
+        xor     dx, dx\r
+        div     cx\r
+        mov     bp, ax                  ; BP = color step, integer part\r
+        xor     ax, ax\r
+        div     cx\r
+        mov     bx, ax                  ; BX = color step, fractional part\r
+        mov     dx, 8000h\r
+        mov     ax, [mx_BytesPerLine]\r
+        xchg    si, ax\r
+@@R2LLoop:\r
+        mov     es:[di], ah\r
+        sub     dx, bx\r
+        sbb     ax, bp\r
+        add     di, si\r
+        dec     cx\r
+        jnz     @@R2LLoop\r
+        .pop    bp, si\r
+        ret\r
+subFillScan     ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a convex polygon with the specified color.\r
+; Interpolates pixel colors using the Gouraud algorithm.\r
+;\r
+; Input:\r
+;       Count   = number of vertexes\r
+;       Map     = indexes of points and colors (integer)\r
+;       Points  = array of points (integer X, Y coordinates)\r
+;       Colors  = array of colors (integer)\r
+;       Color   = base color\r
+; Output:\r
+;       none\r
+; Notes:\r
+;       vertexes must be in counterclockwise order, arrays are 0-based.\r
+;\r
+mxGouraudPoly  PROC FAR\r
+        ARG     Color:WORD,     \\r
+                Colors:DWORD,   \\r
+                Points:DWORD,   \\r
+                Map:DWORD,      \\r
+                Count:WORD      = ARG_SIZE\r
+        LOCAL   WritePlane:BYTE:2,      \\r
+                ScanOffsetT:WORD,       \\r
+                ScanOffsetB:WORD,       \\r
+                ScanCount:WORD,         \\r
+                Holder:WORD,            \\r
+                Height:WORD,            \\r
+                MinIdxT:WORD,           \\r
+                MinIdxB:WORD,           \\r
+                MaxIdx:WORD,            \\r
+                Width:WORD,             \\r
+                BoxX1:WORD,             \\r
+                BoxY1:WORD,             \\r
+                BoxX2:WORD,             \\r
+                BoxY2::WORD             = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+        ASSUME  ds:NOTHING\r
+\r
+; Check that at least three vertexes are specified\r
+        mov     cx, [Count]\r
+        cmp     cx, 3\r
+        jb      @@Exit\r
+\r
+;------------------------------\r
+; Find bounding box for polygon\r
+        les     di, [Map]\r
+        lds     si, [Points]            ; Pointer to vertex array\r
+        mov     [BoxX1], 32767\r
+        mov     [BoxX2], -32768\r
+        mov     [BoxY1], 32767\r
+        mov     [BoxY2], -32768\r
+\r
+        xor     dx, dx\r
+@@MinMaxLoop:\r
+        mov     bx, es:[di]             ; Get index of vertex\r
+        .shl    bx, 2                   ; Get offset in point array\r
+        add     bx, si\r
+\r
+; Check X range\r
+@@CheckMinX:\r
+        mov     ax, ds:[bx].X           ; Get X coordinate\r
+        cmp     ax, [BoxX1]\r
+        jge     @@CheckMaxX\r
+        mov     [BoxX1], ax\r
+        mov     [MinIdxT], dx\r
+        mov     [MinIdxB], dx\r
+@@CheckMaxX:\r
+        cmp     ax, [BoxX2]\r
+        jle     @@CheckMinY\r
+        mov     [BoxX2], ax\r
+        mov     [MaxIdx], dx\r
+\r
+; Check Y range\r
+@@CheckMinY:\r
+        mov     ax, ds:[bx].Y\r
+        cmp     ax, [BoxY1]\r
+        jge     @@CheckMaxY\r
+        mov     [BoxY1], ax\r
+@@CheckMaxY:\r
+        cmp     ax, [BoxY2]\r
+        jle     @@CheckDone\r
+        mov     [BoxY2], ax\r
+\r
+; Repeat thru all points\r
+@@CheckDone:\r
+        inc     di                      ; Next map entry\r
+        inc     di\r
+        inc     dx\r
+        inc     dx\r
+        dec     cx\r
+        jnz     @@MinMaxLoop\r
+\r
+;---------------------------------\r
+; Check if polygon is full clipped\r
+        mov     ax, [BoxX2]\r
+        cmp     ax, [mx_ClipX1]         ; Is poly full clipped?\r
+        jl      @@Exit\r
+        mov     bx, [BoxX1]\r
+        cmp     bx, [mx_ClipX2]         ; Is poly full clipped?\r
+        jg      @@Exit\r
+        sub     ax, bx                  ; Get width\r
+        jle     @@Exit                  ; Exit if not positive\r
+        mov     ax, [BoxY2]\r
+        cmp     ax, [mx_ClipY1]         ; Is poly full clipped?\r
+        jl      @@Exit\r
+        mov     bx, [BoxY1]\r
+        cmp     bx, [mx_ClipY2]         ; Is poly full clipped?\r
+        jg      @@Exit\r
+        sub     ax, bx                  ; Get height\r
+        jle     @@Exit                  ; Exit if not positive\r
+\r
+        dec     [Count]\r
+        shl     [Count], 1              ; We'll work with word offsets\r
+        mov     es, [mx_CodeSegment]\r
+\r
+;--------------\r
+; Scan top edge\r
+        mov     ax, OFFSET mx_ScanBuffer\r
+        mov     [ScanOffsetT], ax\r
+        mov     si, [MinIdxT]           ; Offset of bottom point index\r
+@@STLoop:\r
+        lds     bx, [Map]               ; DS:BX -> map table\r
+        mov     di, ds:[bx+si]          ; Index of top point #1\r
+        dec     si                      ; Next point\r
+        dec     si\r
+        test    si, si\r
+        jnl     @@ST1\r
+        mov     si, [Count]\r
+@@ST1:\r
+        mov     [MinIdxT], si           ; Save new index of top point\r
+        mov     si, ds:[bx+si]          ; Get index of top point #2\r
+        lds     bx, [Colors]            ; Get pointer to color array\r
+        shl     di, 1                   ; Convert indexes to offsets\r
+        shl     si, 1\r
+        mov     ax, ds:[bx+si]          ; Get colors\r
+        mov     dx, ds:[bx+di]\r
+        lds     bx, [Points]            ; DS:BX -> point array\r
+        shl     si, 1\r
+        shl     di, 1\r
+        add     si, bx                  ; DS:SI -> top point #2\r
+        add     bx, di                  ; DS:BX -> top point #1\r
+        mov     di, [ScanOffsetT]\r
+        call    subScan                 ; Scan edge\r
+        mov     [ScanOffsetT], di\r
+        mov     si, [MinIdxT]\r
+        cmp     si, [MaxIdx]            ; End of edge?\r
+        jne     @@STLoop                ; No, continue\r
+\r
+;-----------------\r
+; Scan bottom edge\r
+        mov     ax, OFFSET mx_ScanBuffer + OFFSET Y2\r
+        mov     [ScanOffsetB], ax\r
+        mov     si, [MinIdxB]           ; Offset of bottom point index\r
+@@SBLoop:\r
+        lds     bx, [Map]               ; DS:BX -> map table\r
+        mov     di, ds:[bx+si]          ; Index of bottom point #1\r
+        inc     si                      ; Next bottom point\r
+        inc     si\r
+        cmp     si, [Count]\r
+        jbe     @@SB1\r
+        xor     si, si\r
+@@SB1:\r
+        mov     [MinIdxB], si           ; Save new index of bottom point\r
+        mov     si, ds:[bx+si]          ; Get index of bottom point #2\r
+        lds     bx, [Colors]            ; Get pointer to color array\r
+        shl     di, 1                   ; Convert indexes to offsets\r
+        shl     si, 1\r
+        mov     ax, ds:[bx+si]          ; Get colors\r
+        mov     dx, ds:[bx+di]\r
+        lds     bx, [Points]            ; DS:BX -> point array\r
+        shl     si, 1\r
+        shl     di, 1\r
+        add     si, bx                  ; DS:SI -> top point #2\r
+        add     bx, di                  ; DS:BX -> top point #1\r
+        mov     di, [ScanOffsetB]\r
+        call    subScan                 ; Scan edge\r
+        mov     [ScanOffsetB], di\r
+        mov     si, [MinIdxB]\r
+        cmp     si, [MaxIdx]            ; End of edge?\r
+        jne     @@SBLoop                ; No, continue\r
+\r
+;--------------------\r
+; Clip left and right\r
+        mov     si, OFFSET mx_ScanBuffer\r
+        mov     ax, [BoxX1]\r
+        mov     cx, [BoxX2]\r
+        sub     cx, ax                  ; CX = bounding box width\r
+        mov     bx, [mx_ClipX1]\r
+        sub     bx, ax\r
+        jle     @@ClipL1                ; No need to clip left\r
+        sub     cx, bx                  ; Update width\r
+        add     ax, bx                  ; BoxX1 = mx_ClipX1\r
+        mov     [BoxX1], ax\r
+        .shl    bx, 3                   ; Warning!!! This is an hand-coded\r
+        add     si, bx                  ; multiply by the size of TSCAN\r
+@@ClipL1:\r
+        mov     bx, ax\r
+        add     bx, cx                  ; Last scan column\r
+        sub     bx, [mx_ClipX2]\r
+        jle     @@ClipL2                ; No need to clip right\r
+        sub     cx, bx                  ; Clip right\r
+@@ClipL2:\r
+        test    cx, cx                  ; Is clipped width positive?\r
+        jle     @@Exit                  ; No, exit\r
+        mov     [ScanCount], cx         ; Save number of columns to draw\r
+        mov     [ScanOffsetT], si       ; Remember offset of (clipped) buffer\r
+        mov     ds, [mx_CodeSegment]    ; DS:SI -> scan buffer\r
+\r
+;------------------------------\r
+; Check if Y clipping is needed\r
+        mov     ax, [BoxY1]\r
+        cmp     ax, [mx_ClipY1]\r
+        jl      @@ClipTB                ; Need to clip top\r
+        mov     ax, [BoxY2]\r
+        cmp     ax, [mx_ClipY2]\r
+        jg      @@ClipTB                ; Need to clip bottom\r
+        jmp     @@ClipYExit             ; Skip Y clipping\r
+\r
+;--------------------\r
+; Clip top and bottom\r
+@@ClipTB:\r
+        mov     di, cx                  ; DI = scan count\r
+        inc     di                      ; Increment count for pre-loop test\r
+        sub     si, SIZE TSCAN\r
+@@ClipYLoop:\r
+        dec     di                      ; Any column left?\r
+        jz      @@ClipYExit             ; No, exit\r
+        add     si, SIZE TSCAN\r
+        mov     ax, ds:[si].Y1          ; Y1\r
+        mov     cx, ds:[si].Y2          ; Y2\r
+        mov     dx, [mx_ClipY2]\r
+        cmp     ax, dx                  ; Full clipped?\r
+        jg      @@ClipYClip             ; Yes, skip this column\r
+        cmp     cx, dx                  ; Need to clip bottom?\r
+        jle     @@ClipY1                ; No, continue\r
+; Clip bottom, need to scale colors too\r
+        mov     ds:[si].Y2, dx\r
+        mov     bx, cx\r
+        sub     bx, dx                  ; Clip distance\r
+        sub     cx, ax                  ; Height\r
+        jle     @@ClipYClip\r
+        mov     ax, WORD PTR ds:[si].E1\r
+        sub     ax, WORD PTR ds:[si].E2\r
+        imul    bx\r
+        idiv    cx\r
+        add     WORD PTR ds:[si].E2, ax\r
+        mov     ax, ds:[si].Y1          ; Restore AX and CX\r
+        mov     cx, ds:[si].Y2\r
+@@ClipY1:\r
+        mov     dx, [mx_ClipY1]\r
+        cmp     cx, dx                  ; Full top clipped?\r
+        jl      @@ClipYClip             ; Yes, skip\r
+        sub     cx, ax                  ; Get height\r
+        jle     @@ClipYClip             ; Skip if not positive\r
+        cmp     ax, dx                  ; Need to clip top?\r
+        jge     @@ClipYLoop             ; No, continue\r
+; Clip top, need to scale colors too\r
+        mov     ds:[si].Y1, dx          ; Y1 = mx_ClipY1\r
+        sub     dx, ax                  ; DX = number of pixels clipped\r
+        cmp     cx, dx\r
+        jbe     @@ClipYClip             ; Full clipped, skip\r
+        mov     ax, WORD PTR ds:[si].E2\r
+        sub     ax, WORD PTR ds:[si].E1 ; AX = color distance\r
+        imul    dx\r
+        idiv    cx\r
+        add     WORD PTR ds:[si].E1, ax ; Update starting color\r
+        jmp     @@ClipYLoop\r
+@@ClipYClip:\r
+        mov     ds:[si].Y1, -1          ; Mark column as clipped\r
+        jmp     @@ClipYLoop\r
+@@ClipYExit:\r
+\r
+;-------------\r
+; Draw columns\r
+        mov     es, [mx_VideoSegment]\r
+        mov     si, [ScanOffsetT]\r
+        mov     cl, BYTE PTR [BoxX1]    ; Init write plane\r
+        and     cl, 03h\r
+        mov     al, 11h\r
+        shl     al, cl\r
+        mov     [WritePlane], al\r
+        .shr    [BoxX1], 2\r
+        mov     ax, [Color]             ; Make 8:8 fixed color\r
+        mov     ah, al\r
+        xor     al, al\r
+        mov     [Color], ax\r
+@@DrawLoop:\r
+        mov     ax, ds:[si].Y1\r
+        test    ax, ax                  ; Was column clipped?\r
+        js      @@DrawNext              ; Yes, skip\r
+        mov     cx, ds:[si].Y2\r
+        sub     cx, ax                  ; CX = height\r
+        jle     @@DrawNext\r
+        mul     [mx_BytesPerLine]       ; Get pixel address\r
+        add     ax, [BoxX1]\r
+        mov     di, ax\r
+        mov     ah, [WritePlane]\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax\r
+        mov     dx, [Color]\r
+        call    subFillScan\r
+@@DrawNext:\r
+        rol     [WritePlane], 1\r
+        adc     [BoxX1], 0              ; Bump pointer to video memory if needed\r
+        add     si, SIZE TSCAN\r
+        dec     [ScanCount]\r
+        jnz     @@DrawLoop\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxGouraudPoly  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxpi.asm b/16/x_/mxpi.asm
new file mode 100755 (executable)
index 0000000..9e8525f
--- /dev/null
@@ -0,0 +1,267 @@
+;-----------------------------------------------------------\r
+;\r
+; MXPI.ASM - Put image\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxPutImage\r
+\r
+EXTRN   subClipImage            : NEAR\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+mxTable LABEL   WORD                    ; Raster ops\r
+        DW      subMove\r
+        DW      subAnd\r
+        DW      subOr\r
+        DW      subXor\r
+        DW      subTrans\r
+        DW      subAdd\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Move functions.\r
+; Note: loops unrolled and optimized for CX even, no check for CX = 0.\r
+;\r
+subMove         PROC    NEAR\r
+        shr     cx, 1                   ; Make CX even\r
+        jc      @@Odd                   ; Special case if odd byte\r
+@@Loop: movsb\r
+        add     si, 3\r
+        movsb\r
+        add     si, 3\r
+        dec     cx\r
+        jnz     @@Loop\r
+@@Exit: ret\r
+@@Odd:  movsb\r
+        add     si, 3\r
+        jcxz    @@Exit\r
+        jmp     @@Loop\r
+subMove         ENDP\r
+;\r
+subAnd          PROC     NEAR\r
+        shr     cx, 1\r
+        jc      @@Odd\r
+@@Loop: mov     al, ds:[si]\r
+        mov     ah, ds:[si+4]\r
+        and     es:[di], ax\r
+        inc     di\r
+        inc     di\r
+        add     si, 8\r
+        dec     cx\r
+        jnz     @@Loop\r
+@@Exit: ret\r
+@@Odd:  lodsb\r
+        and     es:[di], al\r
+        inc     di\r
+        add     si, 3\r
+        jcxz    @@Exit\r
+        jmp     @@Loop\r
+subAnd          ENDP\r
+;\r
+subOr           PROC     NEAR\r
+        shr     cx, 1\r
+        jc      @@Odd\r
+@@Loop: mov     al, ds:[si]\r
+        mov     ah, ds:[si+4]\r
+        or      es:[di], ax\r
+        inc     di\r
+        inc     di\r
+        add     si, 8\r
+        dec     cx\r
+        jnz     @@Loop\r
+@@Exit: ret\r
+@@Odd:  lodsb\r
+        or      es:[di], al\r
+        inc     di\r
+        add     si, 3\r
+        jcxz    @@Exit\r
+        jmp     @@Loop\r
+subOr           ENDP\r
+;\r
+subXor          PROC     NEAR\r
+        shr     cx, 1\r
+        jc      @@Odd\r
+@@Loop: mov     al, ds:[si]\r
+        mov     ah, ds:[si+4]\r
+        xor     es:[di], ax\r
+        inc     di\r
+        inc     di\r
+        add     si, 8\r
+        dec     cx\r
+        jnz     @@Loop\r
+@@Exit: ret\r
+@@Odd:  lodsb\r
+        xor     es:[di], al\r
+        inc     di\r
+        add     si, 3\r
+        jcxz    @@Exit\r
+        jmp     @@Loop\r
+subXor          ENDP\r
+;\r
+subTrans        PROC     NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        cmp     al, ah\r
+        je      @@Skip\r
+        mov     es:[di], al\r
+@@Skip: inc     di\r
+        add     si, 4\r
+        dec     cx\r
+        jnz     @@Loop\r
+@@Exit: ret\r
+subTrans        ENDP\r
+;\r
+subAdd          PROC     NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        add     es:[di], al\r
+        inc     di\r
+        add     si, 4\r
+        dec     cx\r
+        jnz     @@Loop\r
+        ret\r
+subAdd          ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies a "raw" image from memory to screen.\r
+;\r
+; Input:\r
+;       Image   = pointer to image\r
+;       X, Y    = coordinates of destination\r
+;       Width   = width of image in pixels\r
+;       Height  = height of image in pixels\r
+;       Op      = raster op (OP_xxx)\r
+; Output:\r
+;       none\r
+;\r
+mxPutImage      PROC    FAR\r
+        ARG     Op:WORD,                \\r
+                Height:WORD,            \\r
+                Width:WORD,             \\r
+                Y:WORD,                 \\r
+                X:WORD,                 \\r
+                Image:DWORD             = ARG_SIZE\r
+        LOCAL   PlaneWidth:WORD:4,      \\r
+                PixelOffset:WORD,       \\r
+                MoveFunction:WORD,      \\r
+                Count:BYTE,             \\r
+                ReadPlane:BYTE,         \\r
+                OpInfo:BYTE,            \\r
+                WritePlane:BYTE         = AUTO_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+\r
+; Clip image\r
+        mov     bx, [X]\r
+        mov     ax, [Y]\r
+        mov     cx, [Width]\r
+        mov     dx, [Height]\r
+        call    subClipImage\r
+        jc      @@Exit                  ; Full clipped\r
+        mov     [Height], dx\r
+        add     WORD PTR Image[0], si   ; Skip clipped pixels\r
+\r
+; Get pixel address\r
+        mul     [mx_BytesPerLine]\r
+        mov     di, bx\r
+        shr     di, 1\r
+        shr     di, 1\r
+        add     di, ax\r
+        mov     [PixelOffset], di\r
+        mov     es, [mx_VideoSegment]   ; ES:DI points to pixel\r
+        and     bl, 03h\r
+        mov     [ReadPlane], bl\r
+\r
+; Compute extra bytes and width count for each plane\r
+        mov     bx, cx\r
+        shr     bx, 1\r
+        shr     bx, 1                   ; Width for each plane\r
+        and     cl, 03h\r
+        mov     al, 00001000b\r
+        shr     al, cl\r
+        mov     si, 3 SHL 1\r
+@@PatchLoop:\r
+        mov     PlaneWidth[si], bx\r
+        shr     al, 1\r
+        adc     bx, 0\r
+        dec     si\r
+        dec     si\r
+        jge     @@PatchLoop\r
+\r
+; Setup planes for output to VGA registers\r
+        mov     cl, [ReadPlane]\r
+        mov     al, 00010001b\r
+        shl     al, cl\r
+        mov     [WritePlane], al\r
+\r
+; Install move function\r
+        mov     bx, [Op]\r
+        mov     [OpInfo], bh            ; Remember additional info if needed\r
+        xor     bh, bh\r
+        cmp     bl, OP_ADD\r
+        jbe     @@SetMoveFunction\r
+        xor     bl, bl\r
+@@SetMoveFunction:\r
+        shl     bx, 1\r
+        mov     ax, mxTable[bx]\r
+        mov     [MoveFunction], ax\r
+\r
+; Put image\r
+        cld\r
+        mov     [Count], 4              ; Four planes\r
+        lea     bx, PlaneWidth          ; SS:[BX] = width in bytes for plane\r
+        mov     ds, WORD PTR Image[2]\r
+@@PlaneLoop:\r
+        cmp     WORD PTR ss:[bx], 0     ; Exit if nothing more to do\r
+        je      @@Exit                  ; (also, never try to move zero bytes!)\r
+        mov     si, WORD PTR Image[0]\r
+        mov     ah, [WritePlane]\r
+        and     ah, 0Fh\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax                  ; Select write plane\r
+        mov     ah, [ReadPlane]\r
+        and     ah, 03h\r
+        mov     al, 04h\r
+        mov     dx, GDC\r
+        out     dx, ax                  ; Select read plane\r
+        mov     dx, [Height]\r
+        mov     di, [PixelOffset]\r
+@@Loop:\r
+        push    si\r
+        push    di\r
+        mov     cx, WORD PTR ss:[bx]    ; Number of bytes to move\r
+        mov     ah, [OpInfo]            ; Transparent color for subTrans\r
+        call    [MoveFunction]\r
+        pop     di\r
+        pop     si\r
+        add     si, [Width]             ; Go to next image line\r
+        add     di, [mx_BytesPerLine]   ; Go to next screen row\r
+        dec     dx\r
+        jnz     @@Loop                  ; Repeat for all lines\r
+        inc     bx\r
+        inc     bx                      ; Select width for next plane\r
+        inc     [ReadPlane]\r
+        rol     [WritePlane], 1\r
+        adc     [PixelOffset], 0\r
+        inc     WORD PTR Image[0]\r
+        dec     [Count]\r
+        jnz     @@PlaneLoop             ; Repeat for all planes\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxPutImage      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxpn.asm b/16/x_/mxpn.asm
new file mode 100755 (executable)
index 0000000..eaaf61b
--- /dev/null
@@ -0,0 +1,60 @@
+;-----------------------------------------------------------\r
+;\r
+; MXPN.ASM - Panning function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxPan\r
+\r
+EXTRN   mxWaitDisplay   : FAR\r
+EXTRN   mxStartAddress  : FAR\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Moves the screen.\r
+;\r
+; Input:\r
+;       X, Y    = new X, Y coordinates of view screen\r
+; Output:\r
+;       none\r
+;\r
+mxPan           PROC    FAR\r
+        ARG     Y:WORD,                 \\r
+                X:WORD                  = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+\r
+        mov     ax, [Y]\r
+        mul     [mx_BytesPerLine]\r
+        mov     dx, [X]\r
+        shr     dx, 1\r
+        shr     dx, 1\r
+        add     ax, dx\r
+        push    ax                      ; Push the start address\r
+        call    mxWaitDisplay\r
+        call    mxStartAddress\r
+\r
+        mov     dx, 03DAh               ; Set the pixel pan register\r
+        in      al, dx\r
+        mov     dx, 03C0h\r
+        mov     al, 33h\r
+        out     dx, al\r
+        mov     al, BYTE PTR [X]\r
+        and     al, 3\r
+        shl     al, 1\r
+        out     dx, al\r
+\r
+        xor     ax, ax\r
+        .leave  ARG_SIZE\r
+mxPan           ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxpp.asm b/16/x_/mxpp.asm
new file mode 100755 (executable)
index 0000000..fc1755a
--- /dev/null
@@ -0,0 +1,121 @@
+;-----------------------------------------------------------\r
+;\r
+; MXPP.ASM - Get/put pixel functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxGetPixel\r
+PUBLIC  mxPutPixel\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Gets a pixel.\r
+;\r
+; Input:\r
+;       X, Y    = pixel coordinates\r
+; Output:\r
+;       pixel color\r
+;\r
+mxGetPixel      PROC    FAR\r
+        ARG     Y:WORD,                 \\r
+                X:WORD                  = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si\r
+\r
+        xor     ax, ax\r
+        mov     si, [X]\r
+        cmp     si, [mx_ClipX1]\r
+        jl      @@Exit\r
+        cmp     si, [mx_ClipX2]\r
+        jg      @@Exit\r
+        mov     bx, [Y]\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      @@Exit\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      @@Exit\r
+\r
+        mov     al, 04h                 ; Set read plane\r
+        mov     ah, BYTE PTR [X]\r
+        and     ah, 3\r
+        mov     dx, GDC\r
+        out     dx, ax\r
+\r
+        mov     ds, [mx_VideoSegment]\r
+        mov     ax, bx\r
+        mul     [mx_BytesPerLine]\r
+        .shr    si, 2\r
+        add     si, ax\r
+\r
+        mov     al, ds:[si]             ; Get pixel value\r
+        xor     ah, ah\r
+\r
+@@Exit:\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetPixel      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Puts a pixel of the specified color.\r
+;\r
+; Input:\r
+;       X, Y    = pixel coordinates\r
+;       Color   = pixel color\r
+; Output:\r
+;       none\r
+;\r
+mxPutPixel      PROC    FAR\r
+        ARG     Color:BYTE:2,           \\r
+                Y:WORD,                 \\r
+                X:WORD                  = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+\r
+        mov     si, [X]\r
+        cmp     si, [mx_ClipX1]\r
+        jl      @@Exit\r
+        cmp     si, [mx_ClipX2]\r
+        jg      @@Exit\r
+        mov     ax, [Y]\r
+        cmp     ax, [mx_ClipY1]\r
+        jl      @@Exit\r
+        cmp     ax, [mx_ClipY2]\r
+        jg      @@Exit\r
+\r
+        mov     ds, [mx_VideoSegment]\r
+        mul     [mx_BytesPerLine]\r
+        .shr    si, 2\r
+        add     si, ax\r
+\r
+        mov     cl, BYTE PTR [X]        ; Set write plane\r
+        and     cl, 3\r
+        mov     ax, 0102h\r
+        shl     ah, cl\r
+        mov     dx, TS\r
+        out     dx, ax\r
+\r
+        mov     al, [Color]             ; Write pixel\r
+        mov     ds:[si], al\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxPutPixel      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxra.asm b/16/x_/mxra.asm
new file mode 100755 (executable)
index 0000000..dd8e683
--- /dev/null
@@ -0,0 +1,37 @@
+;-----------------------------------------------------------\r
+;\r
+; MXRA.ASM - Row address\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxRowAddress\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the row address register.\r
+;\r
+; Input:\r
+;       RowAddress      = row size in words\r
+; Output:\r
+;       none\r
+;\r
+mxRowAddress    PROC    FAR\r
+        ARG     RowAddress:BYTE:2       = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        mov     dx, CRTC\r
+        mov     al, 13h\r
+        mov     ah, [RowAddress]\r
+        out     dx, ax\r
+        xor     ax, ax\r
+        .leave  ARG_SIZE\r
+mxRowAddress    ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxrp.asm b/16/x_/mxrp.asm
new file mode 100755 (executable)
index 0000000..de820c1
--- /dev/null
@@ -0,0 +1,101 @@
+;-----------------------------------------------------------\r
+;\r
+; MXRP.ASM - Rotate palette function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxRotatePalette\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Rotates the palette of the specified number of colors.\r
+;\r
+; Input:\r
+;       Palette = pointer to palette\r
+;       Count   = number of colors to rotate\r
+;       Step    = step size\r
+; Output:\r
+;       none\r
+;\r
+; Note: if Step is positive palette is rotated left to right, otherwise\r
+;       right to left.\r
+;\r
+mxRotatePalette PROC    FAR\r
+        ARG     Step:WORD,      \\r
+                Count:WORD,     \\r
+                Palette:DWORD   = ARG_SIZE\r
+        LOCAL   Holder:BYTE:768 = AUTO_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+\r
+        mov     bx, [Count]\r
+        add     bx, bx\r
+        add     bx, [Count]             ; BX = Count*3\r
+\r
+        lds     si, [Palette]           ; DS:SI -> palette\r
+        push    ss\r
+        pop     es\r
+        lea     di, Holder              ; ES:DI -> local space\r
+        cld\r
+\r
+        mov     ax, [Step]\r
+        mov     dx, ax\r
+        test    ax, ax\r
+        jz      @@Exit                  ; Nothing to do, exit\r
+        jl      @@RightToLeft\r
+\r
+@@LeftToRight:\r
+        add     ax, ax\r
+        add     dx, ax                  ; DX = Step*3\r
+        sub     bx, dx                  ; BX = (Count-Step)*3\r
+        add     si, bx\r
+        push    si\r
+        mov     cx, dx\r
+        rep     movsb\r
+        mov     es, WORD PTR Palette[2]\r
+        mov     di, si\r
+        dec     di                      ; ES:DI -> last byte of palette\r
+        pop     si\r
+        dec     si\r
+        mov     cx, bx\r
+        std\r
+        rep     movsb\r
+        push    ss\r
+        pop     ds\r
+        lea     si, Holder\r
+        les     di, [Palette]\r
+        mov     cx, dx\r
+        cld\r
+        rep     movsb\r
+        jmp     @@Exit\r
+\r
+@@RightToLeft:\r
+        add     ax, ax\r
+        add     dx, ax\r
+        neg     dx                      ; DX = Step*3\r
+        sub     bx, dx                  ; BX = (Count-Step)*3\r
+        mov     cx, dx\r
+        rep     movsb\r
+        les     di, [Palette]\r
+        mov     cx, bx\r
+        rep     movsb\r
+        push    ss\r
+        pop     ds\r
+        lea     si, Holder\r
+        mov     cx, dx\r
+        rep     movsb\r
+\r
+@@Exit:\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxRotatePalette ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxsa.asm b/16/x_/mxsa.asm
new file mode 100755 (executable)
index 0000000..3ebae67
--- /dev/null
@@ -0,0 +1,44 @@
+;-----------------------------------------------------------\r
+;\r
+; MXSA.ASM - Start address function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxStartAddress\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Modifies the starting address of video memory.\r
+;\r
+; Input:\r
+;       StartAddr       = new start address of video memory\r
+; Output:\r
+;       none\r
+;\r
+mxStartAddress  PROC    FAR\r
+        ARG     StartAddr:WORD  = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+\r
+        mov     bx, [StartAddr]\r
+        mov     dx, CRTC\r
+        mov     al, 0Ch                 ; Linear Starting Address high\r
+        mov     ah, bh\r
+        cli\r
+        out     dx, ax\r
+        mov     al, 0Dh                 ; Linear Starting Address low\r
+        mov     ah, bl\r
+        out     dx, ax\r
+        sti\r
+\r
+        .leave  ARG_SIZE\r
+mxStartAddress  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxsc.asm b/16/x_/mxsc.asm
new file mode 100755 (executable)
index 0000000..bcae45e
--- /dev/null
@@ -0,0 +1,50 @@
+;-----------------------------------------------------------\r
+;\r
+; MXSC.ASM - Set color function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxSetColor\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Updates the selected DAC register.\r
+;\r
+; Input:\r
+;       Index   = index of color to set\r
+;       R, G, B = color components\r
+; Output:\r
+;       none\r
+;\r
+mxSetColor      PROC FAR\r
+        ARG     B:BYTE:2,       \\r
+                G:BYTE:2,       \\r
+                R:BYTE:2,       \\r
+                Index:WORD      = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+\r
+        mov     ax, [Index]\r
+        mov     dx, 3C8h                ; PEL write address register\r
+        out     dx, al\r
+        inc     dx\r
+\r
+        mov     al, [R]\r
+        out     dx, al\r
+        mov     al, [G]\r
+        out     dx, al\r
+        mov     al, [B]\r
+        out     dx, al\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxSetColor      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxsi.asm b/16/x_/mxsi.asm
new file mode 100755 (executable)
index 0000000..b88d3b1
--- /dev/null
@@ -0,0 +1,317 @@
+;-----------------------------------------------------------\r
+;\r
+; MXPI.ASM - Stretch image\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxStretchImage\r
+\r
+EXTRN   subClipBox              : NEAR\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+mxTable LABEL   WORD                    ; Raster ops\r
+        DW      subMove\r
+        DW      subAnd\r
+        DW      subOr\r
+        DW      subXor\r
+        DW      subTrans\r
+        DW      subAdd\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Stretches and copies a "raw" image from memory to screen.\r
+;\r
+; Input:\r
+;       Image     = pointer to image\r
+;       X, Y      = coordinates of destination\r
+;       Width     = width of image in pixels\r
+;       Height    = height of image in pixels\r
+;       NewWidth  = new width of image in pixels\r
+;       NewHeight = new height of image in pixels\r
+;       Op        = raster op (OP_xxx)\r
+; Output:\r
+;       none\r
+;\r
+mxStretchImage  PROC    FAR\r
+        ARG     Op:WORD,                \\r
+                NewHeight:WORD,         \\r
+                NewWidth:WORD,          \\r
+                Height:WORD,            \\r
+                Width:WORD,             \\r
+                Y:WORD,                 \\r
+                X:WORD,                 \\r
+                Image:DWORD             = ARG_SIZE\r
+        LOCAL   PixelOffset:WORD,       \\r
+                MoveFunction:WORD,      \\r
+                ReadPlane:BYTE,         \\r
+                OpInfo:BYTE,            \\r
+                WidthStep:DWORD,        \\r
+                HeightStep:DWORD,       \\r
+                ImageLo:WORD,           \\r
+                WritePlane:BYTE         = AUTO_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+\r
+; Get width stretch factor\r
+    IF USE386 EQ TRUE\r
+        movzx   edx, [Width]\r
+        xor     eax, eax\r
+        movzx   ebx, [NewWidth]\r
+        shl     ebx, 16\r
+        idiv    ebx\r
+        mov     [WidthStep], eax\r
+    ELSE\r
+        xor     dx, dx                  ; Width stretch factor\r
+        mov     ax, [Width]\r
+        mov     bx, [NewWidth]\r
+        div     bx\r
+        mov     WORD PTR WidthStep[2], ax\r
+        xor     ax, ax\r
+        div     bx\r
+        mov     WORD PTR WidthStep[0], ax\r
+    ENDIF\r
+; Get height stretch factor\r
+    IF USE386 EQ TRUE\r
+        movzx   edx, [Height]\r
+        xor     eax, eax\r
+        movzx   ebx, [NewHeight]\r
+        shl     ebx, 16\r
+        idiv    ebx\r
+        mov     [HeightStep], eax\r
+    ELSE\r
+        xor     dx, dx\r
+        mov     ax, [Height]\r
+        mov     bx, [NewHeight]\r
+        div     bx\r
+        mov     WORD PTR HeightStep[2], ax\r
+        xor     ax, ax\r
+        div     bx\r
+        mov     WORD PTR HeightStep[0], ax\r
+   ENDIF\r
+\r
+; Clip image\r
+        mov     bx, [X]\r
+        mov     ax, [Y]\r
+        mov     cx, [NewWidth]\r
+        mov     dx, [NewHeight]\r
+        call    subClipBox\r
+        jc      @@Exit                  ; Full clipped\r
+        mov     [NewWidth], cx\r
+        mov     [NewHeight], dx\r
+        sub     [X], bx\r
+        sub     [Y], ax\r
+\r
+; Get pixel address\r
+        mul     [mx_BytesPerLine]\r
+        mov     di, bx\r
+        shr     di, 1\r
+        shr     di, 1\r
+        add     di, ax\r
+        mov     [PixelOffset], di\r
+        mov     es, [mx_VideoSegment]   ; ES:DI points to pixel\r
+        and     bl, 03h\r
+        mov     [ReadPlane], bl         ; Set read plane\r
+        mov     cl, bl\r
+        mov     al, 00010001b\r
+        shl     al, cl\r
+        mov     [WritePlane], al        ; Set write plane\r
+\r
+; Relocate image origin if previously clipped\r
+        mov     ax, [Y]\r
+        test    ax, ax\r
+        jz      @@OriginYDone\r
+    IF USE386 EQ TRUE\r
+        shl     eax, 16\r
+        imul    [HeightStep]\r
+        mov     ax, [Width]\r
+        mul     dx\r
+    ELSE\r
+        mov     bx, ax\r
+        mul     WORD PTR HeightStep[0]\r
+        mov     cx, dx\r
+        mov     ax, bx\r
+        mul     WORD PTR HeightStep[2]\r
+        add     ax, cx\r
+        mul     [Width]\r
+    ENDIF\r
+        add     WORD PTR [Image], ax\r
+@@OriginYDone:\r
+        mov     ax, [X]\r
+        test    ax, ax\r
+        jz      @@OriginXDone\r
+    IF USE386 EQ TRUE\r
+        shl     eax, 16\r
+        imul    [WidthStep]\r
+        add     WORD PTR [Image], dx\r
+    ELSE\r
+        mov     bx, ax\r
+        mul     WORD PTR WidthStep[0]\r
+        mov     cx, dx\r
+        mov     ax, bx\r
+        mul     WORD PTR WidthStep[2]\r
+        add     ax, cx\r
+        add     WORD PTR [Image], ax\r
+    ENDIF\r
+@@OriginXDone:\r
+        mov     ax, WORD PTR HeightStep[2]\r
+        mul     [Width]\r
+        mov     WORD PTR HeightStep[2], ax\r
+\r
+; Install move function\r
+        mov     bx, [Op]\r
+        mov     [OpInfo], bh            ; Remember additional info if needed\r
+        xor     bh, bh\r
+        cmp     bl, OP_ADD\r
+        jbe     @@SetMoveFunction\r
+        xor     bl, bl\r
+@@SetMoveFunction:\r
+        shl     bx, 1\r
+        mov     ax, mxTable[bx]\r
+        mov     [MoveFunction], ax\r
+\r
+; Put image\r
+        mov     ds, WORD PTR Image[2]\r
+        xor     ax, ax\r
+        mov     [ImageLo], ax\r
+@@Loop:\r
+        mov     si, WORD PTR Image[0]   ; Get pointer to image\r
+        mov     ah, [WritePlane]\r
+        and     ah, 0Fh\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax                  ; Select write plane\r
+        mov     ah, [ReadPlane]\r
+        and     ah, 03h\r
+        mov     al, 04h\r
+        mov     dx, GDC\r
+        out     dx, ax                  ; Select read plane\r
+        mov     cx, [NewHeight]\r
+        mov     di, [PixelOffset]       ; ES:DI points to video memory\r
+        mov     ah, [OpInfo]            ; Additional raster op info\r
+        xor     bx, bx\r
+        mov     dx, [mx_BytesPerLine]\r
+        call    [MoveFunction]          ; Draw column\r
+        inc     [ReadPlane]             ; Next read plane\r
+        rol     [WritePlane], 1         ; Next write plane\r
+        adc     [PixelOffset], 0        ; Update video offset if needed\r
+        mov     dx, WORD PTR WidthStep[0]\r
+        mov     ax, WORD PTR WidthStep[2]\r
+        add     [ImageLo], dx\r
+        adc     WORD PTR Image[0], ax   ; Next image column\r
+        dec     [NewWidth]\r
+        jnz     @@Loop                  ; Repeat for all columns\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Move functions, on entry:\r
+;       AH = additional raster op info (e.g. transparent color)\r
+;       BX = 0,\r
+;       CX = pixel count,\r
+;       DX = mx_BytesPerLine.\r
+;\r
+subMove         PROC    NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        mov     es:[di], al\r
+        add     di, dx\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, WORD PTR HeightStep[2]\r
+        add     bx, WORD PTR HeightStep[0]\r
+        jnc     @@Loop\r
+        add     si, [Width]\r
+        jmp     @@Loop\r
+@@Exit: ret\r
+subMove         ENDP\r
+;\r
+subAnd          PROC     NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        and     es:[di], al\r
+        add     di, dx\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, WORD PTR HeightStep[2]\r
+        add     bx, WORD PTR HeightStep[0]\r
+        jnc     @@Loop\r
+        add     si, [Width]\r
+        jmp     @@Loop\r
+@@Exit: ret\r
+subAnd          ENDP\r
+;\r
+subOr           PROC     NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        or      es:[di], al\r
+        add     di, dx\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, WORD PTR HeightStep[2]\r
+        add     bx, WORD PTR HeightStep[0]\r
+        jnc     @@Loop\r
+        add     si, [Width]\r
+        jmp     @@Loop\r
+@@Exit: ret\r
+subOr           ENDP\r
+;\r
+subXor          PROC     NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        xor     es:[di], al\r
+        add     di, dx\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, WORD PTR HeightStep[2]\r
+        add     bx, WORD PTR HeightStep[0]\r
+        jnc     @@Loop\r
+        add     si, [Width]\r
+        jmp     @@Loop\r
+@@Exit: ret\r
+subXor          ENDP\r
+;\r
+subTrans        PROC     NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        cmp     al, ah\r
+        je      @@Skip\r
+        mov     es:[di], al\r
+@@Skip:\r
+        add     di, dx\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, WORD PTR HeightStep[2]\r
+        add     bx, WORD PTR HeightStep[0]\r
+        jnc     @@Loop\r
+        add     si, [Width]\r
+        jmp     @@Loop\r
+@@Exit: ret\r
+subTrans        ENDP\r
+;\r
+subAdd          PROC     NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        add     es:[di], al\r
+        add     di, dx\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, WORD PTR HeightStep[2]\r
+        add     bx, WORD PTR HeightStep[0]\r
+        jnc     @@Loop\r
+        add     si, [Width]\r
+        jmp     @@Loop\r
+@@Exit: ret\r
+subAdd          ENDP\r
+\r
+mxStretchImage  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxsl.asm b/16/x_/mxsl.asm
new file mode 100755 (executable)
index 0000000..d790885
--- /dev/null
@@ -0,0 +1,62 @@
+;-----------------------------------------------------------\r
+;\r
+; MXLN.ASM - Start line function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxStartLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+        ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Changes the video start address to the specified line.\r
+;\r
+; Input:\r
+;       Line    = new start line\r
+; Output:\r
+;       none\r
+;\r
+mxStartLine     PROC FAR\r
+        ARG     Line:WORD       = ARG_SIZE\r
+        .enter  0\r
+        ASSUME  ds:NOTHING\r
+\r
+        mov     ax, [Line]              ; Get video offset\r
+        mul     [mx_BytesPerLine]\r
+        xchg    ax, bx                  ; Copy it into BX\r
+\r
+; Wait display\r
+        mov     dx, STATUS\r
+@@1:    in      al, dx\r
+        test    al, 08h\r
+        jnz     @@1\r
+\r
+; Set starting address\r
+        mov     dx, CRTC\r
+        mov     al, 0Ch                 ; Linear Starting Address high\r
+        mov     ah, bh\r
+        cli\r
+        out     dx, ax\r
+        mov     al, 0Dh                 ; Linear Starting Address low\r
+        mov     ah, bl\r
+        out     dx, ax\r
+        sti\r
+\r
+; Wait retrace\r
+        mov     dx, STATUS\r
+@@2:    in      al,dx\r
+        test    al, 08h\r
+        jz      @@2\r
+\r
+        xor     ax, ax\r
+        .leave  ARG_SIZE\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxsm.asm b/16/x_/mxsm.asm
new file mode 100755 (executable)
index 0000000..183fba1
--- /dev/null
@@ -0,0 +1,508 @@
+;-----------------------------------------------------------\r
+;\r
+; MXSM.ASM - Set/change mode functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxChangeMode\r
+PUBLIC  mxGetAspect\r
+PUBLIC  mxGetScreenSize\r
+PUBLIC  mxSetMode\r
+\r
+PUBLIC  mx_ScreenWidth\r
+PUBLIC  mx_ScreenHeight\r
+PUBLIC  mx_BytesPerLine\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mxSetSysClipRegion      : FAR\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_CodeSegment  : WORD\r
+\r
+mx_ScreenWidth  DW      ?               ; Current screen width\r
+mx_ScreenHeight DW      ?\r
+mx_AspectX      DW      ?               ; Aspect ratio for current mode\r
+mx_AspectY      DW      ?\r
+mx_BytesPerLine DW      0               ; Bytes per line\r
+\r
+;\r
+; Tables for setting video modes, sources:\r
+; - MODEX.ASM, Matt Pritchard\r
+; - Dr. Dobb's Journal, Michael Abrash\r
+; - Fractint VIDEO.ASM module\r
+;\r
+TBL_SingleLine  LABEL   WORD            ; CRTC\r
+        DW      04009h                  ; Cell height: 1 scan line\r
+        DW      00014h                  ; Double word mode off\r
+        DW      0E317h                  ; Byte mode on\r
+        DW      0\r
+TBL_DoubleLine  LABEL   WORD            ; CRTC\r
+        DW      04109h                  ; Cell height: 2 scan lines\r
+        DW      00014h\r
+        DW      0E317h\r
+        DW      0\r
+TBL_Width320    LABEL   WORD            ; CRTC\r
+        DW      05F00h                  ; Horizontal total\r
+        DW      04F01h                  ; Horizontal displayed\r
+        DW      05002h                  ; Start horizontal blanking\r
+        DW      08203h                  ; End horizontal blanking\r
+        DW      05404h                  ; Start horizontal sync\r
+        DW      08005h                  ; End horizontal sync\r
+        DW      02813h                  ; Row address\r
+        DW      0\r
+TBL_Width360    LABEL   WORD            ; CRTC\r
+        DW      06B00h                  ; Horizontal total\r
+        DW      05901h                  ; Horizontal displayed\r
+        DW      05A02h                  ; Start horizontal blanking\r
+        DW      08E03h                  ; End horizontal blanking\r
+        DW      05E04h                  ; Start horizontal sync\r
+        DW      08A05h                  ; End horizontal sync\r
+        DW      02D13h                  ; Row address\r
+        DW      0\r
+TBL_Height175   LABEL   WORD            ; CRTC\r
+        DW      0BF06h                  ; Vertical total\r
+        DW      01F07h                  ; Overflow\r
+        DW      08310h                  ; Start vertical sync\r
+        DW      08511h                  ; End vertical sync\r
+        DW      05D12h                  ; Vertical displayed\r
+        DW      06315h                  ; Start vertical blanking\r
+        DW      0BA16h                  ; End vertical blanking\r
+        DW      0\r
+TBL_Height200   LABEL   WORD            ; CRTC\r
+        DW      0BF06h                  ; Vertical total\r
+        DW      01F07h                  ; Overflow\r
+        DW      09C10h                  ; Start vertical sync\r
+        DW      08E11h                  ; End vertical sync\r
+        DW      08F12h                  ; Vertical displayed\r
+        DW      09615h                  ; Start vertical blanking\r
+        DW      0B916h                  ; End vertical blanking\r
+        DW      0\r
+TBL_Height240   LABEL   WORD            ; CRTC\r
+        DW      00D06h                  ; Vertical total\r
+        DW      03E07h                  ; Overflow\r
+        DW      0EA10h                  ; Start vertical sync\r
+        DW      08C11h                  ; End vertical sync\r
+        DW      0DF12h                  ; Vertical displayed\r
+        DW      0E715h                  ; Start vertical blanking\r
+        DW      00616h                  ; End vertical blanking\r
+        DW      0\r
+TBL_Tweak400x600:\r
+        DW      07400h\r
+        DW      06301h\r
+        DW      06402h\r
+        DW      09703h\r
+        DW      06804h\r
+        DW      09505h\r
+        DW      08606h\r
+        DW      0F007h\r
+        DW      06009h\r
+        DW      0310Fh\r
+        DW      05B10h\r
+        DW      08D11h\r
+        DW      05712h\r
+        DW      03213h\r
+        DW      00014h\r
+        DW      06015h\r
+        DW      08016h\r
+        DW      0E317h\r
+        DW      0\r
+\r
+TBL_320x200:\r
+        DB      63h                     ; 400 scan lines, 25 MHz clock\r
+        DW      6, 5                    ; Aspect: 6/5 = 1.2:1\r
+        DW      320, 200                ; Size\r
+        DW      TBL_Width320, TBL_Height200, TBL_DoubleLine, 0\r
+        DW      819                     ; Max height\r
+TBL_320x240:\r
+        DB      0E3h                    ; 400 scan lines, 25 MHz clock\r
+        DW      1, 1                    ; Aspect: 1/1 = 1:1\r
+        DW      320, 240                ; Size\r
+        DW      TBL_Width320, TBL_Height240, TBL_DoubleLine, 0\r
+        DW      819                     ; Max height\r
+TBL_320x400:\r
+        DB      63h                     ; 480 scan lines, 25 MHz clock\r
+        DW      6, 10                   ; Aspect: 6/10 = 0.6:1\r
+        DW      320, 400                ; Size\r
+        DW      TBL_Width320, TBL_Height200, TBL_SingleLine, 0\r
+        DW      819                     ; Max height\r
+TBL_320x480:\r
+        DB      0E3h                    ; 480 scan lines, 25 MHz clock\r
+        DW      1, 2                    ; Aspect: 1/2 = 0.5:1\r
+        DW      320, 480                ; Size\r
+        DW      TBL_Width320, TBL_Height240, TBL_SingleLine, 0\r
+        DW      819                     ; Max height\r
+TBL_360x200:\r
+        DB      067h                    ; 400 scan lines, 28 MHz clock\r
+        DW      27, 20                  ; Aspect: 27/20 = 1.35:1\r
+        DW      360, 200                ; Size\r
+        DW      TBL_Width360, TBL_Height200, TBL_DoubleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_360x240:\r
+        DB      0E7h                    ; 480 scan lines, 28 MHz clock\r
+        DW      9, 8                    ; Aspect: 9/8 = 1.125:1\r
+        DW      360, 240                ; Size\r
+        DW      TBL_Width360, TBL_Height240, TBL_DoubleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_360x400:\r
+        DB      067h                    ; 400 scan lines, 28 MHz clock\r
+        DW      27, 40                  ; Aspect: 27/40 = 0.675:1\r
+        DW      360, 400                ; Size\r
+        DW      TBL_Width360, TBL_Height200, TBL_SingleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_360x480:\r
+        DB      0E7h                    ; 480 scan lines, 28 MHz clock\r
+        DW      9, 16                   ; Aspect: 9/16 = 0.5625:1\r
+        DW      360, 480                ; Size\r
+        DW      TBL_Width360, TBL_Height240, TBL_SingleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_320x175:\r
+        DB      0A3h\r
+        DW      0, 0                    ; Aspect:\r
+        DW      320, 175\r
+        DW      TBL_Width320, TBL_Height175, TBL_DoubleLine, 0\r
+        DW      819\r
+TBL_320x350:\r
+        DB      0A3h\r
+        DW      0, 0                    ; Aspect:\r
+        DW      320, 175\r
+        DW      TBL_Width320, TBL_Height175, TBL_SingleLine, 0\r
+        DW      819\r
+TBL_360x175:\r
+        DB      0A7h\r
+        DW      0, 0                    ; Aspect:\r
+        DW      360, 480                ; Size\r
+        DW      TBL_Width360, TBL_Height175, TBL_DoubleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_360x350:\r
+        DB      0A7h\r
+        DW      0, 0                    ; Aspect:\r
+        DW      360, 480                ; Size\r
+        DW      TBL_Width360, TBL_Height175, TBL_SingleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_400x600:\r
+        DB      0E7h                    ; 28 MHz clock\r
+        DW      1, 2                    ; Aspect: 1/2 = 0.5:1\r
+        DW      400, 600                ; Size\r
+        DW      TBL_Tweak400x600, 0\r
+        DW      655                     ; Max height\r
+\r
+TBL_Mode        LABEL   WORD\r
+        DW      TBL_320x175\r
+        DW      TBL_320x200\r
+        DW      TBL_320x240\r
+        DW      TBL_320x350\r
+        DW      TBL_320x400\r
+        DW      TBL_320x480\r
+        DW      TBL_360x175\r
+        DW      TBL_360x200\r
+        DW      TBL_360x240\r
+        DW      TBL_360x350\r
+        DW      TBL_360x400\r
+        DW      TBL_360x480\r
+        DW      TBL_400x600\r
+\r
+MAXVMODE        EQU     ($-OFFSET TBL_Mode) / 2\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Enables 80x25 color text mode\r
+;\r
+subText         PROC    NEAR\r
+        ASSUME  ds:MX_TEXT\r
+        mov     ax, 0003h\r
+        int     10h                     ; Call BIOS set mode\r
+\r
+        mov     [mx_ScreenHeight], 0\r
+        mov     [mx_BytesPerLine], 0\r
+        ret\r
+subText         ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Enables the selected graphics mode.\r
+;\r
+; Input:\r
+;       Mode    = mode to select (MX_???x???)\r
+; Output:\r
+;       none\r
+;\r
+mxSetMode       PROC    FAR\r
+        ARG     Mode:WORD       = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si, es, di\r
+\r
+; Set DS to code segment alias\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     si, [Mode]\r
+        cmp     si, MAXVMODE            ; Is it a valid mode?\r
+        ja      @@Exit                  ; No, exit\r
+        test    si, si                  ; Text mode?\r
+        jnz     @@Set                   ; No, handle it\r
+\r
+        call    subText                 ; Back to text mode\r
+        jmp     @@Exit                  ; Exit now\r
+\r
+; Set video mode\r
+@@Set:\r
+        dec     si                      ; Skip text mode\r
+        shl     si, 1\r
+        mov     si, TBL_Mode[si]\r
+        cld\r
+\r
+; Use BIOS to set 320x200x256 linear mode\r
+        push    si                      ; Save SI\r
+        mov     ax, 0013h\r
+        int     10h                     ; Use BIOS to set 320x200 linear mode\r
+        pop     si                      ; Restore SI\r
+\r
+        mov     dx, TS\r
+        mov     ax, 0604h\r
+        out     dx, ax                  ; Disable chain-4 mode\r
+        mov     ax, 0100h\r
+        out     dx, ax                  ; Reset\r
+        mov     dx, MISC\r
+        lodsb\r
+        out     dx, al                  ; New timing/size\r
+        mov     dx, TS\r
+        mov     ax, 0300h\r
+        out     dx, ax                  ; Restart sequencer\r
+\r
+; Unlock CRTC registers 0-7\r
+        mov     dx, CRTC\r
+        mov     al, 11h\r
+        out     dx, al                  ; Vertical sync end register\r
+        inc     dx\r
+        in      al, dx\r
+        and     al, 7Fh                 ; Clear write protect bit\r
+        out     dx, al\r
+\r
+        lodsw                           ; Get X aspect\r
+        mov     [mx_AspectX], ax\r
+        lodsw                           ; Get Y aspect\r
+        mov     [mx_AspectY], ax\r
+        lodsw                           ; Get screen width\r
+        mov     [mx_ScreenWidth], ax\r
+        shr     ax, 1\r
+        shr     ax, 1                   ; Divide by four to get bytes per line\r
+        mov     [mx_BytesPerLine], ax\r
+        lodsw                           ; Get screen height\r
+        mov     [mx_ScreenHeight], ax\r
+\r
+; Set CRTC registers\r
+        mov     bx, si\r
+        mov     dx, CRTC\r
+@@TableLoop:\r
+        mov     si, ds:[bx]             ; DS:SI -> table of CRTC registers\r
+        inc     bx\r
+        inc     bx                      ; DS:BX -> offset of next table\r
+        test    si, si                  ; Last table?\r
+        jz      @@EndLoop               ; Yes, exit loop\r
+@@Loop:\r
+        lodsw                           ; Get CRTC register index and value\r
+        test    ax, ax                  ; End of table?\r
+        jz      @@TableLoop             ; Yes, go to next table\r
+        out     dx, ax                  ; Set register AL to value AH\r
+        jmp     @@Loop                  ; Get next register/value\r
+@@EndLoop:\r
+\r
+; Set virtual screen and system clip region\r
+        push    [mx_ScreenWidth]\r
+        push    WORD PTR ds:[bx]\r
+        call    mxSetSysClipRegion\r
+\r
+; Clear video memory\r
+        mov     dx, TS\r
+        mov     ax, 0F02h\r
+        out     dx, ax                  ; Enable all planes\r
+        mov     es, [mx_VideoSegment]\r
+        xor     di, di\r
+        mov     cx, 8000h\r
+        xor     ax, ax\r
+        rep     stosw\r
+\r
+@@Done:\r
+; Lock CRTC registers 0-7 (some cards need this)\r
+        mov     dx, CRTC\r
+        mov     al, 11h\r
+        out     dx, al                  ; Vertical sync end register\r
+        inc     dx\r
+        in      al, dx\r
+        or      al, 80h                 ; Set write protect bit\r
+        out     dx, al\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        mov     ax, [mx_ScreenWidth]\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxSetMode       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Changes from the current mode the selected graphics mode.\r
+;\r
+; Input:\r
+;       Mode    = mode to select (MX_???x???)\r
+; Output:\r
+;       none\r
+; Notes:\r
+;       this function assumes that mxSetMode and mxSetVirtualScreen\r
+;       have been called first. View size is rearranged to match the\r
+;       specified mode, but video memory is not cleared.\r
+;       Differences from mxSetMode:\r
+;       - video BIOS is not called to initialize graphics;\r
+;       - row address register is not modified;\r
+;       - video memory is not cleared;\r
+;       - mx_BytesPerLine is not modified;\r
+;       - system clip region is not modified.\r
+;\r
+mxChangeMode    PROC    FAR\r
+        ARG     Mode:WORD       = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si, es, di\r
+\r
+; Set DS to code segment alias\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     si, [Mode]\r
+        cmp     si, MAXVMODE            ; Is it a valid mode?\r
+        ja      @@Exit                  ; No, exit\r
+        test    si, si                  ; Text mode?\r
+        jz      @@Exit                  ; Yes, exit\r
+\r
+        dec     si                      ; Skip text mode\r
+        shl     si, 1\r
+        mov     si, TBL_Mode[si]\r
+        cld\r
+\r
+        mov     dx, TS\r
+        mov     ax, 0604h\r
+        out     dx, ax                  ; Disable chain-4 mode\r
+        mov     ax, 0100h\r
+        out     dx, ax                  ; Reset\r
+        mov     dx, MISC\r
+        lodsb\r
+        out     dx, al                  ; New timing/size\r
+        mov     dx, TS\r
+        mov     ax, 0300h\r
+        out     dx, ax                  ; Restart sequencer\r
+\r
+; Unlock CRTC registers 0-7\r
+        mov     dx, CRTC\r
+        mov     al, 11h\r
+        out     dx, al                  ; Vertical sync end register\r
+        inc     dx\r
+        in      al, dx\r
+        and     al, 7Fh                 ; Clear write protect bit\r
+        out     dx, al\r
+\r
+        lodsw                           ; Get X aspect\r
+        mov     [mx_AspectX], ax\r
+        lodsw                           ; Get Y aspect\r
+        mov     [mx_AspectY], ax\r
+        lodsw                           ; Get screen width\r
+        mov     [mx_ScreenWidth], ax\r
+        lodsw                           ; Get screen height\r
+        mov     [mx_ScreenHeight], ax\r
+\r
+; Set CRTC registers\r
+        mov     bx, si\r
+        mov     dx, CRTC\r
+@@TableLoop:\r
+        mov     si, ds:[bx]             ; DS:SI -> table of CRTC registers\r
+        inc     bx\r
+        inc     bx                      ; DS:BX -> offset of next table\r
+        test    si, si                  ; Last table?\r
+        jz      @@EndLoop               ; Yes, exit loop\r
+@@Loop:\r
+        lodsw                           ; Get CRTC register index and value\r
+        test    ax, ax                  ; End of table?\r
+        jz      @@TableLoop             ; Yes, go to next table\r
+        cmp     al, 13h                 ; Row address register?\r
+        je      @@Loop                  ; Yes, ignore it\r
+        out     dx, ax                  ; Set register AL to value AH\r
+        jmp     @@Loop                  ; Get next register/value\r
+@@EndLoop:\r
+\r
+; Lock CRTC registers 0-7 (some cards need this)\r
+        mov     dx, CRTC\r
+        mov     al, 11h\r
+        out     dx, al                  ; Vertical sync end register\r
+        inc     dx\r
+        in      al, dx\r
+        or      al, 80h                 ; Set write protect bit\r
+        out     dx, al\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        mov     ax, [mx_ScreenWidth]\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxChangeMode    ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the aspect ratio for the current mode.\r
+;\r
+; Input:\r
+;       AspectX = pointer to aspect X\r
+;       AspectY = pointer to aspect Y\r
+;\r
+; A rectangle of width AspectX and height AspectY looks like a square.\r
+;\r
+mxGetAspect     PROC FAR\r
+        ARG     AspectY:DWORD,  \\r
+                AspectX:DWORD   = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+        ASSUME  ds:NOTHING\r
+\r
+        lds     si, [AspectX]\r
+        mov     ax, [mx_AspectX]\r
+        mov     ds:[si], ax\r
+        lds     si, [AspectY]\r
+        mov     ax, [mx_AspectY]\r
+        mov     ds:[si], ax\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetAspect     ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current screen size.\r
+;\r
+; Input:\r
+;       Width   = pointer to screen width\r
+;       Height  = pointer to screen height\r
+;\r
+mxGetScreenSize PROC FAR\r
+        ARG     SizeY:DWORD,    \\r
+                SizeX:DWORD     = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+        ASSUME  ds:NOTHING\r
+\r
+        lds     si, [SizeX]\r
+        mov     ax, [mx_ScreenWidth]\r
+        mov     ds:[si], ax\r
+        lds     si, [SizeY]\r
+        mov     ax, [mx_ScreenHeight]\r
+        mov     ds:[si], ax\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetScreenSize ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxsp.asm b/16/x_/mxsp.asm
new file mode 100755 (executable)
index 0000000..1d08e71
--- /dev/null
@@ -0,0 +1,57 @@
+;-----------------------------------------------------------\r
+;\r
+; MXSP.ASM - Set palette function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxSetPalette\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Updates the VGA palette.\r
+;\r
+; Input:\r
+;       Buffer          = pointer to palette data (R,G,B)\r
+;       Start           = index of first color to set\r
+;       Count           = number of color to set\r
+; Output:\r
+;       none\r
+;\r
+mxSetPalette    PROC    FAR\r
+        ARG     Count:WORD,             \\r
+                Start:WORD,             \\r
+                Buffer:DWORD            = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si\r
+\r
+        lds     si, [Buffer]\r
+        mov     cx, [Count]\r
+        mov     ax, [Start]\r
+        mov     dx, 3C8h                ; PEL write address register\r
+        out     dx, al\r
+        inc     dx\r
+        cld\r
+        cli                             ; Disable interrupts\r
+@@Loop:\r
+        lodsb\r
+        out     dx, al                  ; Red\r
+        lodsb\r
+        out     dx, al                  ; Green\r
+        lodsb\r
+        out     dx, al                  ; Blue\r
+        loop    @@Loop                  ; Loop until done\r
+        sti                             ; Enable interrupts\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxSetPalette    ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxss.asm b/16/x_/mxss.asm
new file mode 100755 (executable)
index 0000000..97df736
--- /dev/null
@@ -0,0 +1,72 @@
+;-----------------------------------------------------------\r
+;\r
+; MXSS.ASM - Split screen function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxSplitScreen\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Splits the screen.\r
+;\r
+; Input:\r
+;       Line    = scan line at which screen has to be splitted\r
+; Output:\r
+;       none\r
+;\r
+mxSplitScreen   PROC    FAR\r
+        ARG     Line:WORD       = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+\r
+; Modify the line compare value: bits 0-7 are in the Line Compare\r
+; register (CRTC #18), bit 8 is in the Overflow Low register (CRTC #7)\r
+; and bit 9 is in the Maximum Row Address register (CRTC #9)\r
+        mov     ax, [Line]\r
+        shl     ax, 1                   ; Adjust line for mode "X"\r
+        mov     bh, ah\r
+        mov     bl, ah\r
+        and     bx, 0201h\r
+        mov     cl, 4\r
+        shl     bx, cl\r
+        shl     bh, 1\r
+        mov     dx, CRTC\r
+; Write bits 0-7 to line compare register\r
+        mov     ah, al\r
+        mov     al, 18h\r
+        out     dx, ax\r
+; Write bit 8 to overflow register\r
+        mov     al, 07h\r
+        out     dx, al\r
+        inc     dx\r
+        in      al, dx\r
+        dec     dx\r
+        mov     ah, al\r
+        and     ah, 11101111b\r
+        or      ah, bl\r
+        mov     al, 07h\r
+        out     dx, ax\r
+; Write bit 9 to maximum row address register\r
+        mov     al, 09h\r
+        out     dx, al\r
+        inc     dx\r
+        in      al, dx\r
+        dec     dx\r
+        mov     ah, al\r
+        and     ah, 10111111b\r
+        or      ah, bh\r
+        mov     al, 09h\r
+        out     dx, ax\r
+\r
+        .leave  ARG_SIZE\r
+mxSplitScreen   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxtl.asm b/16/x_/mxtl.asm
new file mode 100755 (executable)
index 0000000..69900c8
--- /dev/null
@@ -0,0 +1,169 @@
+;-----------------------------------------------------------\r
+;\r
+; MXTL.ASM - Put tile\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxPutTile\r
+PUBLIC  mxTransPutTile\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies a "mode-x" tile from memory to screen.\r
+;\r
+; Input:\r
+;       Image   = pointer to tile\r
+;       X, Y    = coordinates of destination\r
+;       Width   = width of image in pixels (Width and 3 = 0)\r
+;       Height  = height of image in pixels\r
+; Output:\r
+;       none\r
+; Note:\r
+;       no clipping is performed on tiles!\r
+;\r
+mxPutTile       PROC    FAR\r
+        ARG     Height:WORD,            \\r
+                Width:WORD,             \\r
+                Y:WORD,                 \\r
+                X:WORD,                 \\r
+                Image:DWORD             = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si, es, di\r
+\r
+        mov     ax, [Y]                 ; Get pixel address\r
+        mul     [mx_BytesPerLine]\r
+        mov     di, [X]\r
+        .shr    di, 2\r
+        add     di, ax\r
+        mov     es, [mx_VideoSegment]\r
+\r
+        lds     si, [Image]             ; Get tile address\r
+        .shr    [Width], 2              ; Number of bytes per plane\r
+        mov     cl, BYTE PTR [X]\r
+        and     cl, 3\r
+        mov     ah, 11h                 ; AH = plane mask\r
+        shl     ah, cl                  ; Align mask to first plane\r
+\r
+        mov     [Y], 4                  ; Number of planes\r
+        mov     bx, [mx_BytesPerLine]\r
+        sub     bx, [Width]             ; Extra bytes per line\r
+@@Loop:\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax                  ; Set write plane\r
+        mov     [X], di                 ; Save video offset\r
+        mov     dx, [Height]\r
+@@Loop2:\r
+        mov     cx, [Width]             ; Number of bytes to move\r
+\r
+        shr     cx, 1                   ; Move line\r
+        rep     movsw\r
+        rcl     cx, 1\r
+        rep     movsb\r
+\r
+        add     di, bx                  ; Move video offset to next line\r
+        dec     dx                      ; Done all lines?\r
+        jnz     @@Loop2                 ; No, continue\r
+        mov     di, [X]                 ; Restore video offset\r
+        rol     ah, 1                   ; Next plane\r
+        adc     di, 0                   ; Bump video offset if needed\r
+        dec     [Y]                     ; Any plane left?\r
+        jnz     @@Loop                  ; Yes, keep looping\r
+\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxPutTile       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies a "mode-x" tile from memory to screen.\r
+; Skips over color 0.\r
+;\r
+; Input:\r
+;       Image   = pointer to tile\r
+;       X, Y    = coordinates of destination\r
+;       Width   = width of image in pixels (Width and 3 = 0)\r
+;       Height  = height of image in pixels\r
+; Output:\r
+;       none\r
+; Note:\r
+;       no clipping is performed on tiles!\r
+;\r
+mxTransPutTile  PROC    FAR\r
+        ARG     Height:WORD,            \\r
+                Width:WORD,             \\r
+                Y:WORD,                 \\r
+                X:WORD,                 \\r
+                Image:DWORD             = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si, es, di\r
+\r
+        mov     ax, [Y]                 ; Get pixel address\r
+        mul     [mx_BytesPerLine]\r
+        mov     di, [X]\r
+        .shr    di, 2\r
+        add     di, ax\r
+        mov     es, [mx_VideoSegment]\r
+\r
+        lds     si, [Image]             ; Get tile address\r
+        .shr    [Width], 2              ; Number of bytes per plane\r
+        mov     cl, BYTE PTR [X]\r
+        and     cl, 3\r
+        mov     ah, 11h                 ; AH = plane mask\r
+        shl     ah, cl                  ; Align mask to first plane\r
+\r
+        mov     [Y], 4                  ; Number of planes\r
+        mov     bx, [mx_BytesPerLine]\r
+        sub     bx, [Width]             ; Extra bytes per line\r
+@@Loop:\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax                  ; Set write plane\r
+        mov     [X], di                 ; Save video offset\r
+        mov     dx, [Height]\r
+@@Loop2:\r
+        mov     cx, [Width]             ; Number of bytes to move\r
+\r
+; Move one line\r
+        jcxz    @@MoveLineDone\r
+@@MoveLineLoop:\r
+        mov     al, ds:[si]\r
+        test    al, al\r
+        jz      @@MoveLineNext\r
+        mov     es:[di], al\r
+@@MoveLineNext:\r
+        inc     si\r
+        inc     di\r
+        dec     cx\r
+        jnz     @@MoveLineLoop\r
+@@MoveLineDone:\r
+\r
+        add     di, bx                  ; Move video offset to next line\r
+        dec     dx                      ; Done all lines?\r
+        jnz     @@Loop2                 ; No, continue\r
+        mov     di, [X]                 ; Restore video offset\r
+        rol     ah, 1                   ; Next plane\r
+        adc     di, 0                   ; Bump video offset if needed\r
+        dec     [Y]                     ; Any plane left?\r
+        jnz     @@Loop                  ; Yes, keep looping\r
+\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxTransPutTile  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxvs.asm b/16/x_/mxvs.asm
new file mode 100755 (executable)
index 0000000..992eaba
--- /dev/null
@@ -0,0 +1,110 @@
+;-----------------------------------------------------------\r
+;\r
+; MXVS.ASM - Set/get virtual screen\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxSetVirtualScreen\r
+PUBLIC  mxGetVirtualScreen\r
+\r
+EXTRN   mxRowAddress            : FAR\r
+EXTRN   mxSetSysClipRegion      : FAR\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_CodeSegment  : WORD\r
+\r
+mx_VirtualWidth         DW      ?       ; Virtual screen size\r
+mx_VirtualHeight        DW      ?\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the virtual screen.\r
+;\r
+; Input:\r
+;       Width   = virtual screen width\r
+;       Height  = virtual screen height\r
+; Output:\r
+;       0 on success, else invalid parameters\r
+;\r
+mxSetVirtualScreen      PROC    FAR\r
+        ARG     Height:WORD,            \\r
+                Width:WORD              = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds\r
+\r
+; Set DS to code segment\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, 1                   ; Assume an error\r
+        cmp     [Width], 320            ; Check width\r
+        jb      @@Exit\r
+        push    ax                      ; Save return code\r
+        mov     dx, 0004h\r
+        xor     ax, ax                  ; DX:AX = 256K\r
+        div     [Width]                 ; Max height in AX\r
+        cmp     [Height], ax\r
+        pop     ax                      ; Restore return code\r
+        ja      @@Exit                  ; Exit if bad heigth\r
+\r
+        mov     ax, [Width]\r
+        and     ax, 0FFF8h              ; Align to byte\r
+        mov     [mx_VirtualWidth], ax\r
+        shr     ax, 1\r
+        shr     ax, 1\r
+        mov     [mx_BytesPerLine], ax\r
+        shr     ax, 1\r
+        push    ax\r
+        call    mxRowAddress            ; Set row address\r
+        mov     ax, [Height]\r
+        mov     [mx_VirtualHeight], ax\r
+\r
+        push    [Width]\r
+        push    [Height]\r
+        call    mxSetSysClipRegion\r
+        xor     ax, ax\r
+\r
+@@Exit:\r
+        .pop    ds\r
+        .leave  ARG_SIZE\r
+mxSetVirtualScreen      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current virtual screen size.\r
+;\r
+; Input:\r
+;       Width   = pointer to virtual screen width\r
+;       Height  = pointer to virtual screen height\r
+; Output:\r
+;       none\r
+;\r
+mxGetVirtualScreen      PROC    FAR\r
+        ARG     Height:DWORD,           \\r
+                Width:DWORD             = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si\r
+\r
+        mov     ax, [mx_VirtualWidth]\r
+        lds     si, [Width]\r
+        mov     ds:[si], ax\r
+        mov     ax, [mx_VirtualHeight]\r
+        lds     si, [Height]\r
+        mov     ds:[si], ax\r
+\r
+        xor     ax, ax\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetVirtualScreen      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxwd.asm b/16/x_/mxwd.asm
new file mode 100755 (executable)
index 0000000..de55208
--- /dev/null
@@ -0,0 +1,28 @@
+;-----------------------------------------------------------\r
+;\r
+; MXWD.ASM - Wait display function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxWaitDisplay\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Waits for display start.\r
+;\r
+mxWaitDisplay   PROC    FAR\r
+        mov     dx, STATUS\r
+@@1:    in      al, dx\r
+        test    al, 08h\r
+        jnz     @@1\r
+        ret\r
+mxWaitDisplay   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxwm.asm b/16/x_/mxwm.asm
new file mode 100755 (executable)
index 0000000..0615885
--- /dev/null
@@ -0,0 +1,39 @@
+;-----------------------------------------------------------\r
+;\r
+; MXWM.ASM - Set write mode function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxWriteMode\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the write mode.\r
+;\r
+; Input:\r
+;       Mode    = write mode (0,1,2,3)\r
+; Output:\r
+;       none\r
+;\r
+mxWriteMode     PROC    FAR\r
+        ARG     Mode:BYTE:2     = ARG_SIZE\r
+        .enter  0\r
+\r
+        mov     dx, GDC\r
+        mov     ah, [Mode]\r
+        and     ah, 00000011b\r
+        or      ah, 01000000b\r
+        mov     al, 05h\r
+        out     dx, ax\r
+\r
+        .leave  ARG_SIZE\r
+mxWriteMode     ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxwp.asm b/16/x_/mxwp.asm
new file mode 100755 (executable)
index 0000000..19ca99d
--- /dev/null
@@ -0,0 +1,62 @@
+;-----------------------------------------------------------\r
+;\r
+; MXWP.ASM - Set write/read plane functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxWritePlane\r
+PUBLIC  mxReadPlane\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the write plane(s).\r
+;\r
+; Input:\r
+;       Plane   = write plane(s) to set (bit 0 enables plane 0,\r
+;                 bit 1 enables plane 1 and so on, different planes\r
+;                 may be selected at the same time)\r
+; Output:\r
+;       none\r
+;\r
+mxWritePlane    PROC    FAR\r
+        ARG     Plane:BYTE:2    = ARG_SIZE\r
+        .enter  0\r
+\r
+        mov     ah, [Plane]\r
+        and     ah, 00001111b           ; Mask off unused bits\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax\r
+\r
+        .leave  ARG_SIZE\r
+mxWritePlane    ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the read plane.\r
+;\r
+; Input:\r
+;       Plane   = read plane to set (0,1,2,3)\r
+; Output:\r
+;       none\r
+;\r
+mxReadPlane     PROC    FAR\r
+        ARG     Plane:BYTE:2    = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        mov     al, 04h\r
+        mov     ah, [Plane]\r
+        and     ah, 0000011b            ; Mask off unused bits\r
+        mov     dx, GDC\r
+        out     dx, ax\r
+        .leave  ARG_SIZE\r
+mxReadPlane     ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/mxwr.asm b/16/x_/mxwr.asm
new file mode 100755 (executable)
index 0000000..bd29fe5
--- /dev/null
@@ -0,0 +1,28 @@
+;-----------------------------------------------------------\r
+;\r
+; MXWR.ASM - Wait vertical retrace function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxWaitRetrace\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Waits for vertical retrace start.\r
+;\r
+mxWaitRetrace   PROC    FAR\r
+        mov     dx, STATUS\r
+@@1:    in      al,dx\r
+        test    al, 08h\r
+        jz      @@1\r
+        ret\r
+mxWaitRetrace   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/x_/readme.txt b/16/x_/readme.txt
new file mode 100755 (executable)
index 0000000..306e8b9
--- /dev/null
@@ -0,0 +1,8 @@
+ModeX - A graphical library for DOS programs\r
+Copyright (c) 1993-1994 Alessandro Scotti\r
+http://www.ascotti.org/\r
+\r
+Please look at the above site in the "Art of..." and\r
+then in the "Old programs" section for more information.\r
+\r
+\r
diff --git a/16/xlib/demo1.exe b/16/xlib/demo1.exe
deleted file mode 100755 (executable)
index 7d8a4d6..0000000
Binary files a/16/xlib/demo1.exe and /dev/null differ
diff --git a/16/xlib/demo2.exe b/16/xlib/demo2.exe
deleted file mode 100755 (executable)
index d6dfd06..0000000
Binary files a/16/xlib/demo2.exe and /dev/null differ
diff --git a/16/xlib/demo3.exe b/16/xlib/demo3.exe
deleted file mode 100755 (executable)
index ef3a06a..0000000
Binary files a/16/xlib/demo3.exe and /dev/null differ
diff --git a/16/xlib/demo4.exe b/16/xlib/demo4.exe
deleted file mode 100755 (executable)
index 54c567d..0000000
Binary files a/16/xlib/demo4.exe and /dev/null differ
diff --git a/16/xlib/demo5.exe b/16/xlib/demo5.exe
deleted file mode 100755 (executable)
index 30993d2..0000000
Binary files a/16/xlib/demo5.exe and /dev/null differ
diff --git a/16/xlib/demo6.exe b/16/xlib/demo6.exe
deleted file mode 100755 (executable)
index 7e26f1f..0000000
Binary files a/16/xlib/demo6.exe and /dev/null differ
diff --git a/16/xlib/demo7.exe b/16/xlib/demo7.exe
deleted file mode 100755 (executable)
index 3762184..0000000
Binary files a/16/xlib/demo7.exe and /dev/null differ
diff --git a/16/xlib/demo8.exe b/16/xlib/demo8.exe
deleted file mode 100755 (executable)
index 98c480e..0000000
Binary files a/16/xlib/demo8.exe and /dev/null differ
index cba0dcac040881c9b129875c19142a21bebc4b0c..d1ec5db3a9062ecfaa9cc7fb626549ab71bd13ca 100755 (executable)
@@ -150,6 +150,9 @@ xvsync.$(OBJ)  : xvsync.asm#                        xvsync.inc xlib.inc     model.inc
 xfill.$(OBJ)   : xfill.asm#                            xfill.inc       xlib.inc                model.inc\r
        $(CC) -c $(CFLAGS) xfill.asm#   xfill.inc       xlib.inc                model.inc\r
 \r
+xbezier.$(OBJ): xbezier.asm\r
+       $(CC) -c $(CFLAGS) xbezier.asm\r
+\r
 #\r
 #other~\r
 #\r
index 0aded8e95f164e8b5b25465c66bcf9e48876226e..f35b3faeae75f1eca1c9585af43fa9f478a2b92f 100755 (executable)
@@ -1,20 +1,22 @@
-/*;IFDEF s\r
+IFDEF s\r
 ;  DISPLAY "XLIB04 Small Model"\r
-;  .model small\r
-;ELSE\r
-;  IFDEF c\r
+  .model small\r
+ELSE\r
+  IFDEF c\r
 ;    DISPLAY "XLIB04 Compact Model"\r
-;    .model compact\r
-;  ELSE\r
-;     IFDEF l\r
+    .model compact\r
+  ELSE\r
+     IFDEF l\r
 ;       DISPLAY "XLIB04 Large Model"\r
-;      .model large\r
-;     ELSE\r
+      .model large\r
+     ELSE\r
+          IFDEF h\r
+      .model huge\r
+               ELSE\r
 ;       DISPLAY "WARNING: Model was not defined at the command line."\r
 ;       DISPLAY "         Using default small model ie /ds         "\r
 ;       DISPLAY "         Include in TASM commandline either /ds, /dc or /dl"\r
-;;       .model small\r
-;     ENDIF\r
-;  ENDIF\r
-;ENDIF\r
-*/\r
+       .model small\r
+     ENDIF\r
+  ENDIF\r
+ENDIF\r
index f39c9a322ea7e8333511cf95ea546ce3237e7353..490b2635c2e2b234b370f6fc99f474a0e3112681 100755 (executable)
@@ -42,7 +42,7 @@ COMMENT $
 \r
 $\r
 \r
-LOCALS\r
+.LOCALS\r
 .8086\r
 \r
 include model.inc\r
index 40a0777591098b80baec1e79fe3b7feeacebfe30..253e237cd815f42fc89d5c27df54651d4f57b4e1 100755 (executable)
@@ -430,4 +430,3 @@ _f_filelength endp
 \r
 \r
        end\r
-\r
index 3dbfa758db4f3701760f103932034c80f446fa15..e352f3cf718463cf3a9f4d113d9851d9ea1753ab 100755 (executable)
 \r
 ;\r
 \r
-;.LOCALS\r
+;.global\r
 ;.8086\r
 \r
 ; First lets find out what memory model to use\r
-\r
-include model.inc\r
+;.model huge\r
+;include model.inc\r
 \r
 \r
 AC_INDEX        equ  03c0h   ;Attribute controller index register\r
@@ -162,5 +162,3 @@ WaitNotVsync2:
        global _VsyncPaletteStart       :word\r
        global _VsyncPaletteCount       :word\r
        global _VsyncPaletteBuffer      :byte\r
-\r
-\r
index 6c9c5c56c0421726f7355e80805b13312fb278eb..910c1fc9c13be1b844e81ab8586ed288c2d208cb 100755 (executable)
@@ -26,9 +26,10 @@ ModeXAddr       macro
        mov     dx,[_ScrnLogicalByteWidth]\r
        mul     dx\r
        pop     dx\r
-       shr     bx,2\r
+       shr     bx,1\r
+       shr     bx,1\r
        add     bx,ax\r
-       add     bx,[PgOffs]\r
+       add     bx,[bp+14]\r
        and     cl,3\r
        endm\r
 \r
@@ -44,7 +45,7 @@ ModeXAddr       macro
 ;\r
 \r
 _x_line        proc\r
-ARG     x1:word,y1:word,x2:word,y2:word,Color:word,PgOffs:word\r
+;ARG     x1:word,y1:word,x2:word,y2:word,Color:word,PgOffs:word\r
 LOCAL   vertincr:word,incr1:word,incr2:word,routine:word=LocalStk\r
        push    bp              ; Set up stack frame\r
        mov     bp,sp\r
@@ -60,8 +61,8 @@ LOCAL   vertincr:word,incr1:word,incr2:word,routine:word=LocalStk
 ; check for vertical line\r
 \r
        mov     si,[_ScrnLogicalByteWidth]\r
-       mov     cx,[x2]\r
-       sub     cx,[x1]\r
+       mov     cx,[bp+8]\r
+       sub     cx,[bp+4]\r
        jz      VertLine\r
 \r
 ; force x1 < x2\r
@@ -70,19 +71,19 @@ LOCAL   vertincr:word,incr1:word,incr2:word,routine:word=LocalStk
 \r
        neg     cx\r
 \r
-       mov     bx,[x2]\r
-       xchg    bx,[x1]\r
-       mov     [x2],bx\r
+       mov     bx,[bp+8]\r
+       xchg    bx,[bp+4]\r
+       mov     [bp+8],bx\r
 \r
-       mov     bx,[y2]\r
-       xchg    bx,[y1]\r
-       mov     [y2],bx\r
+       mov     bx,[bp+10]\r
+       xchg    bx,[bp+6]\r
+       mov     [bp+10],bx\r
 \r
 ; calc dy = abs(y2 - y1)\r
 \r
 L01:\r
-       mov     bx,[y2]\r
-       sub     bx,[y1]\r
+       mov     bx,[bp+10]\r
+       sub     bx,[bp+6]\r
        jnz     short skip\r
        jmp     HorizLine\r
 skip:          jns     L03\r
@@ -113,14 +114,17 @@ L04:
 ; calc first pixel address\r
 \r
        push    cx\r
-       mov     ax,[y1]\r
-       mov     bx,[x1]\r
+       mov     ax,[bp+6]\r
+       mov     bx,[bp+4]\r
        ModeXAddr\r
        mov     di,bx\r
        mov     al,1\r
        shl     al,cl\r
        mov     ah,al           ; duplicate nybble\r
-       shl     al,4\r
+       shl     al,1\r
+       shl     al,1\r
+       shl     al,1\r
+       shl     al,1\r
        add     ah,al\r
        mov     bl,ah\r
        pop     cx\r
@@ -130,8 +134,8 @@ L04:
 ; routine for verticle lines\r
 \r
 VertLine:\r
-       mov     ax,[y1]\r
-       mov     bx,[y2]\r
+       mov     ax,[bp+6]\r
+       mov     bx,[bp+10]\r
        mov     cx,bx\r
        sub     cx,ax\r
        jge     L31\r
@@ -140,7 +144,7 @@ VertLine:
 \r
 L31:\r
        inc     cx\r
-       mov     bx,[x1]\r
+       mov     bx,[bp+4]\r
        push    cx\r
        ModeXAddr\r
 \r
@@ -149,7 +153,7 @@ L31:
        mov     al,MAP_MASK\r
        out     dx,ax\r
        pop     cx\r
-       mov     ax, word ptr [Color]\r
+       mov     ax, word ptr [bp+12]\r
 \r
 ; draw the line\r
 \r
@@ -164,15 +168,15 @@ L32:
 HorizLine:\r
        push    ds\r
 \r
-       mov     ax,[y1]\r
-       mov     bx,[x1]\r
+       mov     ax,[bp+6]\r
+       mov     bx,[bp+4]\r
        ModeXAddr\r
 \r
        mov     di,bx     ; set dl = first byte mask\r
        mov     dl,00fh\r
        shl     dl,cl\r
 \r
-       mov     cx,[x2] ; set dh = last byte mask\r
+       mov     cx,[bp+8] ; set dh = last byte mask\r
        and     cl,3\r
        mov     dh,00eh\r
        shl     dh,cl\r
@@ -180,17 +184,19 @@ HorizLine:
 \r
 ; determine byte offset of first and last pixel in line\r
 \r
-       mov     ax,[x2]\r
-       mov     bx,[x1]\r
+       mov     ax,[bp+8]\r
+       mov     bx,[bp+4]\r
 \r
-       shr     ax,2     ; set ax = last byte column\r
-       shr     bx,2    ; set bx = first byte column\r
+       shr     ax,1     ; set ax = last byte column\r
+       shr     bx,1    ; set bx = first byte column\r
+       shr     ax,1     ; set ax = last byte column\r
+       shr     bx,1    ; set bx = first byte column\r
        mov     cx,ax    ; cx = ax - bx\r
        sub     cx,bx\r
 \r
        mov     ax,dx    ; mov end byte masks to ax\r
        mov     dx,SC_INDEX ; setup dx for VGA outs\r
-       mov     bx, [Color]\r
+       mov     bx, [bp+12]\r
 \r
 ; set pixels in leftmost byte of line\r
 \r
@@ -231,7 +237,7 @@ L44:
 \r
 LoSlopeLine:\r
        mov     al,MAP_MASK\r
-       mov     bh,byte ptr [Color]\r
+       mov     bh,byte ptr [bp+12]\r
 L10:\r
        mov     ah,bl\r
 \r
@@ -283,7 +289,7 @@ HiSlopeLine:
        mov     al,MAP_MASK\r
 L21:            out    dx,ax\r
        push    ax\r
-       mov     ax,[Color]\r
+       mov     ax,[bp+12]\r
        mov     es:[di],al\r
        pop     ax\r
        add     di,bx\r
@@ -314,4 +320,3 @@ Lexit:
 _x_line        endp\r
 \r
 end\r
-\1a
\ No newline at end of file
index a8fd41842af94371f7bab962c121641ec57000f3..cdb174fdd42ca48111ad00c4305d7834d618fef1 100755 (executable)
 ;                      and tripple buffering - Tore Jahn Bastiansen\r
 ;                      (toreba@ifi.uio.no) for the\r
 ;-----------------------------------------------------------------------\r
-\r
-\r
 include xlib.inc\r
 include xmain.inc\r
 \r
 \r
-       .data\r
+       _DATA           SEGMENT WORD PUBLIC USE16 'DATA'\r
+;.data\r
 \r
 \r
 ; Mode X CRTC register tweaks for various resolutions\r
 \r
 \r
-LABEL X256Y200 word\r
+X256Y200 LABEL word\r
                db      0e3h    ; dot clock\r
                db      8       ; Number of CRTC Registers to update\r
        dw      05f00h  ; horz total\r
@@ -49,7 +48,7 @@ LABEL X256Y200 word
        dw      200\r
 \r
 \r
-LABEL X256Y240 word\r
+X256Y240 label word\r
        db      0e3h    ; dot clock\r
        db      16      ; Number of CRTC Registers to update\r
        dw      05f00h  ; horz total\r
@@ -157,7 +156,7 @@ X376Y282 label word
        dw      376\r
        dw      282\r
 \r
-LABEL X256Y400 word\r
+X256Y400 label word\r
        db      0e3h    ; dot clock\r
        db      8       ; Number of CRTC Registers to update\r
        dw      05f00h  ; horz total\r
@@ -173,7 +172,7 @@ LABEL X256Y400 word
        dw      400\r
 \r
 \r
-LABEL X256Y480 word\r
+X256Y480 label word\r
        db      0e3h    ; dot clock\r
        db      16      ; Number of CRTC Registers to update\r
                dw      05f00h  ; horz total\r
@@ -439,6 +438,9 @@ PARAM_COUNT equ ($-PARAMS)
 \r
 DoubleScanFlag db ?     ; Flag to indicate double scanned mode\r
 \r
+_DATA          ENDS\r
+\r
+\r
        .code\r
 \r
 ;-------------------------------------------------------------------------\r
@@ -459,7 +461,9 @@ SetLogicalScrWidth proc
        mov   ax,bx                        ; no - set logical width = physical\r
 \r
 @@ValidLogicalWidth:\r
-       shr   ax,3\r
+       shr   ax,1\r
+       shr   ax,1\r
+       shr   ax,1\r
        out   dx,al\r
 \r
        ; The EXACT logical pixel width may not have been possible since\r
@@ -472,10 +476,12 @@ SetLogicalScrWidth proc
        mov   [_RightClip],ax             ; Set default Right clip column\r
                                          ; screen\r
        sub   ax,[_ScrnPhysicalByteWidth] ; Calculate and store Max X position\r
-       shl   ax,2                        ; of physical screen in virtual\r
+       shl   ax,1                        ; of physical screen in virtual\r
+       shl   ax,1                        ; of physical screen in virtual\r
        mov   [_MaxScrollX],ax            ; screen in pixels\r
        mov   ax,bx                       ; set ax to byte width of virt scrn\r
-       shl   ax,2                        ; convert to pixels\r
+       shl   ax,1                        ; convert to pixels\r
+       shl   ax,1                        ; convert to pixels\r
        mov   [_ScrnLogicalPixelWidth],ax ; store virt scrn pixel width\r
        mov   cx,ax                       ; save ax (return value)\r
 \r
@@ -550,7 +556,7 @@ clear_vram endp
 ; parts adapted from M. Abrash code.\r
 ;------------------------------------------------------------------------\r
 _x_set_mode proc\r
-       ARG   mode:word,logicalscrwidth:word\r
+       ;;arg   mode:word,logicalscrwidth:word\r
        push  bp      ;preserve caller's stack frame\r
        mov   bp,sp\r
 \r
@@ -565,7 +571,7 @@ _x_set_mode proc
        mov   cx,PARAM_COUNT\r
        rep   stosb\r
 \r
-       mov   cx,[mode]\r
+       mov   cx,[BP+4]\r
        cmp   cx,LAST_X_MODE        ; have we selected a valid mode\r
        jle   @@ValidMode           ; Yes !\r
 \r
@@ -657,7 +663,8 @@ _x_set_mode proc
        mov   [_SplitScrnScanLine],ax       ; No splitscrn ==\r
                                            ; splitscrn=PhysicalscrnHeight\r
        mov   bx,ax                         ; Copy width for later use\r
-       shr   ax,2                          ; Convert to byte width\r
+       shr   ax,1                          ; Convert to byte width\r
+       shr   ax,1                          ; Convert to byte width\r
        mov   [_ScrnPhysicalByteWidth],ax   ; Store for later use\r
        lodsw                               ; Load Screen Phys. Height\r
        mov   [_ScrnPhysicalHeight],ax      ; Store for later use\r
@@ -665,7 +672,7 @@ _x_set_mode proc
 \r
        ;  Mode X is set, now set the required logical page width.\r
 \r
-       mov     cx,[logicalscrwidth]\r
+       mov     cx,[BP+6]\r
 \r
        call    SetLogicalScrWidth\r
 \r
@@ -687,10 +694,10 @@ _x_set_mode endp
 ; Written by Themie Gouthas\r
 ;----------------------------------------------------------------------\r
 _x_select_default_plane proc\r
-ARG Plane:byte\r
+       ;arg Plane:byte\r
        push bp\r
        mov  bp,sp       ; set up stack frame\r
-       mov  cl,byte ptr [Plane]\r
+       mov  cl,byte ptr [bp+4]\r
 \r
        ; SELECT WRITE PLANE\r
        and  cl,011b              ;CL = plane\r
@@ -727,7 +734,7 @@ _x_select_default_plane endp
 ;----------------------------------------------------------------------\r
 \r
 _x_set_splitscreen proc\r
-       ARG Line:word\r
+       ;arg Line:word\r
        push bp\r
        mov  bp,sp       ; set up stack frame\r
        push si\r
@@ -769,7 +776,7 @@ _x_set_splitscreen proc
        mov  [_PhysicalStartPixelX],ax  ; offset within virtual screen\r
        mov  [_PhysicalStartY],ax\r
        mov  [_SplitScrnActive],TRUE\r
-       mov  ax,[Line]\r
+       mov  ax,[bp+4]\r
        jns  @@NotNeg    ; Check that Split Scrn start scan line is +ve\r
 \r
        mov  ax,0        ; Since -ve set to 0\r
@@ -804,7 +811,10 @@ _x_set_splitscreen proc
 \r
        mov  ah,bh\r
        and  ah,1\r
-       shl  ah,4\r
+       shl  ah,1\r
+       shl  ah,1\r
+       shl  ah,1\r
+       shl  ah,1\r
        mov  al,OVERFLOW     ; Bit 4 of overflow register = Bit 8 of split\r
        out  dx,al           ; screen scan line,\r
        inc  dx              ; So using readability of VGA registers\r
@@ -816,7 +826,9 @@ _x_set_splitscreen proc
        dec  dx\r
        mov  ah,bh\r
        and  ah,2\r
-       ror  ah,3\r
+       ror  ah,1\r
+       ror  ah,1\r
+       ror  ah,1\r
        mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =\r
        out  dx,al             ; Bit 9 of split screen scan line\r
        inc  dx                ; As we did before, update the apropriate\r
@@ -846,9 +858,9 @@ _x_set_splitscreen proc
 \r
        mov  [_ScrnLogicalHeight],ax     ; Save Screen Logical Height\r
        cmp   ax,[_BottomClip]\r
-       jle   @@BottomClipOK             ; Adjust Clip Rectangle if necessary\r
+       jle   @@BottomClipOK2             ; Adjust Clip Rectangle if necessary\r
        mov   [_BottomClip],ax\r
-@@BottomClipOK:\r
+@@BottomClipOK2:\r
        sub  ax,[_SplitScrnScanLine]     ; Update the maximum Y position of\r
        mov  [_MaxScrollY],ax            ; Physical screen in logical screen\r
 \r
@@ -875,14 +887,14 @@ _x_set_splitscreen      endp
 ;------------------------------------------------------------------------\r
 \r
 _x_page_flip proc\r
-       ARG x:word,y:word\r
+       ;arg x:word,y:word\r
        push  bp                  ;preserve caller's stack frame\r
        mov   bp,sp               ;point to local stack frame\r
        push  si\r
 \r
-       mov  si,[x]\r
+       mov  si,[bp+4]\r
        mov  ax,[_ScrnLogicalByteWidth]     ; Calculate Offset increment\r
-       mov  cx,[y]\r
+       mov  cx,[bp+6]\r
        mul  cx                             ; for Y\r
        cmp  [_DoubleBufferActive],TRUE     ; Do we have double buffering ?\r
        je   @@DoubleBuffer\r
@@ -931,14 +943,14 @@ _x_page_flip endp
 ; Parts addapted from M. Abrash code published in DDJ Mag.\r
 ;------------------------------------------------------------------------\r
 _x_set_start_addr proc\r
-       ARG x:word,y:word\r
+       ;arg x:word,y:word\r
        push bp\r
        mov  bp,sp\r
        push si\r
 \r
-       mov  si,[x]\r
+       mov  si,[bp+4]\r
        mov  ax,[_ScrnLogicalByteWidth]     ; Calculate Offset increment\r
-       mov  cx,[y]                         ; for Y\r
+       mov  cx,[bp+6]                         ; for Y\r
        mul  cx\r
        cmp  [_DoubleBufferActive],TRUE     ; Do we have double buffering ?\r
        je   @@PageResolution\r
@@ -958,7 +970,8 @@ PageFlipEntry2:
 \r
 @@AddColumn:\r
        mov  cx,si\r
-       shr  cx,2\r
+       shr  cx,1\r
+       shr  cx,1\r
        mov  [_PhysicalStartByteX],cx\r
        add  ax,cx                          ; add the column offset for X\r
        mov  bh,al                          ; setup CRTC start addr regs and\r
@@ -1052,14 +1065,14 @@ _x_hide_splitscreen proc
        cmp  [_SplitScrnActive],TRUE\r
        je   @@SplitScreenEnabled\r
 \r
-@@error:\r
+@@error0:\r
        mov  [_ErrorValue],ERROR\r
        pop  bp\r
        ret\r
 \r
 @@SplitScreenEnabled:\r
        cmp  [_CurrXMode],4          ; Do nothing for Modes > 2\r
-       jg   @@error\r
+       jg   @@error0\r
        mov  bx,[_ScrnPhysicalHeight]\r
 \r
        mov  ax,[_ScrnLogicalHeight]\r
@@ -1069,10 +1082,10 @@ _x_hide_splitscreen proc
        mov  [_SplitScrnVisibleHeight],ax\r
 \r
        or    [DoubleScanFlag],0\r
-       jz    @@NotDoubleScanned\r
+       jz    @@NotDoubleScanned0\r
        shl   bx,1\r
        dec   bx\r
-@@NotDoubleScanned:\r
+@@NotDoubleScanned0:\r
        ;mov  cl,[DoubleScanFlag]  ; Compensate for double scanned modes\r
        ;shl  bx,cl\r
 \r
@@ -1086,7 +1099,10 @@ _x_hide_splitscreen proc
 \r
        mov  ah,bh\r
        and  ah,1\r
-       shl  ah,4\r
+       shl  ah,1\r
+       shl  ah,1\r
+       shl  ah,1\r
+       shl  ah,1\r
        mov  al,OVERFLOW  ; Bit 4 of overflow register = Bit 8 of split\r
        out  dx,al        ; screen scan line,\r
        inc  dx           ; So using readability of VGA registers\r
@@ -1098,7 +1114,9 @@ _x_hide_splitscreen proc
        dec  dx\r
        mov  ah,bh\r
        and  ah,2\r
-       ror  ah,3\r
+       ror  ah,1\r
+       ror  ah,1\r
+       ror  ah,1\r
        mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =\r
        out  dx,al             ; Bit 9 of split screen scan line\r
        inc  dx                ; As we did before, update the apropriate\r
@@ -1108,7 +1126,7 @@ _x_hide_splitscreen proc
        out  dx,al\r
        sti                  ; Registers are set, so interrupts are safe\r
 \r
-@@done:\r
+@@done0:\r
 \r
        mov  [_ErrorValue],OK\r
        pop  bp\r
@@ -1140,16 +1158,16 @@ _x_show_splitscreen proc
        mov  bp,sp\r
 \r
        cmp  [_SplitScrnActive],TRUE\r
-       je   @@SplitScreenEnabled\r
+       je   @@SplitScreenEnabled0\r
 \r
-@@error:\r
+@@error1:\r
        mov  [_ErrorValue],ERROR\r
        pop  bp\r
        ret\r
 \r
-@@SplitScreenEnabled:\r
+@@SplitScreenEnabled0:\r
        cmp  [_CurrXMode],4          ; Do nothing for Modes > 2\r
-       jg   @@error\r
+       jg   @@error1\r
 \r
        mov  bx,[_SplitScrnScanLine]\r
        mov  ax,[_ScrnLogicalHeight] ; Update Max Scroll Y\r
@@ -1161,10 +1179,10 @@ _x_show_splitscreen proc
        mov  [_SplitScrnVisibleHeight],ax\r
 \r
        or    [DoubleScanFlag],0\r
-       jz    @@NotDoubleScanned\r
+       jz    @@NotDoubleScanned1\r
        shl   bx,1\r
        dec   bx\r
-@@NotDoubleScanned:\r
+@@NotDoubleScanned1:\r
        ;mov  cl,[DoubleScanFlag]  ; Compensate for double scanned modes\r
        ;shl  bx,cl\r
        WaitVsyncStart               ; wait for vertical retrace\r
@@ -1177,7 +1195,10 @@ _x_show_splitscreen proc
 \r
        mov  ah,bh\r
        and  ah,1\r
-       shl  ah,4\r
+       shl  ah,1\r
+       shl  ah,1\r
+       shl  ah,1\r
+       shl  ah,1\r
        mov  al,OVERFLOW  ; Bit 4 of overflow register = Bit 8 of split\r
        out  dx,al        ; screen scan line,\r
        inc  dx           ; So using readability of VGA registers\r
@@ -1189,7 +1210,9 @@ _x_show_splitscreen proc
        dec  dx\r
        mov  ah,bh\r
        and  ah,2\r
-       ror  ah,3\r
+       ror  ah,1\r
+       ror  ah,1\r
+       ror  ah,1\r
        mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =\r
        out  dx,al             ; Bit 9 of split screen scan line\r
        inc  dx                ; As we did before, update the apropriate\r
@@ -1199,7 +1222,7 @@ _x_show_splitscreen proc
        out  dx,al\r
        sti                  ; Registers are set, so interrupts are safe\r
 \r
-@@Done:\r
+@@Done1:\r
        mov  [_ErrorValue],0\r
        pop  bp\r
        ret\r
@@ -1229,24 +1252,24 @@ _x_show_splitscreen endp
 \r
 \r
 _x_adjust_splitscreen proc\r
-       ARG   ScanLine\r
+       ;arg   ScanLine\r
        push bp\r
        mov  bp,sp\r
 \r
        cmp  [_SplitScrnActive],TRUE\r
-       je   @@SplitScreenEnabled\r
+       je   @@SplitScreenEnabled1\r
 \r
-@@error:\r
+@@error2:\r
        mov  [_ErrorValue],ERROR\r
        pop  bp\r
        ret\r
 \r
-@@SplitScreenEnabled:\r
+@@SplitScreenEnabled1:\r
        cmp  [_CurrXMode],4          ; Do nothing for Modes > 2\r
-       jg   @@error\r
-       mov  bx,[ScanLine]            ; Is the required starting scan line\r
+       jg   @@error2\r
+       mov  bx,[bp+4]            ; Is the required starting scan line\r
        cmp  bx,[_SplitScrnScanLine]  ; valid ?\r
-       js   @@Done                   ; No - Then do nothing\r
+       js   @@Done2                   ; No - Then do nothing\r
 \r
 @@ValidScanLine:\r
 \r
@@ -1259,10 +1282,10 @@ _x_adjust_splitscreen proc
        mov  [_SplitScrnVisibleHeight],ax\r
 \r
        or    [DoubleScanFlag],0\r
-       jz    @@NotDoubleScanned\r
+       jz    @@NotDoubleScanned2\r
        shl   bx,1\r
        dec   bx\r
-@@NotDoubleScanned:\r
+@@NotDoubleScanned2:\r
        ;mov  cl,[DoubleScanFlag]   ; Compensate for double scanned modes\r
        ;shl  bx,cl\r
 \r
@@ -1277,7 +1300,10 @@ _x_adjust_splitscreen proc
 \r
        mov  ah,bh\r
        and  ah,1\r
-       shl  ah,4\r
+       shl  ah,1\r
+       shl  ah,1\r
+       shl  ah,1\r
+       shl  ah,1\r
        mov  al,OVERFLOW  ; Bit 4 of overflow register = Bit 8 of split\r
        out  dx,al        ; screen scan line,\r
        inc  dx           ; So using readability of VGA registers\r
@@ -1289,7 +1315,9 @@ _x_adjust_splitscreen proc
        dec  dx\r
        mov  ah,bh\r
        and  ah,2\r
-       ror  ah,3\r
+       ror  ah,1\r
+       ror  ah,1\r
+       ror  ah,1\r
        mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =\r
        out  dx,al             ; Bit 9 of split screen scan line\r
        inc  dx                ; As we did before, update the apropriate\r
@@ -1298,7 +1326,7 @@ _x_adjust_splitscreen proc
        or   al,ah\r
        out  dx,al\r
        sti                    ; Registers are set, so interrupts are safe\r
-@@Done:\r
+@@Done2:\r
        mov  [_ErrorValue],OK\r
        pop   bp\r
        ret\r
@@ -1330,7 +1358,7 @@ _x_adjust_splitscreen endp
 \r
 \r
 _x_set_doublebuffer proc\r
-          ARG PageHeight:word\r
+          ;arg PageHeight:word\r
           push  bp\r
           mov   bp,sp\r
 \r
@@ -1346,7 +1374,7 @@ _x_set_doublebuffer proc
           mov   ax,[_ScrnLogicalHeight] ; Set Maximum D.B. Page height to\r
           shr   ax,1                    ;   _ScrnLogicalHeight / 2\r
 \r
-          mov   bx,[PageHeight]         ; Is the require D.B. Page Height\r
+          mov   bx,[bp+4]         ; Is the require D.B. Page Height\r
           cmp   ax,bx                   ;  > the Maximum  D.B. Page Height ?\r
 \r
           js    @@InvalidHeight         ; no  - jump\r
@@ -1357,9 +1385,9 @@ _x_set_doublebuffer proc
           mov   [_ScrnLogicalHeight],ax    ; Update logical screen height to\r
                                        ;  reflect the height of a D.B. page\r
           cmp   ax,[_BottomClip]\r
-          jle   @@BottomClipOK             ; Adjust Clip Rectangle if necessary\r
+          jle   @@BottomClipOK0             ; Adjust Clip Rectangle if necessary\r
           mov   [_BottomClip],ax\r
-@@BottomClipOK:\r
+@@BottomClipOK0:\r
           push  ax\r
           mul   [_ScrnLogicalByteWidth]    ; Calculate the offset of the second\r
           mov   cx,ax                      ;  D.B. Page in video ram\r
@@ -1410,40 +1438,40 @@ _x_set_doublebuffer endp
 ;------------------------------------------------------------------------\r
 \r
 _x_set_tripplebuffer proc\r
-          ARG PageHeight:word\r
+          ;arg PageHeight:word\r
           push  bp\r
           mov   bp,sp\r
 \r
           cmp   [_DoubleBufferActive],0\r
-          jne   @@Error\r
+          jne   @@Error3\r
           cmp   [_TrippleBufferActive],0\r
-          je    @@OkToContinue\r
-@@Error:\r
+          je    @@OkToContinue3\r
+@@Error3:\r
           mov   [_ErrorValue],ERROR\r
           pop   bp\r
           ret\r
 \r
-@@OkToContinue:\r
+@@OkToContinue3:\r
           mov   [_VisiblePageIdx],0     ; Set visible Page to 0\r
           mov   ax,[_ScrnLogicalHeight] ; Set Maximum T.B. Page height to\r
           mov   bx,3\r
           xor   dx,dx\r
           idiv  bx                      ;   _ScrnLogicalHeight / 3\r
 \r
-          mov   bx,[PageHeight]         ; Is the require T.B. Page Height\r
+          mov   bx,[bp+4]         ; Is the require T.B. Page Height\r
           cmp   ax,bx                   ;  > the Maximum  T.B. Page Height ?\r
 \r
-          js    @@InvalidHeight         ; no  - jump\r
+          js    @@InvalidHeight0         ; no  - jump\r
           mov   ax,bx                   ; yes - Set the T.B. Page height to\r
                                                                         ;       to the maximum allowed.\r
 \r
-@@InvalidHeight:\r
+@@InvalidHeight0:\r
           mov   [_ScrnLogicalHeight],ax    ; Update logical screen height to\r
                                                                                ;  reflect the height of a T.B. page\r
           cmp   ax,[_BottomClip]\r
-          jle   @@BottomClipOK             ; Adjust Clip Rectangle if necessary\r
+          jle   @@BottomClipOK1             ; Adjust Clip Rectangle if necessary\r
           mov   [_BottomClip],ax\r
-@@BottomClipOK:\r
+@@BottomClipOK1:\r
           push  ax\r
           mul   [_ScrnLogicalByteWidth]    ; Calculate the offset of the second\r
           mov   cx,ax                      ;  D.B. Page in video ram\r
@@ -1489,19 +1517,19 @@ _x_set_tripplebuffer endp
 ;------------------------------------------------------------------------\r
 \r
 _x_set_cliprect proc\r
-ARG left:word,top:word,right:word,bottom:word\r
+;arg left:word,top:word,right:word,bottom:word\r
        push  bp\r
        mov   bp,sp\r
-       mov   ax,[left]\r
-       mov   bx,[right]\r
+       mov   ax,[bp+4]\r
+       mov   bx,[bp+8]\r
        cmp   bx,ax\r
        jns   @@CorrectXOrder\r
        xchg  bx,ax\r
 @@CorrectXOrder:\r
        mov   [_LeftClip],ax\r
        mov   [_RightClip],bx\r
-          mov   ax,[top]\r
-       mov   bx,[bottom]\r
+          mov   ax,[bp+6]\r
+       mov   bx,[bp+10]\r
        cmp   bx,ax\r
           jns   @@CorrectYOrder\r
        xchg  bx,ax\r
@@ -1536,4 +1564,4 @@ _x_wait_vsync proc
 _x_wait_vsync endp\r
 \r
 \r
-       end\r
+end\r
index 44b40fc2bd7a05b433f928af00655559058d4705..4b1f4410ff920f4f8d9920654c8ec0229172ed96 100755 (executable)
@@ -26,6 +26,6 @@
         global _x_show_splitscreen      :proc\r
         global _x_adjust_splitscreen    :proc\r
         global _x_set_doublebuffer      :proc\r
-         global _x_set_tripplebuffer     :proc\r
+        global _x_set_tripplebuffer     :proc\r
         global _x_set_cliprect          :proc\r
-        global _x_wait_vsync            :proc
\ No newline at end of file
+        global _x_wait_vsync            :proc\r
index 558f2665315d1042394faccee37a0ad0e5bad471..a27155dc83a683d3e87571e3ea06109d2329aa11 100755 (executable)
@@ -65,18 +65,18 @@ include xpal.inc
 ; Written by Themie Gouthas\r
 ;----------------------------------------------------------------------\r
 _x_get_pal_struc  proc\r
-ARG  PalBuff:dword,NumColors:word,StartColor:word\r
+;ARG  PalBuff:dword,NumColors:word,StartColor:word\r
      push  bp          ; Set up stack frame\r
      mov   bp,sp\r
      push  di\r
      push  si\r
      cld\r
 \r
-     les   di,dword ptr [PalBuff]  ; Point es:di to palette buffer\r
-     mov   si,[StartColor]         ; Store the Start Colour\r
+     les   di,dword ptr [bp+4]  ; Point es:di to palette buffer\r
+     mov   si,[bp+10]         ; Store the Start Colour\r
      mov   ax,si\r
      stosb\r
-     mov   dx,[NumColors]          ; Store the Number of Colours\r
+     mov   dx,[bp+8]          ; Store the Number of Colours\r
      mov   al,dl\r
      stosb\r
 \r
@@ -100,16 +100,16 @@ _x_get_pal_struc endp
 ; Written by Themie Gouthas\r
 ;----------------------------------------------------------------------\r
 _x_get_pal_raw proc\r
-ARG  PalBuff:dword,NumColors:word,StartColor:word\r
+;ARG  PalBuff:dword,NumColors:word,StartColor:word\r
      push  bp          ; Set up stack frame\r
      mov   bp,sp\r
      push  di\r
      push  si\r
 \r
-     les   di,dword ptr [PalBuff]  ; Point es:di to palette buffer\r
+     les   di,dword ptr [bp+4]  ; Point es:di to palette buffer\r
 \r
-     mov  si,[StartColor]\r
-     mov  cx,[NumColors]\r
+     mov  si,[bp+10]\r
+     mov  cx,[bp+8]\r
 \r
 ReadPalEntry:\r
      cld\r
index f6bed9612dc7c4264cfc9a8f281d3dc6c8b0eab8..7b7dc910d9ab70d2c5ad9eaad41be603f8d523a1 100755 (executable)
@@ -34,21 +34,21 @@ include xpoint.inc
 ;\r
 \r
 _x_put_pix  proc\r
-       ARG X:word,Y:word,PgOfs:word,Color:word\r
+       ;ARG X:word,Y:word,PgOfs:word,Color:word\r
        push bp                   ;preserve caller's stack frame\r
        mov  bp,sp                ;point to local stack frame\r
 \r
        mov  ax,[_ScrnLogicalByteWidth]\r
-       mul  [Y]                  ;offset of pixel's scan line in page\r
-       mov  bx,[X]\r
+       mul  [BP+6]                  ;offset of pixel's scan line in page\r
+       mov  bx,[BP+4]\r
        shr  bx,1                 ;X/4 = offset of pixel in scan line\r
        shr  bx,1                 ;X/4 = offset of pixel in scan line\r
        add  bx,ax                ;offset of pixel in page\r
-       add  bx,[PgOfs]           ;offset of pixel in display memory\r
+       add  bx,[BP+8]           ;offset of pixel in display memory\r
        mov  ax,SCREEN_SEG\r
        mov  es,ax                ;point ES:BX to the pixel's address\r
 \r
-       mov  cl,byte ptr [X]\r
+       mov  cl,byte ptr [BP+4]\r
        and  cl,011b              ;CL = pixel's plane\r
        mov  ax,0100h + MAP_MASK  ;AL = index in SC of Map Mask reg\r
        shl  ah,cl                ;set only the bit for the pixel's\r
@@ -56,7 +56,7 @@ _x_put_pix  proc
        mov  dx,SC_INDEX          ;set the Map Mask to enable only the\r
        out  dx,ax                ; pixel's plane\r
 \r
-       mov  al,byte ptr [Color]\r
+       mov  al,byte ptr [BP+10]\r
        mov  es:[bx],al           ;draw the pixel in the desired color\r
 \r
        pop   bp                  ;restore caller's stack frame\r
@@ -74,21 +74,21 @@ _x_put_pix   endp
 \r
 \r
 _x_get_pix   proc\r
-       ARG x:word,y:word,PageBase:word\r
+       ;ARG x:word,y:word,PageBase:word\r
        push bp                   ;preserve caller's stack frame\r
        mov  bp,sp                ;point to local stack frame\r
 \r
        mov  ax,[_ScrnLogicalByteWidth]\r
-       mul  [Y]                  ;offset of pixel's scan line in page\r
-       mov  bx,[X]\r
+       mul  [bp+6]                  ;offset of pixel's scan line in page\r
+       mov  bx,[bp+4]\r
        shr  bx,1\r
        shr  bx,1                 ;X/4 = offset of pixel in scan line\r
        add  bx,ax                ;offset of pixel in page\r
-       add  bx,[PageBase]        ;offset of pixel in display memory\r
+       add  bx,[bp+8]        ;offset of pixel in display memory\r
        mov  ax,SCREEN_SEG\r
        mov  es,ax                ;point ES:BX to the pixel's address\r
 \r
-       mov  ah,byte ptr [X]\r
+       mov  ah,byte ptr [bp+4]\r
        and  ah,011b              ;AH = pixel's plane\r
        mov  al,READ_MAP          ;AL = index in GC of the Read Map reg\r
        mov  dx,GC_INDEX          ;set the Read Map to read the pixel's\r
diff --git a/16/xw/default.fnt b/16/xw/default.fnt
new file mode 100755 (executable)
index 0000000..12eb22c
--- /dev/null
@@ -0,0 +1,260 @@
+;\r
+; MODEX library default font\r
+; Copyright (c) 1993-1994 by Alessandro Scotti\r
+;\r
+  DB    000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h  ; #0\r
+  DB   07Eh, 081h, 0A5h, 081h, 0A5h, 099h, 081h, 07Eh  ; #1\r
+  DB   07Eh, 0FFh, 0DBh, 0FFh, 0DBh, 0E7h, 0FFh, 07Eh  ; #2\r
+  DB   06Ch, 0FEh, 0FEh, 0FEh, 07Ch, 038h, 010h, 000h  ; #3\r
+  DB   010h, 038h, 07Ch, 0FEh, 07Ch, 038h, 010h, 000h  ; #4\r
+  DB   010h, 038h, 010h, 054h, 0FEh, 054h, 010h, 0FEh  ; #5\r
+  DB   010h, 038h, 07Ch, 0FEh, 0FEh, 07Ch, 010h, 0FEh  ; #6\r
+  DB   000h, 018h, 03Ch, 07Eh, 07Eh, 03Ch, 018h, 000h  ; #7\r
+  DB   0FFh, 0E7h, 0C3h, 081h, 081h, 0C3h, 0E7h, 0FFh  ; #8\r
+  DB   000h, 03Ch, 066h, 042h, 042h, 066h, 03Ch, 000h  ; #9\r
+  DB   0FFh, 0C3h, 099h, 0BDh, 0BDh, 099h, 0C3h, 0FFh  ; #10\r
+  DB   007h, 003h, 005h, 078h, 084h, 084h, 084h, 078h  ; #11\r
+  DB   07Ch, 082h, 082h, 082h, 07Ch, 010h, 038h, 010h  ; #12\r
+  DB   01Ch, 010h, 01Ch, 010h, 010h, 010h, 030h, 030h  ; #13\r
+  DB   03Eh, 022h, 03Eh, 022h, 022h, 026h, 066h, 060h  ; #14\r
+  DB   099h, 05Ah, 03Ch, 0E7h, 0E7h, 03Ch, 05Ah, 099h  ; #15\r
+  DB   000h, 010h, 030h, 070h, 0F0h, 070h, 030h, 010h  ; #16\r
+  DB   000h, 080h, 0C0h, 0E0h, 0F0h, 0E0h, 0C0h, 080h  ; #17\r
+  DB   010h, 038h, 054h, 010h, 010h, 054h, 038h, 010h  ; #18\r
+  DB   048h, 048h, 048h, 048h, 048h, 000h, 048h, 000h  ; #19\r
+  DB   07Eh, 092h, 092h, 072h, 012h, 012h, 012h, 000h  ; #20\r
+  DB   03Ch, 022h, 018h, 024h, 024h, 018h, 044h, 03Ch  ; #21\r
+  DB   000h, 000h, 000h, 000h, 000h, 03Eh, 03Eh, 000h  ; #22\r
+  DB   038h, 054h, 010h, 010h, 010h, 054h, 038h, 0FEh  ; #23\r
+  DB   000h, 010h, 038h, 054h, 010h, 010h, 010h, 000h  ; #24\r
+  DB   000h, 010h, 010h, 010h, 054h, 038h, 010h, 000h  ; #25\r
+  DB   000h, 008h, 004h, 0FEh, 004h, 008h, 000h, 000h  ; #26\r
+  DB   000h, 020h, 040h, 0FEh, 040h, 020h, 000h, 000h  ; #27\r
+  DB   000h, 000h, 080h, 080h, 080h, 0FCh, 000h, 000h  ; #28\r
+  DB   000h, 024h, 042h, 0FFh, 042h, 024h, 000h, 000h  ; #29\r
+  DB   000h, 000h, 010h, 038h, 07Ch, 0FEh, 000h, 000h  ; #30\r
+  DB   000h, 000h, 0FEh, 07Ch, 038h, 010h, 000h, 000h  ; #31\r
+  DB   000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h  ;  \r
+  DB   010h, 010h, 010h, 010h, 010h, 000h, 010h, 000h  ; !\r
+  DB   000h, 024h, 024h, 000h, 000h, 000h, 000h, 000h  ; "\r
+  DB   024h, 024h, 07Eh, 024h, 07Eh, 024h, 024h, 000h  ; #\r
+  DB   038h, 054h, 050h, 038h, 014h, 054h, 038h, 010h  ; $\r
+  DB   000h, 002h, 044h, 008h, 010h, 020h, 042h, 000h  ; %\r
+  DB   038h, 044h, 038h, 060h, 094h, 088h, 074h, 000h  ; &\r
+  DB   020h, 020h, 040h, 000h, 000h, 000h, 000h, 000h  ; '\r
+  DB   010h, 020h, 040h, 040h, 040h, 020h, 010h, 000h  ; (\r
+  DB   040h, 020h, 010h, 010h, 010h, 020h, 040h, 000h  ; )\r
+  DB   000h, 024h, 018h, 07Eh, 018h, 024h, 000h, 000h  ; *\r
+  DB   000h, 010h, 010h, 07Ch, 010h, 010h, 000h, 000h  ; +\r
+  DB   000h, 000h, 000h, 000h, 000h, 010h, 010h, 020h  ; ,\r
+  DB   000h, 000h, 000h, 0FCh, 000h, 000h, 000h, 000h  ; -\r
+  DB   000h, 000h, 000h, 000h, 000h, 000h, 010h, 000h  ; .\r
+  DB   000h, 004h, 008h, 010h, 020h, 040h, 080h, 000h  ; /\r
+  DB   07Ch, 0C6h, 08Ah, 092h, 0A2h, 0C6h, 07Ch, 000h  ; 0\r
+  DB   010h, 030h, 010h, 010h, 010h, 010h, 038h, 000h  ; 1\r
+  DB   078h, 084h, 004h, 018h, 060h, 080h, 0FCh, 000h  ; 2\r
+  DB   078h, 084h, 004h, 038h, 004h, 084h, 078h, 000h  ; 3\r
+  DB   01Ch, 024h, 044h, 084h, 0FEh, 004h, 00Eh, 000h  ; 4\r
+  DB   0FCh, 080h, 0F8h, 004h, 004h, 084h, 078h, 000h  ; 5\r
+  DB   078h, 084h, 080h, 0F8h, 084h, 084h, 078h, 000h  ; 6\r
+  DB   0FCh, 004h, 004h, 008h, 010h, 020h, 020h, 000h  ; 7\r
+  DB   078h, 084h, 084h, 078h, 084h, 084h, 078h, 000h  ; 8\r
+  DB   078h, 084h, 084h, 07Ch, 004h, 084h, 078h, 000h  ; 9\r
+  DB   000h, 000h, 010h, 000h, 000h, 000h, 010h, 000h  ; :\r
+  DB   000h, 000h, 010h, 000h, 000h, 010h, 010h, 020h  ; ;\r
+  DB   008h, 010h, 020h, 040h, 020h, 010h, 008h, 000h  ; <\r
+  DB   000h, 000h, 0FCh, 000h, 000h, 0FCh, 000h, 000h  ; =\r
+  DB   040h, 020h, 010h, 008h, 010h, 020h, 040h, 000h  ; >\r
+  DB   078h, 084h, 004h, 008h, 010h, 000h, 010h, 000h  ; ?\r
+  DB   07Ch, 082h, 0BAh, 0A6h, 0BEh, 080h, 07Ch, 000h  ; @\r
+  DB   078h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h  ; A\r
+  DB   0F8h, 084h, 084h, 0F8h, 084h, 084h, 0F8h, 000h  ; B\r
+  DB   078h, 084h, 080h, 080h, 080h, 084h, 078h, 000h  ; C\r
+  DB   0F0h, 088h, 084h, 084h, 084h, 088h, 0F0h, 000h  ; D\r
+  DB   0FCh, 080h, 080h, 0F0h, 080h, 080h, 0FCh, 000h  ; E\r
+  DB   0FCh, 080h, 080h, 0F0h, 080h, 080h, 080h, 000h  ; F\r
+  DB   078h, 084h, 080h, 09Ch, 084h, 084h, 078h, 000h  ; G\r
+  DB   084h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h  ; H\r
+  DB   038h, 010h, 010h, 010h, 010h, 010h, 038h, 000h  ; I\r
+  DB   01Ch, 008h, 008h, 008h, 088h, 088h, 070h, 000h  ; J\r
+  DB   084h, 088h, 090h, 0E0h, 090h, 088h, 084h, 000h  ; K\r
+  DB   080h, 080h, 080h, 080h, 080h, 080h, 0FCh, 000h  ; L\r
+  DB   0C6h, 0AAh, 092h, 082h, 082h, 082h, 082h, 000h  ; M\r
+  DB   082h, 0C2h, 0A2h, 092h, 08Ah, 086h, 082h, 000h  ; N\r
+  DB   078h, 084h, 084h, 084h, 084h, 084h, 078h, 000h  ; O\r
+  DB   0F8h, 084h, 084h, 0F8h, 080h, 080h, 080h, 000h  ; P\r
+  DB   078h, 084h, 084h, 084h, 094h, 088h, 076h, 000h  ; Q\r
+  DB   0F8h, 084h, 084h, 0F8h, 090h, 088h, 084h, 000h  ; R\r
+  DB   078h, 084h, 080h, 078h, 004h, 084h, 078h, 000h  ; S\r
+  DB   0FEh, 010h, 010h, 010h, 010h, 010h, 010h, 000h  ; T\r
+  DB   084h, 084h, 084h, 084h, 084h, 084h, 078h, 000h  ; U\r
+  DB   084h, 084h, 084h, 084h, 084h, 048h, 030h, 000h  ; V\r
+  DB   082h, 082h, 082h, 082h, 092h, 0AAh, 0C6h, 000h  ; W\r
+  DB   082h, 044h, 028h, 010h, 028h, 044h, 082h, 000h  ; X\r
+  DB   044h, 044h, 044h, 038h, 010h, 010h, 010h, 000h  ; Y\r
+  DB   0FEh, 004h, 008h, 010h, 020h, 040h, 0FEh, 000h  ; Z\r
+  DB   078h, 040h, 040h, 040h, 040h, 040h, 078h, 000h  ; [\r
+  DB   000h, 080h, 040h, 020h, 010h, 008h, 004h, 000h  ; \\r
+  DB   078h, 008h, 008h, 008h, 008h, 008h, 078h, 000h  ; ]\r
+  DB   010h, 028h, 044h, 082h, 000h, 000h, 000h, 000h  ; ^\r
+  DB   000h, 000h, 000h, 000h, 000h, 000h, 000h, 0FFh  ; _\r
+  DB   020h, 020h, 010h, 000h, 000h, 000h, 000h, 000h  ; `\r
+  DB   000h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; a\r
+  DB   000h, 040h, 040h, 078h, 044h, 044h, 078h, 000h  ; b\r
+  DB   000h, 000h, 03Ch, 040h, 040h, 040h, 03Ch, 000h  ; c\r
+  DB   000h, 004h, 004h, 03Ch, 044h, 044h, 03Ch, 000h  ; d\r
+  DB   000h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h  ; e\r
+  DB   000h, 00Ch, 010h, 03Ch, 010h, 010h, 010h, 000h  ; f\r
+  DB   000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 038h  ; g\r
+  DB   000h, 040h, 040h, 078h, 044h, 044h, 044h, 000h  ; h\r
+  DB   000h, 010h, 000h, 010h, 010h, 010h, 010h, 000h  ; i\r
+  DB   000h, 004h, 000h, 004h, 004h, 004h, 044h, 038h  ; j\r
+  DB   000h, 040h, 040h, 050h, 060h, 050h, 048h, 000h  ; k\r
+  DB   000h, 030h, 010h, 010h, 010h, 010h, 010h, 000h  ; l\r
+  DB   000h, 000h, 068h, 054h, 054h, 044h, 044h, 000h  ; m\r
+  DB   000h, 000h, 078h, 044h, 044h, 044h, 044h, 000h  ; n\r
+  DB   000h, 000h, 038h, 044h, 044h, 044h, 038h, 000h  ; o\r
+  DB   000h, 000h, 078h, 044h, 044h, 078h, 040h, 040h  ; p\r
+  DB   000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 004h  ; q\r
+  DB   000h, 000h, 05Ch, 060h, 040h, 040h, 040h, 000h  ; r\r
+  DB   000h, 000h, 038h, 040h, 07Ch, 004h, 07Ch, 000h  ; s\r
+  DB   000h, 010h, 038h, 010h, 010h, 010h, 018h, 000h  ; t\r
+  DB   000h, 000h, 044h, 044h, 044h, 044h, 038h, 000h  ; u\r
+  DB   000h, 000h, 044h, 044h, 044h, 028h, 010h, 000h  ; v\r
+  DB   000h, 000h, 044h, 044h, 054h, 054h, 06Ch, 000h  ; w\r
+  DB   000h, 000h, 044h, 028h, 010h, 028h, 044h, 000h  ; x\r
+  DB   000h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch  ; y\r
+  DB   000h, 000h, 07Ch, 004h, 038h, 040h, 07Ch, 000h  ; z\r
+  DB   000h, 008h, 010h, 010h, 030h, 010h, 010h, 008h  ; {\r
+  DB   000h, 010h, 010h, 010h, 000h, 010h, 010h, 010h  ; |\r
+  DB   000h, 020h, 010h, 010h, 018h, 010h, 010h, 020h  ; }\r
+  DB   064h, 098h, 000h, 000h, 000h, 000h, 000h, 000h  ; ~\r
+  DB   000h, 010h, 028h, 044h, 082h, 082h, 0FEh, 000h  ; \7f\r
+  DB   07Ch, 080h, 080h, 080h, 080h, 07Ch, 004h, 07Ch  ; #128\r
+  DB   000h, 028h, 000h, 044h, 044h, 044h, 038h, 000h  ; #129\r
+  DB   03Ch, 000h, 07Ch, 044h, 07Ch, 040h, 07Ch, 000h  ; #130\r
+  DB   07Eh, 081h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #131\r
+  DB   024h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #132\r
+  DB   078h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #133\r
+  DB   018h, 018h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #134\r
+  DB   000h, 000h, 078h, 080h, 080h, 078h, 008h, 038h  ; #135\r
+  DB   07Ch, 082h, 038h, 044h, 07Ch, 040h, 03Ch, 000h  ; #136\r
+  DB   048h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h  ; #137\r
+  DB   078h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h  ; #138\r
+  DB   000h, 028h, 000h, 010h, 010h, 010h, 010h, 000h  ; #139\r
+  DB   010h, 028h, 000h, 010h, 010h, 010h, 010h, 000h  ; #140\r
+  DB   000h, 030h, 000h, 010h, 010h, 010h, 010h, 000h  ; #141\r
+  DB   048h, 000h, 078h, 084h, 0FCh, 084h, 084h, 000h  ; #142\r
+  DB   030h, 030h, 078h, 084h, 0FCh, 084h, 084h, 000h  ; #143\r
+  DB   038h, 000h, 0FCh, 080h, 0F0h, 080h, 0FCh, 000h  ; #144\r
+  DB   000h, 000h, 07Eh, 008h, 07Eh, 048h, 07Eh, 000h  ; #145\r
+  DB   07Eh, 090h, 090h, 0FCh, 090h, 090h, 09Eh, 000h  ; #146\r
+  DB   07Ch, 082h, 038h, 044h, 044h, 044h, 038h, 000h  ; #147\r
+  DB   028h, 000h, 038h, 044h, 044h, 044h, 038h, 000h  ; #148\r
+  DB   070h, 000h, 038h, 044h, 044h, 044h, 038h, 000h  ; #149\r
+  DB   038h, 044h, 000h, 044h, 044h, 044h, 038h, 000h  ; #150\r
+  DB   070h, 000h, 044h, 044h, 044h, 044h, 038h, 000h  ; #151\r
+  DB   028h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch  ; #152\r
+  DB   048h, 000h, 078h, 084h, 084h, 084h, 078h, 000h  ; #153\r
+  DB   048h, 000h, 084h, 084h, 084h, 084h, 078h, 000h  ; #154\r
+  DB   000h, 010h, 038h, 040h, 040h, 040h, 038h, 010h  ; #155\r
+  DB   038h, 044h, 040h, 0E0h, 040h, 040h, 082h, 0FCh  ; #156\r
+  DB   044h, 07Ch, 010h, 07Ch, 010h, 07Ch, 010h, 000h  ; #157\r
+  DB   0F0h, 088h, 08Ah, 0F7h, 082h, 082h, 082h, 000h  ; #158\r
+  DB   00Ch, 012h, 010h, 018h, 030h, 010h, 090h, 060h  ; #159\r
+  DB   03Ch, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #160\r
+  DB   000h, 018h, 000h, 010h, 010h, 010h, 010h, 000h  ; #161\r
+  DB   01Ch, 000h, 038h, 044h, 044h, 044h, 038h, 000h  ; #162\r
+  DB   01Ch, 000h, 044h, 044h, 044h, 044h, 038h, 000h  ; #163\r
+  DB   07Ch, 000h, 078h, 044h, 044h, 044h, 044h, 000h  ; #164\r
+  DB   07Ch, 000h, 044h, 064h, 054h, 04Ch, 044h, 000h  ; #165\r
+  DB   018h, 024h, 024h, 01Eh, 000h, 03Eh, 000h, 000h  ; #166\r
+  DB   01Ch, 022h, 022h, 01Ch, 000h, 03Eh, 000h, 000h  ; #167\r
+  DB   010h, 000h, 010h, 020h, 040h, 042h, 03Ch, 000h  ; #168\r
+  DB   000h, 000h, 000h, 0FCh, 080h, 080h, 000h, 000h  ; #169\r
+  DB   000h, 000h, 000h, 0FCh, 004h, 004h, 000h, 000h  ; #170\r
+  DB   040h, 044h, 048h, 057h, 021h, 047h, 004h, 007h  ; #171\r
+  DB   040h, 044h, 048h, 052h, 026h, 04Ah, 01Fh, 002h  ; #172\r
+  DB   010h, 000h, 010h, 010h, 010h, 010h, 010h, 000h  ; #173\r
+  DB   000h, 024h, 048h, 090h, 048h, 024h, 000h, 000h  ; #174\r
+  DB   000h, 048h, 024h, 012h, 024h, 048h, 000h, 000h  ; #175\r
+  DB   022h, 088h, 022h, 088h, 022h, 088h, 022h, 088h  ; #176\r
+  DB   055h, 0AAh, 055h, 0AAh, 055h, 0AAh, 055h, 0AAh  ; #177\r
+  DB   0DBh, 077h, 0DBh, 0EEh, 0DBh, 077h, 0DBh, 0EEh  ; #178\r
+  DB   018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h  ; #179\r
+  DB   018h, 018h, 018h, 018h, 0F8h, 018h, 018h, 018h  ; #180\r
+  DB   018h, 018h, 0F8h, 018h, 0F8h, 018h, 018h, 018h  ; #181\r
+  DB   036h, 036h, 036h, 036h, 0F6h, 036h, 036h, 036h  ; #182\r
+  DB   000h, 000h, 000h, 000h, 0FEh, 036h, 036h, 036h  ; #183\r
+  DB   000h, 000h, 0F8h, 018h, 0F8h, 018h, 018h, 018h  ; #184\r
+  DB   036h, 036h, 0F6h, 006h, 0F6h, 036h, 036h, 036h  ; #185\r
+  DB   036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h  ; #186\r
+  DB   000h, 000h, 0FEh, 006h, 0F6h, 036h, 036h, 036h  ; #187\r
+  DB   036h, 036h, 0F6h, 006h, 0FEh, 000h, 000h, 000h  ; #188\r
+  DB   036h, 036h, 036h, 036h, 0FEh, 000h, 000h, 000h  ; #189\r
+  DB   018h, 018h, 0F8h, 018h, 0F8h, 000h, 000h, 000h  ; #190\r
+  DB   000h, 000h, 000h, 000h, 0F8h, 018h, 018h, 018h  ; #191\r
+  DB   018h, 018h, 018h, 018h, 01Fh, 000h, 000h, 000h  ; #192\r
+  DB   018h, 018h, 018h, 018h, 0FFh, 000h, 000h, 000h  ; #193\r
+  DB   000h, 000h, 000h, 000h, 0FFh, 018h, 018h, 018h  ; #194\r
+  DB   018h, 018h, 018h, 018h, 01Fh, 018h, 018h, 018h  ; #195\r
+  DB   000h, 000h, 000h, 000h, 0FFh, 000h, 000h, 000h  ; #196\r
+  DB   018h, 018h, 018h, 018h, 0FFh, 018h, 018h, 018h  ; #197\r
+  DB   018h, 018h, 01Fh, 018h, 01Fh, 018h, 018h, 018h  ; #198\r
+  DB   036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h  ; #199\r
+  DB   036h, 036h, 037h, 030h, 03Fh, 000h, 000h, 000h  ; #200\r
+  DB   000h, 000h, 03Fh, 030h, 037h, 036h, 036h, 036h  ; #201\r
+  DB   036h, 036h, 0F7h, 000h, 0FFh, 000h, 000h, 000h  ; #202\r
+  DB   000h, 000h, 0FFh, 000h, 0F7h, 036h, 036h, 036h  ; #203\r
+  DB   036h, 036h, 037h, 030h, 037h, 036h, 036h, 036h  ; #204\r
+  DB   000h, 000h, 0FFh, 000h, 0FFh, 000h, 000h, 000h  ; #205\r
+  DB   036h, 036h, 0F7h, 000h, 0F7h, 036h, 036h, 036h  ; #206\r
+  DB   018h, 018h, 0FFh, 000h, 0FFh, 000h, 000h, 000h  ; #207\r
+  DB   036h, 036h, 036h, 036h, 0FFh, 000h, 000h, 000h  ; #208\r
+  DB   000h, 000h, 0FFh, 000h, 0FFh, 018h, 018h, 018h  ; #209\r
+  DB   000h, 000h, 000h, 000h, 0FFh, 036h, 036h, 036h  ; #210\r
+  DB   036h, 036h, 036h, 036h, 03Fh, 000h, 000h, 000h  ; #211\r
+  DB   018h, 018h, 01Fh, 018h, 01Fh, 000h, 000h, 000h  ; #212\r
+  DB   000h, 000h, 01Fh, 018h, 01Fh, 018h, 018h, 018h  ; #213\r
+  DB   000h, 000h, 000h, 000h, 03Fh, 036h, 036h, 036h  ; #214\r
+  DB   036h, 036h, 036h, 036h, 0FFh, 036h, 036h, 036h  ; #215\r
+  DB   018h, 018h, 0FFh, 018h, 0FFh, 018h, 018h, 018h  ; #216\r
+  DB   018h, 018h, 018h, 018h, 0F8h, 000h, 000h, 000h  ; #217\r
+  DB   000h, 000h, 000h, 000h, 01Fh, 018h, 018h, 018h  ; #218\r
+  DB   0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh  ; #219\r
+  DB   000h, 000h, 000h, 000h, 0FFh, 0FFh, 0FFh, 0FFh  ; #220\r
+  DB   0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h  ; #221\r
+  DB   00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh  ; #222\r
+  DB   0FFh, 0FFh, 0FFh, 0FFh, 000h, 000h, 000h, 000h  ; #223\r
+  DB   000h, 000h, 062h, 094h, 088h, 094h, 062h, 000h  ; #224\r
+  DB   000h, 0F0h, 088h, 0F0h, 088h, 088h, 0F0h, 080h  ; #225\r
+  DB   000h, 0F8h, 088h, 080h, 080h, 080h, 080h, 000h  ; #226\r
+  DB   000h, 0FCh, 048h, 048h, 048h, 048h, 048h, 000h  ; #227\r
+  DB   0FCh, 084h, 040h, 020h, 040h, 084h, 0FCh, 000h  ; #228\r
+  DB   03Ch, 040h, 038h, 044h, 044h, 044h, 038h, 000h  ; #229\r
+  DB   000h, 000h, 044h, 044h, 044h, 078h, 040h, 040h  ; #230\r
+  DB   000h, 036h, 048h, 008h, 008h, 008h, 008h, 000h  ; #231\r
+  DB   038h, 010h, 038h, 044h, 044h, 038h, 010h, 038h  ; #232\r
+  DB   078h, 084h, 084h, 0FCh, 084h, 084h, 078h, 000h  ; #233\r
+  DB   078h, 084h, 084h, 084h, 048h, 048h, 0CCh, 000h  ; #234\r
+  DB   078h, 004h, 038h, 044h, 044h, 044h, 038h, 000h  ; #235\r
+  DB   000h, 000h, 06Ch, 092h, 092h, 06Ch, 000h, 000h  ; #236\r
+  DB   000h, 000h, 03Ah, 044h, 05Ah, 022h, 05Ch, 000h  ; #237\r
+  DB   018h, 020h, 040h, 078h, 040h, 020h, 018h, 000h  ; #238\r
+  DB   078h, 084h, 084h, 084h, 084h, 084h, 084h, 000h  ; #239\r
+  DB   000h, 0FCh, 000h, 0FCh, 000h, 0FCh, 000h, 000h  ; #240\r
+  DB   020h, 020h, 0F8h, 020h, 020h, 000h, 0F8h, 000h  ; #241\r
+  DB   020h, 010h, 008h, 010h, 020h, 000h, 07Ch, 000h  ; #242\r
+  DB   008h, 010h, 020h, 010h, 008h, 000h, 07Ch, 000h  ; #243\r
+  DB   00Ch, 012h, 010h, 010h, 010h, 010h, 010h, 010h  ; #244\r
+  DB   010h, 010h, 010h, 010h, 010h, 010h, 090h, 060h  ; #245\r
+  DB   000h, 010h, 000h, 07Ch, 000h, 010h, 000h, 000h  ; #246\r
+  DB   000h, 032h, 04Ch, 000h, 032h, 04Ch, 000h, 000h  ; #247\r
+  DB   038h, 044h, 044h, 038h, 000h, 000h, 000h, 000h  ; #248\r
+  DB   000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h  ; #249\r
+  DB   000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h  ; #250\r
+  DB   00Eh, 008h, 008h, 008h, 048h, 028h, 018h, 008h  ; #251\r
+  DB   038h, 024h, 024h, 024h, 024h, 000h, 000h, 000h  ; #252\r
+  DB   03Ch, 004h, 03Ch, 020h, 03Ch, 000h, 000h, 000h  ; #253\r
+  DB   000h, 000h, 03Ch, 03Ch, 03Ch, 03Ch, 000h, 000h  ; #254\r
+  DB   000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h  ; #255\r
diff --git a/16/xw/makefile b/16/xw/makefile
new file mode 100755 (executable)
index 0000000..96d1c08
--- /dev/null
@@ -0,0 +1,132 @@
+#\r
+# MODEX library makefile (for Borland MAKE)\r
+# Copyright (c) 1993,1994 by Alessandro Scotti\r
+#\r
+!ifdef __LINUX__\r
+REMOVECOMMAND=rm -f\r
+COPYCOMMAND=cp -f\r
+DIRSEP=/\r
+OBJ=o\r
+!else\r
+REMOVECOMMAND=del\r
+COPYCOMMAND=copy /y\r
+DIRSEP=\\r
+OBJ=obj\r
+!endif\r
+LIBINCS = modex.def\r
+\r
+LIBOBJS = mxbb.$(OBJ) mxcc.$(OBJ) mxcg.$(OBJ) mxcl.$(OBJ) mxcr.$(OBJ) mxfb.$(OBJ) mxfp.$(OBJ) mxgc.$(OBJ) mxgi.$(OBJ) mxgm.$(OBJ) mxgp.$(OBJ) mxgv.$(OBJ) mxhl.$(OBJ) mxit.$(OBJ) mxll.$(OBJ) mxln.$(OBJ) mxot.$(OBJ) mxpb.$(OBJ) mxpf.$(OBJ) mxpg.$(OBJ) mxpi.$(OBJ) mxpn.$(OBJ) mxpp.$(OBJ) mxra.$(OBJ) mxrp.$(OBJ) mxsa.$(OBJ) mxsc.$(OBJ) mxsi.$(OBJ) mxsl.$(OBJ) mxsm.$(OBJ) mxsp.$(OBJ) mxss.$(OBJ) mxtl.$(OBJ) mxvs.$(OBJ) mxwd.$(OBJ) mxwm.$(OBJ) mxwp.$(OBJ) mxwr.$(OBJ)\r
+\r
+#\r
+# ASM compiler\r
+#\r
+ASMC =wasm\r
+ASMO =-mh -0\r
+\r
+#\r
+# PAS compiler\r
+#\r
+#PASC = tpc\r
+#PASO = /m -$D- -$L- -$S-\r
+\r
+#\r
+# LIB maker, uses response file\r
+#\r
+LIBC = wlib\r
+\r
+# .asm.obj:\r
+#              $(ASMC) $(ASMO) $<\r
+\r
+mxbb.$(OBJ): mxbb.asm\r
+       $(ASMC) $(ASMO) mxbb.asm\r
+mxcc.$(OBJ): mxcc.asm\r
+       $(ASMC) $(ASMO) mxcc.asm\r
+mxcg.$(OBJ): mxcg.asm\r
+       $(ASMC) $(ASMO) mxcg.asm\r
+mxcl.$(OBJ): mxcl.asm\r
+       $(ASMC) $(ASMO) mxcl.asm\r
+mxcr.$(OBJ): mxcr.asm\r
+       $(ASMC) $(ASMO) mxcr.asm\r
+mxfb.$(OBJ): mxfb.asm\r
+       $(ASMC) $(ASMO) mxfb.asm\r
+mxfp.$(OBJ): mxfp.asm\r
+       $(ASMC) $(ASMO) mxfp.asm\r
+mxgc.$(OBJ): mxgc.asm\r
+       $(ASMC) $(ASMO) mxgc.asm\r
+mxgi.$(OBJ): mxgi.asm\r
+       $(ASMC) $(ASMO) mxgi.asm\r
+mxgm.$(OBJ): mxgm.asm\r
+       $(ASMC) $(ASMO) mxgm.asm\r
+mxgp.$(OBJ): mxgp.asm\r
+       $(ASMC) $(ASMO) mxgp.asm\r
+mxgv.$(OBJ): mxgv.asm\r
+       $(ASMC) $(ASMO) mxgv.asm\r
+mxhl.$(OBJ): mxhl.asm\r
+       $(ASMC) $(ASMO) mxhl.asm\r
+mxit.$(OBJ): mxit.asm\r
+       $(ASMC) $(ASMO) mxit.asm\r
+mxll.$(OBJ): mxll.asm\r
+       $(ASMC) $(ASMO) mxll.asm\r
+mxln.$(OBJ): mxln.asm\r
+       $(ASMC) $(ASMO) mxln.asm\r
+mxot.$(OBJ): mxot.asm\r
+       $(ASMC) $(ASMO) mxot.asm\r
+mxpb.$(OBJ): mxpb.asm\r
+       $(ASMC) $(ASMO) mxpb.asm\r
+mxpf.$(OBJ): mxpf.asm\r
+       $(ASMC) $(ASMO) mxpf.asm\r
+mxpg.$(OBJ): mxpg.asm\r
+       $(ASMC) $(ASMO) mxpg.asm\r
+mxpi.$(OBJ): mxpi.asm\r
+       $(ASMC) $(ASMO) mxpi.asm\r
+mxpn.$(OBJ): mxpn.asm\r
+       $(ASMC) $(ASMO) mxpn.asm\r
+mxpp.$(OBJ): mxpp.asm\r
+       $(ASMC) $(ASMO) mxpp.asm\r
+mxra.$(OBJ): mxra.asm\r
+       $(ASMC) $(ASMO) mxra.asm\r
+mxrp.$(OBJ): mxrp.asm\r
+       $(ASMC) $(ASMO) mxrp.asm\r
+mxsa.$(OBJ): mxsa.asm\r
+       $(ASMC) $(ASMO) mxsa.asm\r
+mxsc.$(OBJ): mxsc.asm\r
+       $(ASMC) $(ASMO) mxsc.asm\r
+mxsi.$(OBJ): mxsi.asm\r
+       $(ASMC) $(ASMO) mxsi.asm\r
+mxsl.$(OBJ): mxsl.asm\r
+       $(ASMC) $(ASMO) mxsl.asm\r
+mxsm.$(OBJ): mxsm.asm\r
+       $(ASMC) $(ASMO) mxsm.asm\r
+mxsp.$(OBJ): mxsp.asm\r
+       $(ASMC) $(ASMO) mxsp.asm\r
+mxss.$(OBJ): mxss.asm\r
+       $(ASMC) $(ASMO) mxss.asm\r
+mxtl.$(OBJ): mxtl.asm\r
+       $(ASMC) $(ASMO) mxtl.asm\r
+mxvs.$(OBJ): mxvs.asm\r
+       $(ASMC) $(ASMO) mxvs.asm\r
+mxwd.$(OBJ): mxwd.asm\r
+       $(ASMC) $(ASMO) mxwd.asm\r
+mxwm.$(OBJ): mxwm.asm\r
+       $(ASMC) $(ASMO) mxwm.asm\r
+mxwp.$(OBJ): mxwp.asm\r
+       $(ASMC) $(ASMO) mxwp.asm\r
+mxwr.$(OBJ): mxwr.asm\r
+       $(ASMC) $(ASMO) mxwr.asm\r
+\r
+all: $(LIBOBJS) modex.lib\r
+# modex.tpu modex.tpp\r
+\r
+#modex.tpu: $(LIBOBJS) modex.pas\r
+#        $(PASC) $(PASO) modex\r
+#        copy modex.tpu ..\r
+#        copy modex.pas ..\r
+\r
+#modex.tpp: $(LIBOBJS) modex.pas\r
+#        $(PASC) /cp $(PASO) modex\r
+#        copy modex.tpp ..\r
+\r
+modex.lib: modex.lbr $(LIBOBJS)\r
+       $(LIBC) modex.lib @modex.lbr\r
+\r
+$(LIBOBJS):   modex.def\r
diff --git a/16/xw/makefile.bcc b/16/xw/makefile.bcc
new file mode 100755 (executable)
index 0000000..d3ad8b7
--- /dev/null
@@ -0,0 +1,81 @@
+#\r
+# MODEX library makefile (for Borland MAKE)\r
+# Copyright (c) 1993,1994 by Alessandro Scotti\r
+#\r
+LIBINCS = MODEX.DEF\r
+\r
+LIBOBJS = MXBB.OBJ \\r
+          MXCC.OBJ \\r
+          MXCG.OBJ \\r
+          MXCL.OBJ \\r
+          MXCR.OBJ \\r
+          MXFB.OBJ \\r
+          MXFP.OBJ \\r
+          MXGC.OBJ \\r
+          MXGI.OBJ \\r
+          MXGM.OBJ \\r
+          MXGP.OBJ \\r
+          MXGV.OBJ \\r
+          MXHL.OBJ \\r
+          MXIT.OBJ \\r
+          MXLL.OBJ \\r
+          MXLN.OBJ \\r
+          MXOT.OBJ \\r
+          MXPB.OBJ \\r
+          MXPF.OBJ \\r
+          MXPG.OBJ \\r
+          MXPI.OBJ \\r
+          MXPN.OBJ \\r
+          MXPP.OBJ \\r
+          MXRA.OBJ \\r
+          MXRP.OBJ \\r
+          MXSA.OBJ \\r
+          MXSC.OBJ \\r
+          MXSI.OBJ \\r
+          MXSL.OBJ \\r
+          MXSM.OBJ \\r
+          MXSP.OBJ \\r
+          MXSS.OBJ \\r
+          MXTL.OBJ \\r
+          MXVS.OBJ \\r
+          MXWD.OBJ \\r
+          MXWM.OBJ \\r
+          MXWP.OBJ \\r
+          MXWR.OBJ\r
+\r
+#\r
+# ASM compiler\r
+#\r
+ASMC = tasm\r
+ASMO = /m5 /p\r
+\r
+#\r
+# PAS compiler\r
+#\r
+PASC = tpc\r
+PASO = /m -$D- -$L- -$S-\r
+\r
+#\r
+# LIB maker, uses response file\r
+#\r
+LIBC = tlib\r
+\r
+.asm.obj:\r
+        $(ASMC) $(ASMO) $<\r
+\r
+target: modex.lib
+# modex.tpu modex.tpp\r
+\r
+#modex.tpu: $(LIBOBJS) modex.pas\r
+#        $(PASC) $(PASO) modex\r
+#        copy modex.tpu ..\r
+#        copy modex.pas ..\r
+\r
+#modex.tpp: $(LIBOBJS) modex.pas\r
+#        $(PASC) /cp $(PASO) modex\r
+#        copy modex.tpp ..\r
+\r
+modex.lib: modex.lbr $(LIBOBJS)\r
+        $(LIBC) modex.lib @modex.lbr\r
+\r
+$(LIBOBJS):   modex.def\r
diff --git a/16/xw/modex.bak b/16/xw/modex.bak
new file mode 100755 (executable)
index 0000000..560a1c6
Binary files /dev/null and b/16/xw/modex.bak differ
diff --git a/16/xw/modex.def b/16/xw/modex.def
new file mode 100755 (executable)
index 0000000..7977a4a
--- /dev/null
@@ -0,0 +1,163 @@
+;------------------------------------------------------------\r
+;\r
+; MODEX.DEF - Include file\r
+; Copyright (c) 1993-1994 by Alessandro Scotti\r
+;\r
+;JUMPS\r
+;LOCALS\r
+\r
+TRUE            EQU     1       ; Boolean constants\r
+FALSE           EQU     0\r
+\r
+USE286  = FALSE                  ; TRUE enables 80286 instructions\r
+USE386  = FALSE                  ; TRUE enables 80386 (and 80286) instructions\r
+\r
+IF USE286 EQ TRUE\r
+        P286\r
+ENDIF\r
+\r
+IF USE386 EQ TRUE\r
+        P386\r
+        USE286  = TRUE\r
+ENDIF\r
+\r
+MXVERSION       EQU     0128h   ; Library version (1.40)\r
+\r
+;------------------------------------------------------------\r
+;\r
+; VGA definitions\r
+;\r
+MISC    EQU     3C2h            ; Miscellaneous output\r
+TS      EQU     3C4h            ; Timing Sequencer index register\r
+GDC     EQU     3CEh            ; Graphics Data Controller index register\r
+CRTC    EQU     3D4h            ; CRTC index register\r
+STATUS  EQU     3DAh            ; Input Status register one\r
+\r
+;------------------------------------------------------------\r
+;\r
+; Raster operators\r
+;\r
+OP_SET          EQU     0\r
+OP_MOVE         EQU     0       ; Same as OP_SET\r
+OP_AND          EQU     1\r
+OP_OR           EQU     2\r
+OP_XOR          EQU     3\r
+OP_TRANS        EQU     4\r
+OP_ADD          EQU     5       ; Must be last op\r
+\r
+;------------------------------------------------------------\r
+;\r
+; Polygon fill functions\r
+;\r
+POLYSCANBUFSIZE EQU     4*1024\r
+\r
+;------------------------------------------------------------\r
+; Macro to push registers, variables or flags onto the stack\r
+; Usage: .push "loc16"[,"loc16"...]\r
+; where "loc16" is a 16-bit register, a word-sized variable or the\r
+; keyword "FLAGS".\r
+; Exmpl: .push ax, flags, var1\r
+;        .pop  ax, flags, var1\r
+;\r
+.push   MACRO   r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10\r
+    IFNB <r10>\r
+        .ERROR <.PUSH has more than 10 arguments>\r
+    ENDIF\r
+    IRP $reg, <r0, r1, r2, r3, r4, r5, r6, r7, r8, r9>\r
+        IFB <$reg>                      ;; Is argument blank?\r
+            EXITM                       ;; Yes, exit\r
+        ELSEIFIDNI <$reg>, <FLAGS>      ;; Is argument the keyword "FLAGS"?\r
+            pushf                       ;; Yes, push flags\r
+        ELSE\r
+            push    $reg                ;; Push argument\r
+        ENDIF\r
+    ENDM\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+; Macro to pop registers, variables or flags from the stack\r
+; Usage: .pop "loc16"[,"loc16"...]\r
+; where "loc16" is a 16-bit register, a word-sized variable or the\r
+; keyword "FLAGS".\r
+; Exmpl: .push ax, flags, var1\r
+;        .pop  ax, flags, var1\r
+;\r
+.pop    MACRO   r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10\r
+    IFNB <r10>\r
+        .ERROR <.POP has more than 10 arguments>\r
+    ENDIF\r
+    IRP $reg, <r9, r8, r7, r6, r5, r4, r3, r2, r1, r0>\r
+        IFNB <$reg>                     ;; Is argument non-blank?\r
+            IFIDNI <$reg>, <FLAGS>      ;; Yes, is it the keyword "FLAGS"?\r
+                popf                    ;; Yes, pop flags\r
+            ELSE\r
+                pop     $reg            ;; Pop argument\r
+            ENDIF\r
+        ENDIF\r
+    ENDM\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.enter  MACRO   localsize\r
+    IF USE286 EQ TRUE\r
+        enter   localsize, 0\r
+    ELSE\r
+        push    bp\r
+        mov     bp, sp\r
+        sub     sp, localsize\r
+    ENDIF\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.leave  MACRO   argsize\r
+;    IF USE286 EQ TRUE\r
+;        leave\r
+;    ELSE\r
+;        mov     sp, bp\r
+;        pop     bp\r
+;    ENDIF\r
+;    IFNB <argspace>\r
+;        ret     argsize\r
+;    ELSE\r
+;        ret\r
+;    ENDIF\r
+;ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.shr    MACRO   arg, count\r
+;    IF USE286 EQ TRUE\r
+;        shr     arg, count\r
+;    ELSE\r
+;        $temp = count\r
+;        WHILE $temp GT 0\r
+;            shr arg, 1\r
+;            $temp = $temp-1\r
+;        ENDM\r
+;    ENDIF\r
+;ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.shl    MACRO   arg, count\r
+;    IF USE286 EQ TRUE\r
+;        shl     arg, count\r
+;    ELSE\r
+;        $temp = count\r
+;        WHILE $temp GT 0\r
+;            shl arg, 1\r
+;            $temp = $temp-1\r
+;        ENDM\r
+;    ENDIF\r
+;ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.chk386 MACRO   name, jump\r
+;    IF USE386 EQ FALSE\r
+;        .OUT    "Warning: ", <name>, " needs a 386 or better to run!"\r
+;        jmp     @@jump\r
+;    ENDIF\r
+;ENDM\r
diff --git a/16/xw/modex.h b/16/xw/modex.h
new file mode 100755 (executable)
index 0000000..2c1f1eb
--- /dev/null
@@ -0,0 +1,153 @@
+/*\r
+    MODEX.H - C/C++ include file for the MODEX library\r
+    Copyright (c) 1994 Alessandro Scotti\r
+*/\r
+\r
+#ifndef _MODEX_H_               // Avoid nested inclusions\r
+#define _MODEX_H_\r
+\r
+//\r
+// Video modes\r
+//\r
+#define MX_TEXT     0           // 80x25 text\r
+#define MX_320x175  1           // 320x175x256\r
+#define MX_320x200  2           // 320x200x256, 4 pages, aspect 6:5\r
+#define MX_320x240  3           // 320x240x256, 3 pages, aspect 1:1\r
+#define MX_320x350  4           // 320x350x256\r
+#define MX_320x400  5           // 320x400x256, 2 pages\r
+#define MX_320x480  6           // 320x480x256, 1 page\r
+#define MX_360x175  7           // 360x175x256\r
+#define MX_360x200  8           // 360x200x256, 3 pages\r
+#define MX_360x240  9           // 360x240x256, 2 pages\r
+#define MX_360x350  10          // 360x350x256\r
+#define MX_360x400  11          // 360x400x256, 1 page\r
+#define MX_360x480  12          // 360x480x256, 1 page\r
+#define MX_400x600  13          // 400x600x256, 1 page\r
+\r
+//\r
+// Fade effects\r
+//\r
+#define MX_FADEIN   0\r
+#define MX_FADEOUT  1\r
+\r
+//\r
+// Raster ops\r
+//\r
+#define OP_SET      0           // No operator\r
+#define OP_AND      1           // And\r
+#define OP_OR       2           // Or\r
+#define OP_XOR      3           // Xor\r
+#define OP_TRANS    4           // Transparent\r
+#define OP_ADD      5           // Additive\r
+#define OP_MOVE     0           // Alias for OP_SET\r
+\r
+//\r
+// Temporary definitions\r
+//\r
+#define MXBYTE      unsigned char\r
+#define MXBOOL      short int\r
+#define MXSINT      short int\r
+#define MXUINT      unsigned short int\r
+#define MXAPI       far pascal\r
+#define MXPTR       void far *\r
+\r
+// Functions\r
+\r
+#ifdef __cplusplus                      // Avoid C++ name mangling\r
+extern "C" {\r
+#endif\r
+\r
+//\r
+// Initialization\r
+//\r
+MXSINT  MXAPI mxInit( void );             // Returns 0 if successful\r
+void    MXAPI mxTerm( void );\r
+MXUINT  MXAPI mxGetVersion( void );\r
+//\r
+// Mode setting\r
+//\r
+void    MXAPI mxChangeMode( MXUINT mode );\r
+void    MXAPI mxSetMode( MXUINT mode );\r
+void    MXAPI mxGetAspect( MXUINT far *aspectx, MXUINT far *aspecty );\r
+void    MXAPI mxGetScreenSize( MXUINT far *width, MXUINT far *height );\r
+//\r
+// Hardware support\r
+//\r
+void    MXAPI mxWriteMode( MXBYTE wm );\r
+void    MXAPI mxSplitScreen( MXUINT line );\r
+void    MXAPI mxStartAddress( MXUINT sa );\r
+void    MXAPI mxStartLine( MXUINT sl );\r
+void    MXAPI mxWaitDisplay( void );\r
+void    MXAPI mxWaitRetrace( void );\r
+void    MXAPI mxWritePlane( MXBYTE wp );\r
+void    MXAPI mxReadPlane( MXBYTE rp );\r
+void    MXAPI mxRowAddress( MXBYTE ra );\r
+//\r
+// Virtual screen\r
+//\r
+void    MXAPI mxGetVirtualScreen( MXUINT far *width, MXUINT far *height );\r
+void    MXAPI mxSetVirtualScreen( MXUINT width, MXUINT height );\r
+void    MXAPI mxPan( MXUINT x, MXUINT y );\r
+//\r
+// Clipping\r
+//\r
+MXBOOL  MXAPI mxGetClip( void );\r
+MXBOOL  MXAPI mxGetClipRegion( MXSINT far *x, MXSINT far *y, MXSINT far *w, MXSINT far *h );\r
+MXBOOL  MXAPI mxSetClip( MXBOOL );\r
+void    MXAPI mxSetClipRegion( MXUINT x, MXUINT y, MXUINT width, MXUINT height );\r
+//\r
+// Graphics\r
+//\r
+void    MXAPI mxBitBlt( MXSINT sx, MXSINT sy, MXUINT width, MXUINT height, MXSINT dx, MXSINT dy );\r
+void    MXAPI mxFillBox( MXSINT x, MXSINT y, MXUINT width, MXUINT height, MXUINT color, MXUINT op );\r
+MXBYTE  MXAPI mxGetPixel( MXSINT x, MXSINT y );\r
+void    MXAPI mxPutPixel( MXSINT x, MXSINT y, MXBYTE color );\r
+void    MXAPI mxLine( MXSINT x1, MXSINT y1, MXSINT x2, MXSINT y2, MXUINT color, MXUINT op );\r
+void    MXAPI mxGetImage( MXPTR img, MXSINT x, MXSINT y, MXUINT width, MXUINT height );\r
+void    MXAPI mxPutImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT op );\r
+void    MXAPI mxPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT width, MXUINT height );\r
+void    MXAPI mxTransPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT w, MXUINT h );\r
+void    MXAPI mxCircle( MXSINT x, MXSINT y, MXUINT radius, MXBYTE color );\r
+void    MXAPI mxStretchImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT neww, MXUINT newh, MXUINT op );\r
+//\r
+// Palette\r
+//\r
+void    MXAPI mxColorToGray( MXPTR source, MXPTR dest, MXUINT count );\r
+void    MXAPI mxGammaCorrect( MXPTR source, MXPTR dest, MXUINT count );\r
+void    MXAPI mxGetColor( MXUINT index, MXSINT far *r, MXSINT far *g, MXSINT far *b );\r
+void    MXAPI mxSetColor( MXUINT index, MXSINT red, MXSINT green, MXSINT blue );\r
+void    MXAPI mxGetPalette( MXPTR palette, MXUINT index, MXUINT count );\r
+void    MXAPI mxSetPalette( MXPTR palette, MXUINT index, MXUINT count );\r
+void    MXAPI mxFadePalette( MXPTR, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT );\r
+void    MXAPI mxRotatePalette( MXPTR palette, MXUINT count, MXSINT step );\r
+//\r
+// Text\r
+//\r
+MXSINT  MXAPI mxSetFont( MXPTR font, MXUINT charwidth, MXUINT charheight );\r
+void    MXAPI mxSetTextColor( MXUINT color, MXUINT op );\r
+void    MXAPI mxGetTextStep( MXSINT far *deltax, MXSINT far *deltay );\r
+void    MXAPI mxSetTextStep( MXSINT deltax, MXSINT deltay );\r
+void    MXAPI mxOutChar( MXSINT x, MXSINT y, char c );\r
+void    MXAPI mxOutText( MXSINT x, MXSINT y, char far *sz );\r
+//\r
+// Convex polygons\r
+//\r
+void    MXAPI mxFillPoly( MXUINT, MXPTR, MXPTR, MXUINT, MXUINT );\r
+void    MXAPI mxGouraudPoly( MXUINT, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT );\r
+void    MXAPI mxTexturePoly( MXUINT, MXPTR, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+//\r
+// Remove temporary defines\r
+//\r
+#undef  MXBYTE\r
+#undef  MXBOOL\r
+#undef  MXSINT\r
+#undef  MXUINT\r
+#undef  MXPTR\r
+#undef  MXAPI\r
+\r
+#endif  // _MODEX_H_\r
diff --git a/16/xw/modex.lbr b/16/xw/modex.lbr
new file mode 100755 (executable)
index 0000000..93fc780
--- /dev/null
@@ -0,0 +1,39 @@
++-MXBB.OBJ &\r
++-MXCC.OBJ &\r
++-MXCG.OBJ &\r
++-MXCL.OBJ &\r
++-MXCR.OBJ &\r
++-MXFB.OBJ &\r
++-MXFP.OBJ &\r
++-MXGC.OBJ &\r
++-MXGI.OBJ &\r
++-MXGM.OBJ &\r
++-MXGP.OBJ &\r
++-MXGV.OBJ &\r
++-MXHL.OBJ &\r
++-MXIT.OBJ &\r
++-MXLL.OBJ &\r
++-MXLN.OBJ &\r
++-MXOT.OBJ &\r
++-MXPB.OBJ &\r
++-MXPF.OBJ &\r
++-MXPG.OBJ &\r
++-MXPI.OBJ &\r
++-MXPN.OBJ &\r
++-MXPP.OBJ &\r
++-MXPT.OBJ &\r
++-MXRA.OBJ &\r
++-MXRP.OBJ &\r
++-MXSA.OBJ &\r
++-MXSC.OBJ &\r
++-MXSI.OBJ &\r
++-MXSL.OBJ &\r
++-MXSM.OBJ &\r
++-MXSP.OBJ &\r
++-MXSS.OBJ &\r
++-MXTL.OBJ &\r
++-MXVS.OBJ &\r
++-MXWD.OBJ &\r
++-MXWM.OBJ &\r
++-MXWP.OBJ &\r
++-MXWR.OBJ\r
diff --git a/16/xw/modex.pas b/16/xw/modex.pas
new file mode 100755 (executable)
index 0000000..7d9d26e
--- /dev/null
@@ -0,0 +1,194 @@
+(*\r
+   Turbo Pascal interface to the MODEX library\r
+   Copyright (c) 1993,1994 by Alessandro Scotti\r
+*)\r
+unit ModeX;\r
+interface\r
+\r
+const\r
+  (* Video modes *)\r
+  MX_TEXT       = 0;\r
+  MX_320x175    = 1;\r
+  MX_320x200    = 2;\r
+  MX_320x240    = 3;\r
+  MX_320x350    = 4;\r
+  MX_320x400    = 5;\r
+  MX_320x480    = 6;\r
+  MX_360x175    = 7;\r
+  MX_360x200    = 8;\r
+  MX_360x240    = 9;\r
+  MX_360x350    = 10;\r
+  MX_360x400    = 11;\r
+  MX_360x480    = 12;\r
+  MX_400x600    = 13;\r
+\r
+  (* Fade effects *)\r
+  MX_FADEIN     = 0;\r
+  MX_FADEOUT    = 1;\r
+\r
+  (* Raster ops *)\r
+  OP_SET        = 0;\r
+  OP_AND        = 1;\r
+  OP_OR         = 2;\r
+  OP_XOR        = 3;\r
+  OP_TRANS      = 4;\r
+  OP_ADD        = 5;\r
+  OP_MOVE       = 0;                    (* Alias for OP_SET *)\r
+\r
+procedure mxBitBlt( SX, SY: integer; Width, Height: word; DX, DY: integer );\r
+procedure mxCircle( CX, CY: integer; Radius: word; Color: byte );\r
+procedure mxChangeMode( Mode: word );\r
+procedure mxColorToGray( ColorPalette, GrayPalette: pointer; Count: word );\r
+procedure mxFadePalette( Palette: pointer; Cmd, Start, Count, R, G, B: word );\r
+procedure mxFillBox( X, Y: integer; Width, Height: word; Color: byte; Op: word );\r
+procedure mxGammaCorrect( ColorPalette, GammaPalette: pointer; Count: word );\r
+procedure mxGetAspect( var AspectX, AspectY: word );\r
+function  mxGetClipRegion( var X1, Y1, Width, Height: word ): boolean;\r
+function  mxGetClip: boolean;\r
+procedure mxGetImage( Image: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxGetPalette( Palette: pointer; Start, Count: word );\r
+function  mxGetPixel( X, Y: word ): byte;\r
+procedure mxGetScreenSize( var Width, Height: word );\r
+procedure mxGetTextStep( var DeltaX, DeltaY: integer );\r
+function  mxGetVersion: word;\r
+procedure mxGetVirtualScreen( var Width, Height: word );\r
+procedure mxInit;\r
+procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word );\r
+procedure mxOutChar( X, Y: integer; C: char );\r
+procedure mxOutText( X, Y: integer; S: pointer );\r
+procedure mxPan( X, Y: word );\r
+procedure mxPutImage( Image: pointer; X, Y: integer; Width, Height, Op: word );\r
+procedure mxPutPixel( X, Y: word; C: byte );\r
+procedure mxPutTile( Tile: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxReadPlane( Plane: byte );\r
+procedure mxRotatePalette( Palette: pointer; Count: word; Step: integer );\r
+procedure mxRowAddress( RowAddress: byte );\r
+function  mxSetClip( Clip: boolean ): boolean;\r
+procedure mxSetClipRegion( X1, Y1, Width, Height: word );\r
+procedure mxSetColor( Index, R, G, B: word );\r
+procedure mxSetFont( Font: pointer; Width, Height: word );\r
+procedure mxSetMode( Mode: word );\r
+procedure mxSetPalette( Palette: pointer; Start, Count: word );\r
+procedure mxSetTextColor( Color, Op: word );\r
+procedure mxSetTextStep( DeltaX, DeltaY: integer );\r
+procedure mxSetVirtualScreen( Width, Height: word );\r
+procedure mxStretchImage( Image: pointer; X, Y: integer; Width, Height, NewWidth, NewHeight, Op: word );\r
+procedure mxSplitScreen( Line: word );\r
+procedure mxStartAddress( StartAddress: word );\r
+procedure mxStartLine( Line: word );\r
+procedure mxTerm;\r
+procedure mxTransPutTile( Tile: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxWaitDisplay;\r
+procedure mxWaitRetrace;\r
+procedure mxWriteMode( Mode: byte );\r
+procedure mxWritePlane( Plane: byte );\r
+\r
+procedure mxFillPoly( Count: word; var Map, Points; Color: word );\r
+procedure mxGouraudPoly( Count: word; var Map, Points, Colors; BaseColor: word );\r
+procedure mxTexturePoly( Count: word; var Map, Points, ImgPoints, Texture; Width: word );\r
+\r
+procedure mxOutStr( X, Y: integer; S: string );\r
+\r
+implementation\r
+\r
+procedure mxBitBlt;                                             external;\r
+procedure mxChangeMode( Mode: word );                           external;\r
+procedure mxCircle;                                             external;\r
+procedure mxColorToGray;                                        external;\r
+procedure mxFadePalette;                                        external;\r
+procedure mxFillBox;                                            external;\r
+procedure mxGammaCorrect;                                       external;\r
+procedure mxGetAspect( var AspectX, AspectY: word );            external;\r
+function  mxGetClipRegion;                                      external;\r
+function  mxGetClip: boolean;                                   external;\r
+procedure mxGetImage;                                           external;\r
+procedure mxGetPalette( Palette: pointer; Start, Count: word ); external;\r
+function  mxGetPixel( X, Y: word ): byte;                       external;\r
+procedure mxGetScreenSize( var Width, Height: word );           external;\r
+procedure mxGetTextStep( var DeltaX, DeltaY: integer );         external;\r
+function  mxGetVersion: word;                                   external;\r
+procedure mxGetVirtualScreen( var Width, Height: word );        external;\r
+procedure mxInit;                                               external;\r
+procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word );   external;\r
+procedure mxOutChar( X, Y: integer; C: char );                  external;\r
+procedure mxOutText( X, Y: integer; S: pointer );               external;\r
+procedure mxPan( X, Y: word );                                  external;\r
+procedure mxPutImage;                                           external;\r
+procedure mxPutPixel( X, Y: word; C: byte );                    external;\r
+procedure mxPutTile;                                            external;\r
+procedure mxReadPlane( Plane: byte );                           external;\r
+procedure mxRotatePalette;                                      external;\r
+procedure mxRowAddress( RowAddress: byte );                     external;\r
+function  mxSetClip( Clip: boolean ): boolean;                  external;\r
+procedure mxSetClipRegion( X1, Y1, Width, Height: word );       external;\r
+procedure mxSetColor( Index, R, G, B: word );                   external;\r
+procedure mxSetFont( Font: pointer; Width, Height: word );      external;\r
+procedure mxSetMode( Mode: word );                              external;\r
+procedure mxSetPalette( Palette: pointer; Start, Count: word ); external;\r
+procedure mxSetTextColor( Color, Op: word );                    external;\r
+procedure mxSetTextStep( DeltaX, DeltaY: integer );             external;\r
+procedure mxSetVirtualScreen( Width, Height: word );            external;\r
+procedure mxSplitScreen( Line: word );                          external;\r
+procedure mxStartAddress( StartAddress: word );                 external;\r
+procedure mxStartLine;                                          external;\r
+procedure mxStretchImage;                                       external;\r
+procedure mxTerm;                                               external;\r
+procedure mxTransPutTile;                                       external;\r
+procedure mxWaitDisplay;                                        external;\r
+procedure mxWaitRetrace;                                        external;\r
+procedure mxWriteMode( Mode: byte );                            external;\r
+procedure mxWritePlane( Plane: byte );                          external;\r
+\r
+procedure mxFillPoly;                                           external;\r
+procedure mxGouraudPoly;                                        external;\r
+procedure mxTexturePoly;                                        external;\r
+{$L MXPB}\r
+{$L MXPF}\r
+{$L MXPG}\r
+{$L MXPT}\r
+\r
+{$L MXBB}\r
+{$L MXCC}\r
+{$L MXCG}\r
+{$L MXCL}\r
+{$L MXCR}\r
+{$L MXFB}\r
+{$L MXFP}\r
+{$L MXGI}\r
+{$L MXGM}\r
+{$L MXGP}\r
+{$L MXGV}\r
+{$L MXHL}\r
+{$L MXIT}\r
+{$L MXLN}\r
+{$L MXOT}\r
+{$L MXPI}\r
+{$L MXPN}\r
+{$L MXPP}\r
+{$L MXRA}\r
+{$L MXRP}\r
+{$L MXSA}\r
+{$L MXSC}\r
+{$L MXSI}\r
+{$L MXSL}\r
+{$L MXSM}\r
+{$L MXSP}\r
+{$L MXSS}\r
+{$L MXTL}\r
+{$L MXVS}\r
+{$L MXWD}\r
+{$L MXWM}\r
+{$L MXWP}\r
+{$L MXWR}\r
+\r
+(*\r
+   Prints a Turbo Pascal string.\r
+   Note: BP 7.0 supports ASCIIZ strings (PChar type).\r
+*)\r
+procedure mxOutStr;\r
+begin\r
+  S := S + #0;\r
+  mxOutText( X, Y, @S[1] );\r
+end;\r
+\r
+end.\r
diff --git a/16/xw/modex/DEMO01.EXE b/16/xw/modex/DEMO01.EXE
new file mode 100755 (executable)
index 0000000..28caff8
Binary files /dev/null and b/16/xw/modex/DEMO01.EXE differ
diff --git a/16/xw/modex/DEMO01.PAS b/16/xw/modex/DEMO01.PAS
new file mode 100755 (executable)
index 0000000..c684acd
--- /dev/null
@@ -0,0 +1,126 @@
+(*\r
+    DEMO01 - Sprites, page flipping and palette rotation\r
+    Copyright (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+  MAX_SPRITE = 100;\r
+type\r
+  (* Sprite structure *)\r
+  TSprite = record\r
+    X, Y : integer;                        (* Sprite coordinates *)\r
+    DX,DY: integer;                        (* Deltas for sprite movement *)\r
+    W, H : integer;                        (* Sprite width and height *)\r
+    Image: array[ 1..16, 1..16 ] of byte;  (* Sprite image data *)\r
+  end;\r
+  (* RGB color structure *)\r
+  TRgb    = record\r
+    R, G, B: byte;\r
+  end;\r
+var\r
+  S      : array[ 1..MAX_SPRITE ] of TSprite;   (* An array of sprites *)\r
+  Palette: array[ byte ] of TRgb;               (* Palette *)\r
+  Page   : word;                                (* Page offset *)\r
+  I      : word;\r
+\r
+(* Initializes a sprite structure *)\r
+procedure sxInit( var S: TSprite );\r
+var\r
+  I: word;\r
+begin\r
+  S.X := Random( 320 );  (* Initialize position with random values *)\r
+  S.Y := Random( 240 );\r
+  S.DX := Random( 7 )-3; (* Initialize speed with random values *)\r
+  S.DY := Random( 7 )-3;\r
+  S.W := 16;             (* Size is fixed in this program *)\r
+  S.H := 16;\r
+  (* The image is a square with a hole inside *)\r
+  FillChar( S.Image, SizeOf(S.Image), Random(15)+1 );\r
+  for I:=5 to 12 do FillChar( S.Image[ I, 5 ], 8, 0 );\r
+end;\r
+\r
+(* Moves a sprite *)\r
+procedure sxMove( var S: TSprite );\r
+begin\r
+  Inc( S.X, S.DX );     (* Get new position *)\r
+  Inc( S.Y, S.DY );\r
+  (* Check sprite position, change delta if needed *)\r
+  if( S.X > 320 ) then begin\r
+    S.X := 320;\r
+    S.DX := -S.DX;\r
+  end;\r
+  if( S.X < -16 ) then begin\r
+    S.X := -16;\r
+    S.DX := -S.DX;\r
+  end;\r
+  if( S.Y > 240 ) then begin\r
+    S.Y := 240;\r
+    S.DY := -S.DY;\r
+  end;\r
+  if( S.Y < -16 ) then begin\r
+    S.Y := -16;\r
+    S.DY := -S.DY;\r
+  end;\r
+  (* Draw the sprite, note the Page offset added to the *)\r
+  (* Y coordinate of the image *)\r
+  mxPutImage( @S.Image, S.X, Page+S.Y, S.W, S.H, OP_TRANS );\r
+end;\r
+\r
+begin\r
+  (* Initialize library *)\r
+  mxInit;\r
+\r
+  (* Enter graphics mode *)\r
+  mxSetMode( MX_320x240 );\r
+\r
+  (* Print initialization message *)\r
+  mxSetTextColor( 15, OP_TRANS );\r
+  mxOutStr( 4, 4, 'Initializing...' );\r
+\r
+  (* Initialize sprites *)\r
+  for I:=1 to MAX_SPRITE do sxInit( S[I] );\r
+\r
+  (* Draw background *)\r
+  for I:=1 to 192 do begin\r
+    mxCircle( 160, 480+120, I, I+63 );\r
+    mxCircle( 161, 480+120, I, I+63 );\r
+  end;\r
+\r
+  (* Compute and set palette *)\r
+  for I:=1 to 192 do with Palette[I+63] do begin\r
+    R := 0;\r
+    G := 0;\r
+    B := 0;\r
+    if( I < 64 ) then\r
+      R := I shr 1+31\r
+    else if( I < 128 ) then\r
+      G := (I-64) shr 1+31\r
+    else\r
+      B := (I-128) shr 1+31;\r
+  end;\r
+  mxSetPalette( @Palette[64], 64, 192 );\r
+\r
+  (* Main loop *)\r
+  Page := 240;\r
+  while( not KeyPressed ) do begin\r
+    (* Set clip region to current page *)\r
+    mxSetClipRegion( 0, Page, 320, 240 );\r
+    mxSetClip( TRUE );\r
+    (* Restore background *)\r
+    mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+    (* Draw sprites *)\r
+    for I:=1 to MAX_SPRITE do sxMove( S[I] );\r
+    (* Print message *)\r
+    mxOutStr( 4, Page+4, 'Some sprites moving...' );\r
+    (* Flip page *)\r
+    mxStartLine( Page );\r
+    Page := 240-Page;\r
+    (* Animate palette *)\r
+    mxSetPalette( @Palette[64], 64, 192 );\r
+    mxRotatePalette( @Palette[64], 192, 3 );\r
+  end;\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw/modex/DEMO02.EXE b/16/xw/modex/DEMO02.EXE
new file mode 100755 (executable)
index 0000000..14e7dc7
Binary files /dev/null and b/16/xw/modex/DEMO02.EXE differ
diff --git a/16/xw/modex/DEMO02.PAS b/16/xw/modex/DEMO02.PAS
new file mode 100755 (executable)
index 0000000..6b4fb6f
--- /dev/null
@@ -0,0 +1,125 @@
+(*\r
+    DEMO02 - Texture mapping and palette rotation\r
+    (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Plasma, Threed;\r
+\r
+const\r
+  LSIZE = 85;\r
+  Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+type\r
+  T2DPoint = record\r
+    X, Y: integer;\r
+  end;\r
+  TTexture = record\r
+    Desc   : array[ 0..3 ] of T2DPoint;\r
+    Width  : word;\r
+    Data   : array[ 1..64*64 ] of byte;\r
+  end;\r
+  TQuad = record\r
+    VtxCnt : word;\r
+    Vtx    : array[ 0..3 ] of word;\r
+    Texture: word;\r
+  end;\r
+var\r
+  Vtx   : array[ 0..7 ] of TPoint;\r
+  XVtx  : array[ 0..7 ] of TPoint;\r
+  VVtx  : array[ 0..7 ] of T2DPoint;\r
+  Face  : array[ 0..5 ] of TQuad;\r
+  Txts  : array[ 0..5 ] of TTexture;\r
+  Nrm   : array[ 0..5 ] of TPoint;\r
+  XNrm  : array[ 0..5 ] of TPoint;\r
+  Page  : word;\r
+  Palette: array[ byte ] of record R, G, B: byte; end;\r
+\r
+(* Make a 64x64 plasma to be used as texture *)\r
+procedure MakeTexture( Idx: word );\r
+var\r
+  I: word;\r
+begin\r
+  mxFillBox( 0, 0, 64, 64, 0, OP_SET );\r
+  MakePlasma( 0, 0, 64, 64, 96, Random(192)+1, Random(192)+1, Random(192)+1 );\r
+  mxGetImage( @Txts[Idx].Data, 0, 0, 64, 64 );\r
+  (* Texture vertexes are 8:8 fixed, add $80 (0.5) for best results *)\r
+  with Txts[Idx] do begin\r
+    Desc[0].X := $80; Desc[0].Y := $80;\r
+    Desc[1].X := $80; Desc[1].Y := $3F80;\r
+    Desc[2].X := $3F80; Desc[2].Y := $3F80;\r
+    Desc[3].X := $3F80; Desc[3].Y := $80;\r
+    Width := 64;\r
+  end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+  I: integer;\r
+begin\r
+  (* Build vertexes for a cube *)\r
+  with Vtx[0] do begin X:=-LSIZE; Y:=-LSIZE; Z:=-LSIZE; end;\r
+  with Vtx[1] do begin X:=+LSIZE; Y:=-LSIZE; Z:=-LSIZE; end;\r
+  with Vtx[2] do begin X:=-LSIZE; Y:=+LSIZE; Z:=-LSIZE; end;\r
+  with Vtx[3] do begin X:=+LSIZE; Y:=+LSIZE; Z:=-LSIZE; end;\r
+  with Vtx[4] do begin X:=-LSIZE; Y:=-LSIZE; Z:=+LSIZE; end;\r
+  with Vtx[5] do begin X:=+LSIZE; Y:=-LSIZE; Z:=+LSIZE; end;\r
+  with Vtx[6] do begin X:=-LSIZE; Y:=+LSIZE; Z:=+LSIZE; end;\r
+  with Vtx[7] do begin X:=+LSIZE; Y:=+LSIZE; Z:=+LSIZE; end;\r
+  for I:=0 to 7 do begin          (* Make points 16:16 fixed *)\r
+    Vtx[I].X := Vtx[I].X*$10000;\r
+    Vtx[I].Y := Vtx[I].Y*$10000;\r
+    Vtx[I].Z := Vtx[I].Z*$10000;\r
+  end;\r
+  (* Build faces *)\r
+  with Face[0] do begin Vtx[0]:=0; Vtx[1]:=2; Vtx[2]:=3; Vtx[3]:=1; end;\r
+  with Face[1] do begin Vtx[0]:=4; Vtx[1]:=5; Vtx[2]:=7; Vtx[3]:=6; end;\r
+  with Face[2] do begin Vtx[0]:=0; Vtx[1]:=1; Vtx[2]:=5; Vtx[3]:=4; end;\r
+  with Face[3] do begin Vtx[0]:=1; Vtx[1]:=3; Vtx[2]:=7; Vtx[3]:=5; end;\r
+  with Face[4] do begin Vtx[0]:=2; Vtx[1]:=0; Vtx[2]:=4; Vtx[3]:=6; end;\r
+  with Face[5] do begin Vtx[0]:=7; Vtx[1]:=3; Vtx[2]:=2; Vtx[3]:=6; end;\r
+  for I:=0 to 5 do Face[I].Texture := I;\r
+  (* Build textures and palette *)\r
+  Randomize;\r
+  FillChar( Palette, SizeOf(Palette), 0 );\r
+  MakePlasmaPalette( Palette, PAL_RGB );\r
+  mxSetPalette( @Palette, 0, 193 );\r
+  for I:=0 to 5 do MakeTexture( I );\r
+end;\r
+\r
+var\r
+  AX, AY, AZ: byte;\r
+  I: word;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;          (* Start with hidden page *)\r
+\r
+  AX := 0;\r
+  AY := 0;\r
+  AZ := 0;\r
+  (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+  tdSetTranslation( Trans );\r
+  tdSetPerspective( 400*$10000, $10000, $10000 );\r
+  (* Main loop, all magic here! *)\r
+  while( not KeyPressed ) do begin\r
+    tdSetRotation( AX, AY, AZ );                (* Set new angles *)\r
+    tdTransform( Vtx, XVtx, 8 );                (* 3D transform points *)\r
+    tdTransformToImage( XVtx, VVtx, 8, 160, 120+Page );\r
+    Inc( AX, 1 );                               (* Bump angles *)\r
+    Inc( AY, 1 );\r
+    Inc( AZ, 2 );\r
+    mxSetClipRegion( 0, Page, 320, 240 );       (* Set clip to new page *)\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+    mxRotatePalette( @Palette[1], 192, 3 );     (* Rotate palette *)\r
+    (* Draw cube: backface culling is straighforward in this case, so *)\r
+    (* it can be handled by the polygon filling procedure *)\r
+    for I:=0 to 5 do\r
+      mxTexturePoly( 4, Face[I].Vtx, VVtx, Txts[I].Desc, Txts[I].Data, Txts[I].Width );\r
+    mxStartLine( Page );                        (* Flip pages *)\r
+    mxSetPalette( @Palette[1], 1, 192 );        (* Set new palette *)\r
+    Page := 240-Page;\r
+  end;\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw/modex/DEMO03.EXE b/16/xw/modex/DEMO03.EXE
new file mode 100755 (executable)
index 0000000..c646c4b
Binary files /dev/null and b/16/xw/modex/DEMO03.EXE differ
diff --git a/16/xw/modex/DEMO03.PAS b/16/xw/modex/DEMO03.PAS
new file mode 100755 (executable)
index 0000000..01d10f4
--- /dev/null
@@ -0,0 +1,152 @@
+(*\r
+    DEMO03 - Simple star animation, morphs between a cube and a sphere\r
+    (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+const\r
+  MAXVTX = 1000;        (* Number of points *)\r
+  EDGE = 70;            (* Length of cube edge *)\r
+  RADIUS = 90;          (* Radius of sphere *)\r
+  WAITCOUNT = 192;      (* Frames to wait for non-morphing shapes *)\r
+  MS = 32;              (* Number of steps for morphing *)\r
+  Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+  InitMorph1: array[ 0..3 ] of integer = ( 0, MS, 0, 0 );\r
+  InitMorph2: array[ 0..3 ] of integer = ( 0, 0, 0, MS );\r
+  InitDelta1: array[ 0..3 ] of integer = ( 0, -1, 0, +1 );\r
+  InitDelta2: array[ 0..3 ] of integer = ( 0, +1, 0, -1 );\r
+type\r
+  T2DPoint = record\r
+    X, Y: integer;\r
+  end;\r
+  T3DPointArray = array[ 0..MAXVTX-1 ] of TPoint;\r
+  P3DPointArray = ^T3DPointArray;\r
+var\r
+  CubeVtx, SphereVtx, Vtx, XVtx: P3DPointArray;\r
+  VVtx  : array[ 0..MAXVTX-1 ] of T2DPoint;\r
+  Page  : word;\r
+  Status, Count, Delta1, Delta2, Morph1, Morph2: integer;\r
+\r
+procedure Swap( var A, B: longint );\r
+var\r
+  L: longint;\r
+begin\r
+  L := A; A := B; B := L;\r
+end;\r
+\r
+function Toggle( A: longint ): longint;\r
+begin\r
+  Toggle := A;\r
+  if( Random(2) = 0 ) then Toggle := -A;\r
+end;\r
+\r
+procedure Init;\r
+label Retry;\r
+var\r
+  I: integer;\r
+begin\r
+  New( CubeVtx );\r
+  New( SphereVtx );\r
+  New( Vtx );\r
+  New( XVtx );\r
+  (* Build vertexes (yes, I know this piece of code is terrible) *)\r
+  Randomize;\r
+  for I:=0 to MAXVTX-1 do begin\r
+    with CubeVtx^[I] do begin\r
+      (* Build cube *)\r
+      X := (longint(Random(2*EDGE))-EDGE)*$10000;\r
+      Y := (longint(Random(2*EDGE))-EDGE)*$10000;\r
+      Z := Toggle( EDGE*$10000 );\r
+      case Random(3) of\r
+        0: Swap( X, Z );\r
+        1: Swap( Y, Z );\r
+      end;\r
+    end;\r
+    with SphereVtx^[I] do begin\r
+      (* Build sphere *)\r
+Retry:\r
+      X := (longint(Random(2*RADIUS))-RADIUS);\r
+      Y := (longint(Random(2*RADIUS))-RADIUS);\r
+      if( X*X+Y*Y > RADIUS*RADIUS ) then goto Retry;\r
+      Z := Toggle( Round( Sqrt( Abs( RADIUS*RADIUS-X*X-Y*Y ) ) ) );\r
+      case Random(3) of\r
+        0: Swap( X, Z );\r
+        1: Swap( Y, Z );\r
+      end;\r
+      X := X * $10000; Y := Y * $10000; Z := Z * $10000;\r
+    end;\r
+  end;\r
+  (* Initialize morphing *)\r
+  Move( CubeVtx^, Vtx^, SizeOf(Vtx^) );\r
+  Status := 0;\r
+  Count := WAITCOUNT;\r
+end;\r
+\r
+procedure Morph;\r
+var\r
+  I: integer;\r
+begin\r
+  (* Fully unoptimized, slowest loop I could think of! *)\r
+  for I:=0 to MAXVTX-1 do begin\r
+    Vtx^[I].X := ((CubeVtx^[I].X * Morph1)+(SphereVtx^[I].X * Morph2)) div MS;\r
+    Vtx^[I].Y := ((CubeVtx^[I].Y * Morph1)+(SphereVtx^[I].Y * Morph2)) div MS;\r
+    Vtx^[I].Z := ((CubeVtx^[I].Z * Morph1)+(SphereVtx^[I].Z * Morph2)) div MS;\r
+  end;\r
+end;\r
+\r
+var\r
+  AX, AY, AZ: byte;\r
+  I: word;\r
+  C: char;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;          (* Start with hidden page *)\r
+\r
+  AX := 0;\r
+  AY := 0;\r
+  AZ := 0;\r
+  (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+  tdSetTranslation( Trans );\r
+  tdSetPerspective( 400*$10000, $10000, $10000 );\r
+  C := #0;\r
+  repeat\r
+    tdSetRotation( AX, AY, AZ );                (* Set new angles *)\r
+    tdTransform( Vtx^, XVtx^, MAXVTX );         (* 3D transform points *)\r
+    tdTransformToImage( XVtx^, VVtx, MAXVTX, 160, 120+Page );\r
+    Inc( AX, 1 );                               (* Bump angles *)\r
+    Inc( AY, 1 );\r
+    Inc( AZ, 2 );\r
+    mxSetClipRegion( 0, Page, 320, 240 );       (* Set clip to new page *)\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+    (* Draw points *)\r
+    for I:=0 to MAXVTX-1 do\r
+      mxPutPixel( VVtx[I].X, VVtx[I].Y, 128 + XVtx^[I].Z shr 18 );\r
+    mxStartLine( Page );                        (* Flip pages *)\r
+    Page := 240-Page;\r
+    (* Morph *)\r
+    if( Odd(Status) ) then begin\r
+      Morph;\r
+      Inc( Morph1, Delta1 );\r
+      Inc( Morph2, Delta2 );\r
+      if( Morph1 < 0 )or( Morph2 < 0 ) then Inc( Status );\r
+      if( Status = 4 ) then Status := 0;\r
+    end\r
+    else begin\r
+      Dec( Count );\r
+      if( Count < 0 ) then begin\r
+        Inc( Status );\r
+        Count :=  WAITCOUNT;\r
+        Morph1 := InitMorph1[Status];\r
+        Morph2 := InitMorph2[Status];\r
+        Delta1 := InitDelta1[Status];\r
+        Delta2 := InitDelta2[Status];\r
+      end;\r
+    end;\r
+  until( KeyPressed );\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw/modex/DEMO04.DAT b/16/xw/modex/DEMO04.DAT
new file mode 100755 (executable)
index 0000000..72aaad0
Binary files /dev/null and b/16/xw/modex/DEMO04.DAT differ
diff --git a/16/xw/modex/DEMO04.EXE b/16/xw/modex/DEMO04.EXE
new file mode 100755 (executable)
index 0000000..1fec5e8
Binary files /dev/null and b/16/xw/modex/DEMO04.EXE differ
diff --git a/16/xw/modex/DEMO04.PAS b/16/xw/modex/DEMO04.PAS
new file mode 100755 (executable)
index 0000000..1a94631
--- /dev/null
@@ -0,0 +1,198 @@
+(*\r
+    DEMO04 - Multiple textures and triple buffering (3 pages)\r
+    (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+const\r
+  MAXVTX = 256;\r
+  MAXCUB = 2;\r
+  MAXTXT = 2;\r
+  Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+  TxtSunDial: array[ 0..7 ] of word = (\r
+    $7F80,$0080, $0080,$0080, $0080,$7E80, $7F80,$7E80 );\r
+  TxtSapphire : array[ 0..7 ] of word = (\r
+    $0080,$0080, $0080,$1F80, $1F80,$1F80, $1F80,$0080 );\r
+  TxtMarble: array[ 0..7 ] of word = (\r
+    $0080,$8080, $0080,$FD80, $7F80,$FD80, $7F80,$8080 );\r
+type\r
+  T2DPoint = record\r
+    X, Y: integer;\r
+  end;\r
+  TTexture = record\r
+    Desc   : array[ 0..3 ] of record X, Y: word end;\r
+    Width  : word;\r
+    Data   : pointer;\r
+  end;\r
+  TQuad = record\r
+    Vtx    : array[ 0..3 ] of word;\r
+    Texture: word;\r
+  end;\r
+  TCube    = record\r
+    Face   : array[ 0..5 ] of TQuad;\r
+    Base   : integer;\r
+  end;\r
+var\r
+  Vtx, XVtx: array[ 0..MAXVTX ] of TPoint;\r
+  VVtx     : array[ 0..MAXVTX ] of T2DPoint;\r
+  Cube     : array[ 0..MAXCUB ] of TCube;\r
+  ZList    : array[ 0..MAXCUB ] of integer;\r
+  VtxCnt   : word;\r
+  Txts     : array[ 0..MAXTXT ] of TTexture;\r
+  Page     : word;\r
+  Palette  : array[ byte ] of record R, G, B: byte; end;\r
+  TxtDat1, TxtDat2: pointer;\r
+\r
+(* Add a new entry to the vertex array *)\r
+procedure AddVtx( PX, PY, PZ: longint );\r
+begin\r
+  with Vtx[VtxCnt] do begin X:=PX*$10000; Y:=PY*$10000; Z:=PZ*$10000; end;\r
+  Inc( VtxCnt );\r
+end;\r
+\r
+procedure MakeCube( var C: TCube; X1,Y1,Z1, X2,Y2,Z2, TX,TY,TZ, Texture: integer );\r
+const\r
+  FaceIdx: array[ 0..23 ] of integer = (\r
+    0,1,2,3, 0,4,5,1, 1,5,6,2, 2,6,7,3, 3,7,4,0, 6,5,4,7 );\r
+var\r
+  I, VC: integer;\r
+begin\r
+  VC := VtxCnt;\r
+  C.Base := VC;\r
+  AddVtx( X1+TX, Y1+TY, Z1+TZ );\r
+  AddVtx( X2+TX, Y1+TY, Z1+TZ );\r
+  AddVtx( X2+TX, Y2+TY, Z1+TZ );\r
+  AddVtx( X1+TX, Y2+TY, Z1+TZ );\r
+  AddVtx( X1+TX, Y1+TY, Z2+TZ );\r
+  AddVtx( X2+TX, Y1+TY, Z2+TZ );\r
+  AddVtx( X2+TX, Y2+TY, Z2+TZ );\r
+  AddVtx( X1+TX, Y2+TY, Z2+TZ );\r
+  for I:=0 to 23 do C.Face[I shr 2].Vtx[I and 3] := VC+FaceIdx[I];\r
+  for I:=0 to 5 do C.Face[I].Texture := Texture;\r
+end;\r
+\r
+procedure MakeTexture( Idx: integer; var VtxData );\r
+var\r
+  P: ^word;\r
+  I: integer;\r
+begin\r
+  P := @VtxData;\r
+  with Txts[Idx] do begin\r
+    for I:=0 to 3 do begin\r
+      Desc[I].X := P^; Inc( P );\r
+      Desc[I].Y := P^; Inc( P );\r
+    end;\r
+    Width := 129;\r
+    Data := TxtDat1;\r
+  end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+  I: integer;\r
+  V: integer;\r
+  F: file;\r
+  P: array[ 1..768 ] of byte;\r
+begin\r
+  (* Initialize objects *)\r
+  VtxCnt := 0;\r
+  MakeCube( Cube[0], -64,-64,8, 64,64,-8, 0,0,0, 1 );   (* Sundial *)\r
+  Cube[0].Face[0].Texture := 0;\r
+  V := VtxCnt;\r
+  MakeCube( Cube[1], -16,-16,16, 16,16,-16, 0,0,0, 2 ); (* Sapphire *)\r
+  tdSetTranslation( Trans );\r
+  tdSetRotation( 32, 32, 00 );\r
+  tdRotate( Vtx[V], XVtx[V], 8 );       (* Got to rotate this cube *)\r
+  for I:=V to V+7 do begin\r
+    Vtx[I].X := XVtx[I].X;\r
+    Vtx[I].Y := XVtx[I].Y;\r
+    Vtx[I].Z := XVtx[I].Z + 100*$10000;\r
+  end;\r
+  MakeCube( Cube[2], -64,-4,48, 64,4,-48, 0,68,56, 1 ); (* Marble *)\r
+  (* Load texture and palette *)\r
+  Assign( F, 'DEMO04.DAT' );\r
+  Reset( F, 1 );\r
+  BlockRead( F, P, SizeOf(P) );\r
+  mxSetPalette( @P, 0, 256 );\r
+  GetMem( TxtDat1, 63*1024 );\r
+  BlockRead( F, TxtDat1^, 129*286 );\r
+  Close( F );\r
+  TxtDat2 := Ptr( Seg(TxtDat1^), Ofs(TxtDat1^)+129*254 );\r
+  (* Init textures *)\r
+  MakeTexture( 0, TxtSundial );\r
+  MakeTexture( 1, TxtMarble );\r
+  MakeTexture( 2, TxtSapphire );\r
+  Txts[2].Data := TxtDat2;\r
+end;\r
+\r
+(* Sort procedure, not worth optimizing with only a few objects *)\r
+procedure SortObjects;\r
+var\r
+  I, J, K: integer;\r
+  ZMax: array[ 0..MAXCUB ] of longint;\r
+  ZI: integer;\r
+  L: longint;\r
+begin\r
+  for I:=0 to MAXCUB do begin\r
+    L := XVtx[Cube[I].Base].Z;\r
+    for J:=1 to 7 do\r
+      if( L > XVtx[Cube[I].Base+J].Z ) then L := XVtx[Cube[I].Base+J].Z;\r
+    ZMax[I] := L;\r
+    ZList[I] := I;\r
+  end;\r
+  for I:=0 to MAXCUB-1 do begin\r
+    ZI := I;\r
+    for J:=I+1 to MAXCUB do\r
+      if( ZMax[ZList[J]] > ZMax[ZList[ZI]] ) then ZI := J;\r
+    if( ZI <> I ) then begin\r
+      K := ZList[I];\r
+      ZList[I] := ZList[ZI];\r
+      ZList[ZI] := K;\r
+    end;\r
+  end;\r
+end;\r
+\r
+var\r
+  AX, AY, AZ: byte;\r
+  I, J, K: word;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;          (* Start with hidden page *)\r
+\r
+  (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+  AX := 0; AY := 0; AZ := 0;\r
+  tdSetTranslation( Trans );\r
+  tdSetPerspective( 600*$10000, $10000, $10000 );\r
+  (* Main loop, all magic here! *)\r
+  while( not KeyPressed ) do begin\r
+    tdSetRotation( AX, AY, AZ );                (* Set new angles *)\r
+    tdTransform( Vtx, XVtx, VtxCnt );           (* 3D transform points *)\r
+    tdTransformToImage( XVtx, VVtx, VtxCnt, 160, 120+Page );\r
+    Inc( AX, 1 );                               (* Bump angles *)\r
+    Inc( AY, 2 );\r
+    Inc( AZ, 1 );\r
+    mxSetClipRegion( 0, Page, 320, 240 );       (* Set clip to new page *)\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+    (* Draw objects *)\r
+    SortObjects;\r
+    for I:=0 to MAXCUB do with Cube[ZList[I]] do begin\r
+      for J:=0 to 5 do begin\r
+        K := Face[J].Texture;\r
+        mxTexturePoly( 4, Face[J].Vtx, VVtx, Txts[K].Desc, Txts[K].Data^, Txts[K].Width );\r
+      end;\r
+    end;\r
+    (* Flip page: at 320x240 the Start Address Register Low is always zero *)\r
+    case Page of\r
+      0  : begin PortW[$3D4] := $000C; Page := 240; end;\r
+      240: begin PortW[$3D4] := $4B0C; Page := 480; end;\r
+      480: begin PortW[$3D4] := $960C; Page := 0; end;\r
+    end;\r
+    mxWaitRetrace; (* If the frame rate seems low, try to remove this line *)\r
+  end;\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw/modex/DEMO05.EXE b/16/xw/modex/DEMO05.EXE
new file mode 100755 (executable)
index 0000000..21a7c20
Binary files /dev/null and b/16/xw/modex/DEMO05.EXE differ
diff --git a/16/xw/modex/DEMO05.PAS b/16/xw/modex/DEMO05.PAS
new file mode 100755 (executable)
index 0000000..819c5cf
--- /dev/null
@@ -0,0 +1,131 @@
+(*\r
+   DEMO05 - A Gouraud-shaded rotating torus\r
+   (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+(* Define ALTPAL for alternate palette *)\r
+{$define ALTPAL}\r
+\r
+const\r
+  MAXVTX1 = 15; RADIUS1 = 70;   (* MAXVTX1+1 must be multiple of 4 *)\r
+  MAXVTX2 = 15; RADIUS2 = 30;\r
+  MAXVTX  = (MAXVTX1+1)*(MAXVTX2+1)-1;\r
+  MAXFACE = MAXVTX;\r
+  Trans : TPoint = ( X:0; Y:0; Z:0 );           (* Object translation *)\r
+  Light : TPoint = ( X:0; Y:0; Z:-63*$10000 );  (* Light direction *)\r
+type\r
+  TQuad   = record\r
+    QVtx  : array[ 0..3 ] of integer;\r
+  end;\r
+var\r
+  Vtx, XVtx : array[ 0..MAXVTX ] of TPoint;     (* Points *)\r
+  VVtx      : array[ 0..MAXVTX ] of record X, Y: integer end;\r
+  Face      : array[ 0..MAXFACE ] of TQuad;     (* Polys *)\r
+  Culled    : array[ 0..MAXFACE ] of integer;\r
+  GNrm,XGNrm: array[ 0..MAXVTX ] of TVector;    (* Gouraud normals *)\r
+  VtxLight  : array[ 0..MAXVTX ] of integer;    (* Points brightness *)\r
+  Page      : word;\r
+\r
+function GetVtx( I1, I2: integer ): integer;\r
+begin\r
+  GetVtx := (I1 mod (MAXVTX1+1))*(MAXVTX2+1) + I2 mod (MAXVTX2+1);\r
+end;\r
+\r
+procedure Init;\r
+var\r
+  R, N, X, Y, Z: real;\r
+  I, J, K, V: integer;\r
+begin\r
+  (* Build vertexes *)\r
+  for I:=0 to MAXVTX1 do begin\r
+    K := (I + (MAXVTX1+1) shr 2) mod (MAXVTX1+1);\r
+    R := RADIUS1 + RADIUS2*Cos( 2*K*Pi / (MAXVTX1+1) );\r
+    for J:=0 to MAXVTX2 do begin\r
+      V := I*(MAXVTX2+1)+J;                     (* Index of current vertex *)\r
+      (* Compute coordinates of current vertex *)\r
+      X := R*Cos(2*J*Pi / (MAXVTX2+1));         (* Get coordinates *)\r
+      Y := R*Sin(2*J*Pi / (MAXVTX2+1));\r
+      Z := RADIUS2*Sin(2*K*Pi / (MAXVTX1+1));\r
+      Vtx[V].X := Round( X )*$10000;            (* Save coordinates *)\r
+      Vtx[V].Y := Round( Y )*$10000;\r
+      Vtx[V].Z := Round( Z )*$10000;\r
+      (* Compute direction of Gouraud normal thru current vertex *)\r
+      X := X - RADIUS1*Cos(2*J*Pi / (MAXVTX2+1));\r
+      Y := Y - RADIUS1*Sin(2*J*Pi / (MAXVTX2+1));\r
+      N := Sqrt( X*X + Y*Y + Z*Z );             (* Get vector length *)\r
+      GNrm[V].X := Trunc( X*$10000/N );         (* Save normal vector *)\r
+      GNrm[V].Y := Trunc( Y*$10000/N );\r
+      GNrm[V].Z := Trunc( Z*$10000/N );\r
+    end;\r
+  end;\r
+  (* Generate faces so that depth-sorting is not needed: there are still *)\r
+  (* some *very* little errors, but this is the best I could devise *)\r
+  J := 0;\r
+  K := 0;\r
+  for I:=0 to MAXFACE do with Face[I] do begin\r
+    QVtx[0] := GetVtx( J, K );\r
+    QVtx[1] := GetVtx( J, K+1 );\r
+    QVtx[2] := GetVtx( J+1, K+1 );\r
+    QVtx[3] := GetVtx( J+1, K );\r
+    Inc( K );\r
+    if( K > MAXVTX2 ) then begin\r
+      K := 0;\r
+      Inc( J );\r
+    end;\r
+  end;\r
+{$ifndef ALTPAL}\r
+  for I:=0 to 63 do mxSetColor( I+64, 0, 0, I );     (* Blue palette *)\r
+{$else}\r
+  for I:=0 to 31 do mxSetColor(I+64, 0, I shl 1, 0); (* Green neon palette *)\r
+  for I:=32 to 63 do mxSetColor ( I+64, (I-32) shl 1, 63, (I-32) shl 1 );\r
+{$endif}\r
+end;\r
+\r
+var\r
+  AX, AY, AZ: byte;\r
+  I: word;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;          (* Start with hidden page *)\r
+\r
+  AX := 0;\r
+  AY := 0;\r
+  AZ := 0;\r
+  (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+  tdSetTranslation( Trans );\r
+  tdSetLight( Light );\r
+  tdSetPerspective( 400*$10000, $10000, $10000 );\r
+  (* Main loop, all magic here! *)\r
+  while( not KeyPressed ) do begin\r
+    tdSetRotation( AX, AY, AZ );                (* Set new angles *)\r
+    tdTransform( Vtx, XVtx, MAXVTX+1 );         (* 3D transform points *)\r
+    tdTransformToImage( XVtx, VVtx, MAXVTX+1, 160, 120+Page );\r
+    tdRotate( GNrm, XGNrm, MAXVTX+1 );          (* Rotate Gouraud normals *)\r
+    tdTransformLight( XGNrm, VtxLight, MAXVTX+1 );\r
+    (* Backplane culling is not really needed here! *)\r
+    FillChar( Culled, SizeOf(Culled), 0 );\r
+    tdBackPlaneCull( Face, XVtx, Culled, MAXFACE+1, SizeOf(TQuad) );\r
+    Inc( AX, 1 );                               (* Bump angles *)\r
+    Inc( AY, 2 );\r
+    Inc( AZ, 3 );\r
+    mxSetClipRegion( 0, Page, 320, 240 );       (* Set clip to new page *)\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+    (* Draw polygons *)\r
+    for I:=0 to MAXFACE do with Face[I] do\r
+      if( Culled[I] >= 0 ) then mxGouraudPoly( 4, QVtx, VVtx, VtxLight, 64 );\r
+    (* Flip page: at 320x240 the Start Address Register Low is always zero *)\r
+    case Page of\r
+      0  : begin PortW[$3D4] := $000C; Page := 240; end;\r
+      240: begin PortW[$3D4] := $4B0C; Page := 480; end;\r
+      480: begin PortW[$3D4] := $960C; Page := 0; end;\r
+    end;\r
+    mxWaitRetrace; (* Uncomment this instruction if screen flickers *)\r
+  end;\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw/modex/DEMO06.DAT b/16/xw/modex/DEMO06.DAT
new file mode 100755 (executable)
index 0000000..1ac2c2b
Binary files /dev/null and b/16/xw/modex/DEMO06.DAT differ
diff --git a/16/xw/modex/DEMO06.EXE b/16/xw/modex/DEMO06.EXE
new file mode 100755 (executable)
index 0000000..f1308e8
Binary files /dev/null and b/16/xw/modex/DEMO06.EXE differ
diff --git a/16/xw/modex/DEMO06.PAS b/16/xw/modex/DEMO06.PAS
new file mode 100755 (executable)
index 0000000..f26af06
--- /dev/null
@@ -0,0 +1,135 @@
+(*\r
+    DEMO06 - Magnifying glass\r
+    (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+  R = 40;               (* Lens radius *)\r
+  K : real = 1.8;       (* Magnifying factor, less makes a stronger lens *)\r
+type\r
+  TLine   = array[ 0..319 ] of byte;\r
+  PLine   = ^TLine;\r
+  TScreen = array[ 0..239 ] of PLine;\r
+var\r
+  VScreen: TScreen;                             (* Virtual screen *)\r
+  BallX  : array[ 0..R, 0..R ] of integer;\r
+  BallY  : array[ 0..R, 0..R ] of integer;\r
+  Sprite : array[ -R..R, -R..R ] of byte;\r
+  Page   : word;\r
+\r
+(* Returns "lens-view" coordinates of X,Y *)\r
+procedure GetCoords( var X, Y: integer );\r
+var\r
+  LR, Z, SinA, SinB, TgB, Q: real;\r
+begin\r
+  LR := Sqrt( X*X + Y*Y );\r
+  if( LR = 0 ) then Exit;\r
+  if( LR < R ) then begin\r
+    Z := Sqrt( R*R - LR*LR );\r
+    SinA := LR / R;\r
+    SinB := SinA / K;\r
+    TgB := SinB / Sqrt( 1-SinB*SinB );\r
+    Q := LR - TgB*Z;\r
+    X := Round( X * ( Q/LR ) );\r
+    Y := Round( Y * ( Q/LR ) );\r
+  end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+  F      : file;\r
+  Palette: array[ 0..767 ] of record R, G, B: byte; end;\r
+  X, Y,\r
+  X2, Y2 : integer;\r
+begin\r
+  (* Load background image *)\r
+  Assign( F, 'demo06.dat' );\r
+  Reset( F, 1 );\r
+  BlockRead( F, Palette, 768 );\r
+  mxSetPalette( @Palette, 0, 256 );\r
+  for Y:=0 to 239 do begin\r
+    New( VScreen[Y] );\r
+    BlockRead( F, VScreen[Y]^, 320 );\r
+    mxPutImage( VScreen[Y], 0, 480+Y, 320, 1, OP_MOVE );\r
+  end;\r
+  Close( F );\r
+  (* Build lens *)\r
+  for X:=0 to R do begin\r
+    for Y:=0 to R do begin\r
+      X2 := X;\r
+      Y2 := Y;\r
+      GetCoords( X2, Y2 );\r
+      BallX[X, Y] := X2;\r
+      BallY[X, Y] := Y2;\r
+    end;\r
+  end;\r
+end;\r
+\r
+procedure PutLens( OX, OY: integer );\r
+var\r
+  X, Y: integer;\r
+begin\r
+  for X:=0 to R do begin\r
+    for Y:=0 to R do begin\r
+      Sprite[Y][X] := VScreen[ OY+BallY[X,Y] ]^[ OX+BallX[X,Y] ];\r
+      Sprite[Y][-X] := VScreen[ OY+BallY[X,Y] ]^[ OX-BallX[X,Y] ];\r
+      Sprite[-Y][X] := VScreen[ OY-BallY[X,Y] ]^[ OX+BallX[X,Y] ];\r
+      Sprite[-Y][-X] := VScreen[ OY-BallY[X,Y] ]^[ OX-BallX[X,Y] ];\r
+    end;\r
+  end;\r
+  (* Draw the sprite *)\r
+  mxPutImage( @Sprite, OX-R, OY-R+Page, 2*R+1, 2*R+1, OP_MOVE );\r
+end;\r
+\r
+function Delta: integer;\r
+begin\r
+  Delta := Random(3)+2;\r
+end;\r
+\r
+procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer );\r
+begin\r
+  if( Cond ) then begin\r
+    Coord := NewCoord;\r
+    DeltaC := Sign*Delta;\r
+  end;\r
+end;\r
+\r
+var\r
+  X, Y, DX, DY: integer;\r
+  C: char;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;\r
+  X := R;\r
+  Y := R;\r
+  Randomize;\r
+  DX := Delta;\r
+  DY := Delta;\r
+\r
+  (* Main loop *)\r
+  repeat\r
+    (* Update video *)\r
+    mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+    PutLens( X, Y );\r
+    mxCircle( X, Page+Y, R, 0 );\r
+    (* Update lens coordinates *)\r
+    Inc( X, DX );\r
+    Check( X+R >= 319, X, DX, 319-R, -1 );\r
+    Check( X <= R, X, DX, R, +1 );\r
+    Inc( Y, DY );\r
+    Check( Y+R >= 239, Y, DY, 239-R, -1 );\r
+    Check( Y <= R, Y, DY, R, +1 );\r
+    (* Flip pages: double buffering, avoid wait for display *)\r
+    case Page of\r
+      0  : begin PortW[$3D4] := $000C; Page := 240; end;\r
+      240: begin PortW[$3D4] := $4B0C; Page := 0; end;\r
+    end;\r
+    mxWaitRetrace; (* Wait for hidden page to show *)\r
+  until( KeyPressed );\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw/modex/DEMO07.EXE b/16/xw/modex/DEMO07.EXE
new file mode 100755 (executable)
index 0000000..8a40116
Binary files /dev/null and b/16/xw/modex/DEMO07.EXE differ
diff --git a/16/xw/modex/DEMO07.PAS b/16/xw/modex/DEMO07.PAS
new file mode 100755 (executable)
index 0000000..04fff79
--- /dev/null
@@ -0,0 +1,68 @@
+(*\r
+    DEMO07 - Hardware scrolling\r
+    Copyright (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+  (* Change this if scrolling seems jerky (this simple program does *)\r
+  (* not handle vertical retrace/display very well) *)\r
+  STEPS = 5;\r
+\r
+procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer );\r
+begin\r
+  if( Cond ) then begin\r
+    Coord := NewCoord;\r
+    DeltaC := Sign*(Random(3)+2);\r
+  end;\r
+end;\r
+\r
+var\r
+  I, X, Y, DX, DY: integer;\r
+begin\r
+  (* Initialize library and graphics mode *)\r
+  mxInit;\r
+  mxSetMode( MX_320x200 );\r
+  (* Set a 640x400 virtual screen *)\r
+  mxSetVirtualScreen( 640, 400 );\r
+  mxSetClip( TRUE );\r
+\r
+  X := 0;\r
+  Y := 0;\r
+  DX := 1;\r
+  DY := 1;\r
+\r
+  (* Main loop: draw lines, circles, points and rectangles in separate *)\r
+  (* 320x200 windows, while smoothly panning virtual screen *)\r
+  while( not KeyPressed ) do begin\r
+    (* Points *)\r
+    mxSetClipRegion( 0, 0, 320, 200 );\r
+    for I:=1 to STEPS do\r
+      mxPutPixel( Random(320), Random(200), Random(16) );\r
+    (* Lines *)\r
+    mxSetClipRegion( 0, 200, 320, 200 );\r
+    for I:=1 to STEPS do\r
+      mxLine( Random(320), Random(200)+200, Random(320), Random(200)+200, Random(16), OP_SET );\r
+    (* Circles *)\r
+    mxSetClipRegion( 320, 0, 320, 200 );\r
+    for I:=1 to STEPS do\r
+      mxCircle( Random(320)+320, Random(200), Random(100), Random(16) );\r
+    (* Boxes *)\r
+    mxSetClipRegion( 320, 200, 320, 200 );\r
+    for I:=1 to STEPS do\r
+      mxFillBox( Random(320)+320, Random(200)+200, Random(100)+1, Random(100)+1, Random(16), OP_SET );\r
+    (* Pan *)\r
+    Inc( X, DX );\r
+    Check( X+320 >= 639, X, DX, 319, -1 );\r
+    Check( X < 0, X, DX, 0, +1 );\r
+    Inc( Y, DY );\r
+    Check( Y+200 >= 399, Y, DY, 199, -1 );\r
+    Check( Y < 0, Y, DY, 0, +1 );\r
+    mxPan( X, Y );\r
+    mxWaitRetrace;\r
+  end;\r
+\r
+  (* Shutdown *)\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw/modex/MATH.INC b/16/xw/modex/MATH.INC
new file mode 100755 (executable)
index 0000000..742af41
--- /dev/null
@@ -0,0 +1,34 @@
+;\r
+; MATH.INC - Include file for THREED.ASM\r
+;\r
+\r
+; 3-dimensional point, coordinates in fixed format (16:16)\r
+;\r
+TPOINT  STRUC\r
+        X       DD      ?\r
+        Y       DD      ?\r
+        Z       DD      ?\r
+TPOINT  ENDS\r
+\r
+; 2-dimensional point, coordinates in integer format\r
+;\r
+TIMAGEPOINT     STRUC\r
+        IX      DW      ?\r
+        IY      DW      ?\r
+TIMAGEPOINT     ENDS\r
+\r
+; Fixed-point divide: EAX = EAX / arg\r
+;\r
+.xdiv   MACRO   arg\r
+        xor     edx, edx\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    arg\r
+ENDM\r
+\r
+; Fixed-point multiply: EAX = EAX * arg\r
+;\r
+.xmul   MACRO   arg\r
+        imul    arg\r
+        shrd    eax, edx, 16\r
+ENDM\r
diff --git a/16/xw/modex/PLASMA.PAS b/16/xw/modex/PLASMA.PAS
new file mode 100755 (executable)
index 0000000..237e292
--- /dev/null
@@ -0,0 +1,103 @@
+unit Plasma;\r
+interface\r
+\r
+const\r
+  PAL_RGB       = 0;\r
+  PAL_CLOUDS    = 1;\r
+  PAL_LANDSCAPE = 2;\r
+\r
+procedure MakePlasma( X, Y: integer; W, H: word; C1, C2, C3, C4: byte );\r
+procedure MakePlasmaPalette( var Palette; What: word );\r
+\r
+implementation uses Modex;\r
+\r
+procedure NewColor( XA, YA, X, Y, XB, YB: integer );\r
+var\r
+  Color: longint;\r
+begin\r
+  Color := Abs( XA-XB )+Abs( YA-YB );\r
+  Color := Random( Color shl 1 )-Color;\r
+  Color := (Color+mxGetPixel( XA, YA )+mxGetPixel( XB, YB )+1) shr 1;\r
+  if( Color < 1 ) then Color := 1;\r
+  if( Color > 192 ) then Color := 192;\r
+  if( mxGetPixel( X, Y ) = 0 ) then\r
+    mxPutPixel( X, Y, Lo(Color) );\r
+end;\r
+\r
+procedure Divide( X1, Y1, X2, Y2: integer );\r
+var\r
+  X, Y, Color: integer;\r
+begin\r
+  if not( (X2-X1<2)and(Y2-Y1<2) ) then begin\r
+    X := (X1+X2) shr 1;\r
+    Y := (Y1+Y2) shr 1;\r
+    NewColor( X1, Y1, X, Y1, X2, Y1 );\r
+    NewColor( X2, Y1, X2, Y, X2, Y2 );\r
+    NewColor( X1, Y2, X, Y2, X2, Y2 );\r
+    NewColor( X1, Y1, X1, Y, X1, Y2 );\r
+    Color := (mxGetPixel( X1, Y1 )+mxGetPixel( X2, Y1 )+\r
+              mxGetPixel( X2, Y2 )+mxGetPixel( X1, Y2 )) shr 2;\r
+    mxPutPixel( X, Y, Color );\r
+    Divide( X1, Y1, X, Y );\r
+    Divide( X, Y1, X2, Y );\r
+    Divide( X, Y, X2, Y2 );\r
+    Divide( X1, Y, X, Y2 );\r
+  end;\r
+end;\r
+\r
+procedure MakePlasma;\r
+begin\r
+  Dec( W );\r
+  Dec( H );\r
+  mxPutPixel( X, Y, C1 );\r
+  mxPutPixel( X, Y+H, C2 );\r
+  mxPutPixel( X+W, Y+H, C3 );\r
+  mxPutPixel( X+W, Y, C4 );\r
+  Divide( X, Y, X+W, Y+H );\r
+end;\r
+\r
+procedure MakePlasmaPalette;\r
+type\r
+  TPal = array[ byte ] of record R, G, B: byte end;\r
+var\r
+  I: word;\r
+begin\r
+  FillChar( TPal(Palette)[1], 192*3, 0 );\r
+  case What of\r
+    PAL_CLOUDS:\r
+      for I:=1 to 192 do begin\r
+        TPal(Palette)[I].R := Abs( I-96 )*63 div 96;\r
+        TPal(Palette)[I].G := Abs( I-96 )*63 div 96;\r
+        TPal(Palette)[I].B := 63;\r
+      end;\r
+    PAL_LANDSCAPE:\r
+      begin\r
+        for I:=0 to 31 do begin\r
+          TPal(Palette)[I+1].R := I;\r
+          TPal(Palette)[I+1].G := I;\r
+          TPal(Palette)[I+1].B := I + I shr 1+15;\r
+        end;\r
+        for I:=32 to 63 do begin\r
+          TPal(Palette)[I+1].R := 0;\r
+          TPal(Palette)[I+1].G := I;\r
+          TPal(Palette)[I+1].B := 0;\r
+        end;\r
+        for I:=64 to 191 do begin\r
+          TPal(Palette)[I+1].R := (I-64) div 3 + 15;\r
+          TPal(Palette)[I+1].G := (I-64) div 3 + 15;\r
+          TPal(Palette)[I+1].B := (I-64) div 3 + 15;\r
+        end;\r
+      end;\r
+    else\r
+      for I:=1 to 64 do begin\r
+        TPal(Palette)[I].G := I-1;\r
+        TPal(Palette)[I].B := 64-I;\r
+        TPal(Palette)[I+64].R := I-1;\r
+        TPal(Palette)[I+64].G := 64-I;\r
+        TPal(Palette)[I+128].B := I-1;\r
+        TPal(Palette)[I+128].R := 64-I;\r
+      end;\r
+  end;\r
+end;\r
+\r
+end.
\ No newline at end of file
diff --git a/16/xw/modex/QIX2.EXE b/16/xw/modex/QIX2.EXE
new file mode 100755 (executable)
index 0000000..a10d7db
Binary files /dev/null and b/16/xw/modex/QIX2.EXE differ
diff --git a/16/xw/modex/QIX2.PAS b/16/xw/modex/QIX2.PAS
new file mode 100755 (executable)
index 0000000..d1b5979
--- /dev/null
@@ -0,0 +1,210 @@
+{$E-,N+}\r
+uses Crt, Modex;\r
+\r
+const\r
+  DEFVERT = 12;         (* Vertex count *)\r
+  DEFREPL = 3;          (* Repetition count *)\r
+  DEFQIXS = 2;          (* Qixs *)\r
+  FADESPEED = 48;\r
+type\r
+  TPoint = record\r
+    X, Y : integer;\r
+  end;\r
+  TRGB = record\r
+    R, G, B: byte;\r
+  end;\r
+  TQix = record\r
+    Color: integer;\r
+    Vert : array[ 0..DEFVERT-1, 0..DEFREPL-1 ] of TPoint;\r
+    Delta: array[ 0..DEFVERT-1 ] of TPoint;\r
+  end;\r
+var\r
+  Page : integer;\r
+  MaxX,\r
+  MaxY : word;\r
+  Qix  : array[ 0..DEFQIXS-1 ] of TQix;\r
+  Pal  : array[ byte ] of TRGB;\r
+\r
+type\r
+  TReal = double;\r
+  TRPoint = record\r
+    X, Y: TReal;\r
+  end;\r
+  TMatrix = array[ 0..3, 0..3 ] of TReal;\r
+var\r
+  M: TMatrix;\r
+  G: array[ 0..DEFVERT-1 ] of TRPoint;\r
+  C: array[ 0..DEFVERT-1 ] of TRPoint;\r
+\r
+procedure BumpPal( Idx, DR, DG, DB, Steps: integer );\r
+var\r
+  I: integer;\r
+begin\r
+  for I:=1 to Steps do begin\r
+    Pal[Idx+1].R := Pal[Idx].R + DR;\r
+    Pal[Idx+1].G := Pal[Idx].G + DG;\r
+    Pal[Idx+1].B := Pal[Idx].B + DB;\r
+    Inc( Idx );\r
+  end;\r
+end;\r
+\r
+procedure InitPalette;\r
+begin\r
+  with Pal[0] do begin R:=0; G:=0; B:=0; end;\r
+  with Pal[1] do begin R:=0; G:=0; B:=62; end;\r
+  BumpPal( 1,   0, 2, -2,  31 );\r
+  BumpPal( 32,  2, -2, 0,  31 );\r
+  BumpPal( 63,  -2, 2, 2,  31 );\r
+  BumpPal( 94,  2, 0, -2,  31 );\r
+  BumpPal( 125, -2, -2, 2, 31 );\r
+end;\r
+\r
+procedure Init( var Qix: TQix; Color: integer );\r
+var\r
+  I: integer;\r
+begin\r
+  FillChar( Qix.Vert, SizeOf(Qix.Vert), 0 );\r
+  for I:=0 to DEFVERT-1 do begin\r
+    Qix.Vert[I, DEFREPL-1].X := Random( MaxX );\r
+    Qix.Vert[I, DEFREPL-1].Y := Random( MaxY );\r
+    Qix.Delta[I].X := Random(5)+1;\r
+    Qix.Delta[I].Y := Random(5)+1;\r
+  end;\r
+  Qix.Color := Color;\r
+\r
+  (* Initialize matrix (Catmull-Rom) *)\r
+  M[0,0] := -1/2; M[0,1] := 3/2; M[0,2] := -3/2; M[0,3] := 1/2;\r
+  M[1,0] := 1; M[1,1] := -5/2; M[1,2] := 2; M[1,3] := -1/2;\r
+  M[2,0] := -1/2; M[2,1] := 0; M[2,2] := 1/2; M[2,3] := 0;\r
+  M[3,0] := 0; M[3,1] := 1; M[3,2] := 0; M[3,3] := 0;\r
+end;\r
+\r
+procedure mxBezier( var Qix: TQix; I0, Idx, N: integer );\r
+var\r
+  I, J: integer;\r
+  T, T2, T3: TReal;\r
+  X0, Y0, X, Y: TReal;\r
+  Delta: TReal;\r
+begin\r
+  (* Compute coefficients *)\r
+  for I:=0 to 3 do begin\r
+    C[I].X := 0;\r
+    for J:=0 to 3 do C[I].X := C[I].X + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].X;\r
+    C[I].Y := 0;\r
+    for J:=0 to 3 do C[I].Y := C[I].Y + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].Y;\r
+  end;\r
+  X0 := C[3].X;\r
+  Y0 := C[3].Y;\r
+  Delta := 1 / N;\r
+  T := 0;\r
+  for I:=1 to N do begin\r
+    T := T + Delta;\r
+    T2 := T*T;\r
+    T3 := T*T2;\r
+    X := C[0].X*T3 + C[1].X*T2 + C[2].X*T + C[3].X;\r
+    Y := C[0].Y*T3 + C[1].Y*T2 + C[2].Y*T + C[3].Y;\r
+    mxLine( Round(X0), Page+Round(Y0), Round(X), Page+Round(Y), Qix.Color, OP_SET );\r
+    X0 := X;\r
+    Y0 := Y;\r
+  end;\r
+end;\r
+\r
+procedure Plot( var Qix: TQix; Idx: integer );\r
+var\r
+  I, J: integer;\r
+begin\r
+  for I:=0 to DEFVERT-1 do begin\r
+    mxBezier( Qix, I, Idx, 12 );\r
+  end;\r
+end;\r
+\r
+procedure Update( var Qix: TQix; Idx: integer );\r
+var\r
+  I: integer;\r
+begin\r
+  for I:=0 to DEFVERT-1 do with Qix do begin\r
+    Inc( Vert[I,Idx].X, Delta[I].X );\r
+    if( Vert[I,Idx].X < 0 ) then begin\r
+      Vert[I,Idx].X := 0;\r
+      Delta[I].X := Random( 5 )+1;\r
+    end;\r
+    if( Vert[I,Idx].X > MaxX ) then begin\r
+      Vert[I,Idx].X := MaxX;\r
+      Delta[I].X := -Random( 5 )-1;\r
+    end;\r
+    Inc( Vert[I,Idx].Y, Delta[I].Y );\r
+    if( Vert[I,Idx].Y < 0 ) then begin\r
+      Vert[I,Idx].Y := 0;\r
+      Delta[I].Y := Random( 5 )+1;\r
+    end;\r
+    if( Vert[I,Idx].Y > MaxY ) then begin\r
+      Vert[I,Idx].Y := MaxY;\r
+      Delta[I].Y := -Random( 5 )-1;\r
+    end;\r
+  end;\r
+end;\r
+\r
+procedure Copy( var Qix: TQix; Dest, Src: integer );\r
+var\r
+  I: integer;\r
+begin\r
+  for I:=0 to DEFVERT-1 do with Qix do begin\r
+    Vert[I,Dest].X := Vert[I,Src].X;\r
+    Vert[I,Dest].Y := Vert[I,Src].Y;\r
+  end;\r
+end;\r
+\r
+procedure AnimateQix;\r
+var\r
+  Q, Idx, I, J, P, Count: integer;\r
+begin\r
+  Count := 0;\r
+  P := DEFREPL-1;\r
+  I := 0;\r
+  J := 1;\r
+  repeat\r
+    mxSetClipRegion( 0, Page, MaxX+1, MaxY+1 );\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, MaxX+1, MaxY+1, 0, OP_SET );\r
+    for Q:=0 to DEFQIXS-1 do begin\r
+      Copy( Qix[Q], I, P );\r
+      Update( Qix[Q], I );\r
+      for Idx:=0 to DEFREPL-1 do begin\r
+        Plot( Qix[Q], Idx );\r
+      end;\r
+    end;\r
+    I := (I+1) mod DEFREPL;\r
+    J := (J+1) mod DEFREPL;\r
+    P := (P+1) mod DEFREPL;\r
+    Inc( Count );\r
+    mxStartLine( Page );\r
+    if( Count >= FADESPEED ) then begin\r
+      for Q:=0 to DEFQIXS-1 do begin\r
+        Inc( Qix[Q].Color );\r
+        if( Qix[Q].Color > 156 ) then\r
+          Qix[Q].Color := 1;\r
+      end;\r
+      Count := 0;\r
+    end;\r
+    Page := 240-Page;\r
+  until( KeyPressed );\r
+end;\r
+\r
+var\r
+  I: integer;\r
+begin\r
+  Randomize;\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  mxGetScreenSize( MaxX, MaxY );\r
+  for I:=0 to DEFQIXS-1 do\r
+    Init( Qix[I], (I*(155 div DEFQIXS)) mod 155 + 1 );\r
+  InitPalette;\r
+  mxSetPalette( @Pal, 0, 157 );\r
+  Page := 240;\r
+  Dec( MaxX );\r
+  Dec( MaxY );\r
+  AnimateQix;\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw/modex/README.TXT b/16/xw/modex/README.TXT
new file mode 100755 (executable)
index 0000000..306e8b9
--- /dev/null
@@ -0,0 +1,8 @@
+ModeX - A graphical library for DOS programs\r
+Copyright (c) 1993-1994 Alessandro Scotti\r
+http://www.ascotti.org/\r
+\r
+Please look at the above site in the "Art of..." and\r
+then in the "Old programs" section for more information.\r
+\r
+\r
diff --git a/16/xw/modex/SINCOS.INC b/16/xw/modex/SINCOS.INC
new file mode 100755 (executable)
index 0000000..6986eee
--- /dev/null
@@ -0,0 +1,518 @@
+;\r
+; SINCOS.INC - Sin/cos tables for THREED.ASM\r
+;\r
+\r
+tblSin  LABEL DWORD\r
+  DD    0\r
+  DD    411733\r
+  DD    823219\r
+  DD    1234209\r
+  DD    1644455\r
+  DD    2053710\r
+  DD    2461729\r
+  DD    2868265\r
+  DD    3273072\r
+  DD    3675909\r
+  DD    4076531\r
+  DD    4474698\r
+  DD    4870169\r
+  DD    5262706\r
+  DD    5652074\r
+  DD    6038037\r
+  DD    6420363\r
+  DD    6798821\r
+  DD    7173184\r
+  DD    7543226\r
+  DD    7908725\r
+  DD    8269459\r
+  DD    8625213\r
+  DD    8975771\r
+  DD    9320922\r
+  DD    9660458\r
+  DD    9994176\r
+  DD    10321873\r
+  DD    10643353\r
+  DD    10958422\r
+  DD    11266890\r
+  DD    11568571\r
+  DD    11863283\r
+  DD    12150850\r
+  DD    12431097\r
+  DD    12703856\r
+  DD    12968963\r
+  DD    13226258\r
+  DD    13475586\r
+  DD    13716797\r
+  DD    13949745\r
+  DD    14174291\r
+  DD    14390298\r
+  DD    14597637\r
+  DD    14796184\r
+  DD    14985817\r
+  DD    15166424\r
+  DD    15337895\r
+  DD    15500126\r
+  DD    15653022\r
+  DD    15796488\r
+  DD    15930439\r
+  DD    16054795\r
+  DD    16169479\r
+  DD    16274424\r
+  DD    16369565\r
+  DD    16454846\r
+  DD    16530216\r
+  DD    16595628\r
+  DD    16651044\r
+  DD    16696429\r
+  DD    16731757\r
+  DD    16757007\r
+  DD    16772163\r
+  DD    16777216\r
+  DD    16772163\r
+  DD    16757007\r
+  DD    16731757\r
+  DD    16696429\r
+  DD    16651044\r
+  DD    16595628\r
+  DD    16530216\r
+  DD    16454846\r
+  DD    16369565\r
+  DD    16274424\r
+  DD    16169479\r
+  DD    16054795\r
+  DD    15930439\r
+  DD    15796488\r
+  DD    15653022\r
+  DD    15500126\r
+  DD    15337895\r
+  DD    15166424\r
+  DD    14985817\r
+  DD    14796184\r
+  DD    14597637\r
+  DD    14390298\r
+  DD    14174291\r
+  DD    13949745\r
+  DD    13716797\r
+  DD    13475586\r
+  DD    13226258\r
+  DD    12968963\r
+  DD    12703856\r
+  DD    12431097\r
+  DD    12150850\r
+  DD    11863283\r
+  DD    11568571\r
+  DD    11266890\r
+  DD    10958422\r
+  DD    10643353\r
+  DD    10321873\r
+  DD    9994176\r
+  DD    9660458\r
+  DD    9320922\r
+  DD    8975771\r
+  DD    8625213\r
+  DD    8269459\r
+  DD    7908725\r
+  DD    7543226\r
+  DD    7173184\r
+  DD    6798821\r
+  DD    6420363\r
+  DD    6038037\r
+  DD    5652074\r
+  DD    5262706\r
+  DD    4870169\r
+  DD    4474698\r
+  DD    4076531\r
+  DD    3675909\r
+  DD    3273072\r
+  DD    2868265\r
+  DD    2461729\r
+  DD    2053710\r
+  DD    1644455\r
+  DD    1234209\r
+  DD    823219\r
+  DD    411733\r
+  DD    0\r
+  DD    -411733\r
+  DD    -823219\r
+  DD    -1234209\r
+  DD    -1644455\r
+  DD    -2053710\r
+  DD    -2461729\r
+  DD    -2868265\r
+  DD    -3273072\r
+  DD    -3675909\r
+  DD    -4076531\r
+  DD    -4474698\r
+  DD    -4870169\r
+  DD    -5262706\r
+  DD    -5652074\r
+  DD    -6038037\r
+  DD    -6420363\r
+  DD    -6798821\r
+  DD    -7173184\r
+  DD    -7543226\r
+  DD    -7908725\r
+  DD    -8269459\r
+  DD    -8625213\r
+  DD    -8975771\r
+  DD    -9320922\r
+  DD    -9660458\r
+  DD    -9994176\r
+  DD    -10321873\r
+  DD    -10643353\r
+  DD    -10958422\r
+  DD    -11266890\r
+  DD    -11568571\r
+  DD    -11863283\r
+  DD    -12150850\r
+  DD    -12431097\r
+  DD    -12703856\r
+  DD    -12968963\r
+  DD    -13226258\r
+  DD    -13475586\r
+  DD    -13716797\r
+  DD    -13949745\r
+  DD    -14174291\r
+  DD    -14390298\r
+  DD    -14597637\r
+  DD    -14796184\r
+  DD    -14985817\r
+  DD    -15166424\r
+  DD    -15337895\r
+  DD    -15500126\r
+  DD    -15653022\r
+  DD    -15796488\r
+  DD    -15930439\r
+  DD    -16054795\r
+  DD    -16169479\r
+  DD    -16274424\r
+  DD    -16369565\r
+  DD    -16454846\r
+  DD    -16530216\r
+  DD    -16595628\r
+  DD    -16651044\r
+  DD    -16696429\r
+  DD    -16731757\r
+  DD    -16757007\r
+  DD    -16772163\r
+  DD    -16777216\r
+  DD    -16772163\r
+  DD    -16757007\r
+  DD    -16731757\r
+  DD    -16696429\r
+  DD    -16651044\r
+  DD    -16595628\r
+  DD    -16530216\r
+  DD    -16454846\r
+  DD    -16369565\r
+  DD    -16274424\r
+  DD    -16169479\r
+  DD    -16054795\r
+  DD    -15930439\r
+  DD    -15796488\r
+  DD    -15653022\r
+  DD    -15500126\r
+  DD    -15337895\r
+  DD    -15166424\r
+  DD    -14985817\r
+  DD    -14796184\r
+  DD    -14597637\r
+  DD    -14390298\r
+  DD    -14174291\r
+  DD    -13949745\r
+  DD    -13716797\r
+  DD    -13475586\r
+  DD    -13226258\r
+  DD    -12968963\r
+  DD    -12703856\r
+  DD    -12431097\r
+  DD    -12150850\r
+  DD    -11863283\r
+  DD    -11568571\r
+  DD    -11266890\r
+  DD    -10958422\r
+  DD    -10643353\r
+  DD    -10321873\r
+  DD    -9994176\r
+  DD    -9660458\r
+  DD    -9320922\r
+  DD    -8975771\r
+  DD    -8625213\r
+  DD    -8269459\r
+  DD    -7908725\r
+  DD    -7543226\r
+  DD    -7173184\r
+  DD    -6798821\r
+  DD    -6420363\r
+  DD    -6038037\r
+  DD    -5652074\r
+  DD    -5262706\r
+  DD    -4870169\r
+  DD    -4474698\r
+  DD    -4076531\r
+  DD    -3675909\r
+  DD    -3273072\r
+  DD    -2868265\r
+  DD    -2461729\r
+  DD    -2053710\r
+  DD    -1644455\r
+  DD    -1234209\r
+  DD    -823219\r
+  DD    -411733\r
+tblCos  LABEL DWORD\r
+  DD    16777216\r
+  DD    16772163\r
+  DD    16757007\r
+  DD    16731757\r
+  DD    16696429\r
+  DD    16651044\r
+  DD    16595628\r
+  DD    16530216\r
+  DD    16454846\r
+  DD    16369565\r
+  DD    16274424\r
+  DD    16169479\r
+  DD    16054795\r
+  DD    15930439\r
+  DD    15796488\r
+  DD    15653022\r
+  DD    15500126\r
+  DD    15337895\r
+  DD    15166424\r
+  DD    14985817\r
+  DD    14796184\r
+  DD    14597637\r
+  DD    14390298\r
+  DD    14174291\r
+  DD    13949745\r
+  DD    13716797\r
+  DD    13475586\r
+  DD    13226258\r
+  DD    12968963\r
+  DD    12703856\r
+  DD    12431097\r
+  DD    12150850\r
+  DD    11863283\r
+  DD    11568571\r
+  DD    11266890\r
+  DD    10958422\r
+  DD    10643353\r
+  DD    10321873\r
+  DD    9994176\r
+  DD    9660458\r
+  DD    9320922\r
+  DD    8975771\r
+  DD    8625213\r
+  DD    8269459\r
+  DD    7908725\r
+  DD    7543226\r
+  DD    7173184\r
+  DD    6798821\r
+  DD    6420363\r
+  DD    6038037\r
+  DD    5652074\r
+  DD    5262706\r
+  DD    4870169\r
+  DD    4474698\r
+  DD    4076531\r
+  DD    3675909\r
+  DD    3273072\r
+  DD    2868265\r
+  DD    2461729\r
+  DD    2053710\r
+  DD    1644455\r
+  DD    1234209\r
+  DD    823219\r
+  DD    411733\r
+  DD    0\r
+  DD    -411733\r
+  DD    -823219\r
+  DD    -1234209\r
+  DD    -1644455\r
+  DD    -2053710\r
+  DD    -2461729\r
+  DD    -2868265\r
+  DD    -3273072\r
+  DD    -3675909\r
+  DD    -4076531\r
+  DD    -4474698\r
+  DD    -4870169\r
+  DD    -5262706\r
+  DD    -5652074\r
+  DD    -6038037\r
+  DD    -6420363\r
+  DD    -6798821\r
+  DD    -7173184\r
+  DD    -7543226\r
+  DD    -7908725\r
+  DD    -8269459\r
+  DD    -8625213\r
+  DD    -8975771\r
+  DD    -9320922\r
+  DD    -9660458\r
+  DD    -9994176\r
+  DD    -10321873\r
+  DD    -10643353\r
+  DD    -10958422\r
+  DD    -11266890\r
+  DD    -11568571\r
+  DD    -11863283\r
+  DD    -12150850\r
+  DD    -12431097\r
+  DD    -12703856\r
+  DD    -12968963\r
+  DD    -13226258\r
+  DD    -13475586\r
+  DD    -13716797\r
+  DD    -13949745\r
+  DD    -14174291\r
+  DD    -14390298\r
+  DD    -14597637\r
+  DD    -14796184\r
+  DD    -14985817\r
+  DD    -15166424\r
+  DD    -15337895\r
+  DD    -15500126\r
+  DD    -15653022\r
+  DD    -15796488\r
+  DD    -15930439\r
+  DD    -16054795\r
+  DD    -16169479\r
+  DD    -16274424\r
+  DD    -16369565\r
+  DD    -16454846\r
+  DD    -16530216\r
+  DD    -16595628\r
+  DD    -16651044\r
+  DD    -16696429\r
+  DD    -16731757\r
+  DD    -16757007\r
+  DD    -16772163\r
+  DD    -16777216\r
+  DD    -16772163\r
+  DD    -16757007\r
+  DD    -16731757\r
+  DD    -16696429\r
+  DD    -16651044\r
+  DD    -16595628\r
+  DD    -16530216\r
+  DD    -16454846\r
+  DD    -16369565\r
+  DD    -16274424\r
+  DD    -16169479\r
+  DD    -16054795\r
+  DD    -15930439\r
+  DD    -15796488\r
+  DD    -15653022\r
+  DD    -15500126\r
+  DD    -15337895\r
+  DD    -15166424\r
+  DD    -14985817\r
+  DD    -14796184\r
+  DD    -14597637\r
+  DD    -14390298\r
+  DD    -14174291\r
+  DD    -13949745\r
+  DD    -13716797\r
+  DD    -13475586\r
+  DD    -13226258\r
+  DD    -12968963\r
+  DD    -12703856\r
+  DD    -12431097\r
+  DD    -12150850\r
+  DD    -11863283\r
+  DD    -11568571\r
+  DD    -11266890\r
+  DD    -10958422\r
+  DD    -10643353\r
+  DD    -10321873\r
+  DD    -9994176\r
+  DD    -9660458\r
+  DD    -9320922\r
+  DD    -8975771\r
+  DD    -8625213\r
+  DD    -8269459\r
+  DD    -7908725\r
+  DD    -7543226\r
+  DD    -7173184\r
+  DD    -6798821\r
+  DD    -6420363\r
+  DD    -6038037\r
+  DD    -5652074\r
+  DD    -5262706\r
+  DD    -4870169\r
+  DD    -4474698\r
+  DD    -4076531\r
+  DD    -3675909\r
+  DD    -3273072\r
+  DD    -2868265\r
+  DD    -2461729\r
+  DD    -2053710\r
+  DD    -1644455\r
+  DD    -1234209\r
+  DD    -823219\r
+  DD    -411733\r
+  DD    0\r
+  DD    411733\r
+  DD    823219\r
+  DD    1234209\r
+  DD    1644455\r
+  DD    2053710\r
+  DD    2461729\r
+  DD    2868265\r
+  DD    3273072\r
+  DD    3675909\r
+  DD    4076531\r
+  DD    4474698\r
+  DD    4870169\r
+  DD    5262706\r
+  DD    5652074\r
+  DD    6038037\r
+  DD    6420363\r
+  DD    6798821\r
+  DD    7173184\r
+  DD    7543226\r
+  DD    7908725\r
+  DD    8269459\r
+  DD    8625213\r
+  DD    8975771\r
+  DD    9320922\r
+  DD    9660458\r
+  DD    9994176\r
+  DD    10321873\r
+  DD    10643353\r
+  DD    10958422\r
+  DD    11266890\r
+  DD    11568571\r
+  DD    11863283\r
+  DD    12150850\r
+  DD    12431097\r
+  DD    12703856\r
+  DD    12968963\r
+  DD    13226258\r
+  DD    13475586\r
+  DD    13716797\r
+  DD    13949745\r
+  DD    14174291\r
+  DD    14390298\r
+  DD    14597637\r
+  DD    14796184\r
+  DD    14985817\r
+  DD    15166424\r
+  DD    15337895\r
+  DD    15500126\r
+  DD    15653022\r
+  DD    15796488\r
+  DD    15930439\r
+  DD    16054795\r
+  DD    16169479\r
+  DD    16274424\r
+  DD    16369565\r
+  DD    16454846\r
+  DD    16530216\r
+  DD    16595628\r
+  DD    16651044\r
+  DD    16696429\r
+  DD    16731757\r
+  DD    16757007\r
+  DD    16772163\r
diff --git a/16/xw/modex/THREED.ASM b/16/xw/modex/THREED.ASM
new file mode 100755 (executable)
index 0000000..5ecd3ba
--- /dev/null
@@ -0,0 +1,872 @@
+COMMENT /\r
+        Fixed-point math functions and 3D transforms\r
+        Copyright (c) 1993,94 by Alessandro Scotti\r
+/\r
+WARN    PRO\r
+P386\r
+JUMPS\r
+LOCALS\r
+\r
+INCLUDE MATH.INC\r
+\r
+PUBLIC  tdFixedMul\r
+PUBLIC  tdGetNormal\r
+PUBLIC  tdRotate\r
+PUBLIC  tdGetSurfaceLight\r
+PUBLIC  tdSetLight\r
+PUBLIC  tdSetRotation\r
+PUBLIC  tdSetTranslation\r
+PUBLIC  tdTransform\r
+PUBLIC  tdTransformToImage\r
+PUBLIC  tdTransformLight\r
+PUBLIC  tdBackPlaneCull\r
+PUBLIC  tdSetPerspective\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Data segment\r
+;\r
+MATH_DATA       SEGMENT USE16 PARA PUBLIC 'DATA'\r
+                ASSUME ds:MATH_DATA\r
+\r
+INCLUDE         SINCOS.INC              ; Fixed 8:24 sin/cos table\r
+\r
+XRotation       TPOINT  <>              ; 3x3 rotation matrix\r
+YRotation       TPOINT  <>\r
+ZRotation       TPOINT  <>\r
+\r
+Translation     TPOINT  <>              ; Translation vector\r
+\r
+Light           TPOINT  <>              ; Light vector\r
+AmbientLight    DW      00              ; Ambient light\r
+\r
+XScale                  DD      10000h  ; Scaling factor for X coordinate\r
+YScale                  DD      10000h  ; Scaling factor for Y coordinate\r
+PerspectiveDistance     DD      20000000h\r
+\r
+MATH_DATA       ENDS\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Code segment\r
+;\r
+MATH_TEXT       SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MATH_TEXT, es:NOTHING, fs:NOTHING\r
+\r
+tdSetPerspective        PROC PASCAL FAR\r
+        ARG     Perspective:DWORD,      \\r
+                ScaleX:DWORD,           \\r
+                ScaleY:DWORD\r
+        USES    ds\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        mov     eax, [Perspective]\r
+        mov     [PerspectiveDistance], eax\r
+        mov     eax, [ScaleX]\r
+        mov     [XScale], eax\r
+        mov     eax, [ScaleY]\r
+        mov     [YScale], eax\r
+\r
+        ret\r
+tdSetPerspective        ENDP\r
+\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the rotation matrix.\r
+;\r
+; Input:\r
+;       RX      = X-axis rotation angle\r
+;       RY      = X-axis rotation angle\r
+;       RZ      = X-axis rotation angle\r
+; Output:\r
+;       none\r
+;\r
+tdSetRotation   PROC PASCAL FAR\r
+        ARG     RX:WORD,        \\r
+                RY:WORD,        \\r
+                RZ:WORD\r
+        USES    ds, si, di\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        mov     bx, [RZ]\r
+        mov     si, [RY]\r
+        mov     di, [RX]\r
+        shl     bx, 2\r
+        shl     si, 2\r
+        shl     di, 2\r
+\r
+        push    ebp                     ; We use EBP as a scratch register\r
+\r
+; Set X rotation\r
+        mov     eax, tblCos[bx]\r
+        imul    tblCos[si]\r
+        mov     [XRotation.X], edx\r
+\r
+        mov     eax, tblSin[bx]\r
+        imul    tblCos[si]\r
+        mov     [XRotation.Y], edx\r
+\r
+        mov     eax, tblSin[si]\r
+        sar     eax, 8                  ; Convert fixed 8:24 to fixed 16:16\r
+        mov     [XRotation.Z], eax\r
+\r
+; Set Y rotation\r
+        mov     eax, tblCos[bx]\r
+        imul    tblSin[si]              ; EDX:EAX = fixed 16:48\r
+        shrd    eax, edx, 24            ; EAX = fixed 8:24\r
+        imul    tblSin[di]              ; EDX:EAX = fixed 16:48\r
+        mov     ebp, eax\r
+        mov     ecx, edx\r
+        mov     eax, tblSin[bx]\r
+        imul    tblCos[di]\r
+        add     eax, ebp\r
+        adc     edx, ecx                ; EDX:EAX = fixed 16:48\r
+        neg     edx\r
+        mov     [YRotation.X], edx\r
+\r
+        mov     eax, tblSin[bx]\r
+        imul    tblSin[si]\r
+        shrd    eax, edx, 24\r
+        imul    tblSin[di]\r
+        mov     ebp, eax\r
+        mov     ecx, edx\r
+        mov     eax, tblCos[bx]\r
+        imul    tblCos[di]\r
+        sub     eax, ebp\r
+        sbb     edx, ecx\r
+        mov     [YRotation.Y], edx\r
+\r
+        mov     eax, tblCos[si]\r
+        imul    tblSin[di]\r
+        mov     [YRotation.Z], edx\r
+\r
+; Set Z rotation\r
+        mov     eax, tblCos[bx]\r
+        imul    tblSin[si]\r
+        shrd    eax, edx, 24\r
+        imul    tblCos[di]\r
+        mov     ebp, eax\r
+        mov     ecx, edx\r
+        mov     eax, tblSin[bx]\r
+        imul    tblSin[di]\r
+        sub     eax, ebp\r
+        sbb     edx, ecx\r
+        mov     [ZRotation.X], edx\r
+\r
+        mov     eax, tblSin[bx]\r
+        imul    tblSin[si]\r
+        shrd    eax, edx, 24\r
+        imul    tblCos[di]\r
+        mov     ebp, eax\r
+        mov     ecx, edx\r
+        mov     eax, tblCos[bx]\r
+        imul    tblSin[di]\r
+        add     eax, ebp\r
+        add     edx, ecx\r
+        neg     edx\r
+        mov     [ZRotation.Y], edx\r
+\r
+        mov     eax, tblCos[si]\r
+        imul    tblCos[di]\r
+        mov     [ZRotation.Z], edx\r
+\r
+        pop     ebp                     ; Restore EBP\r
+\r
+        ret\r
+tdSetRotation   ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the translation vector.\r
+;\r
+; Input:\r
+;       TV      = pointer to translation vector\r
+; Output:\r
+;       none\r
+;\r
+tdSetTranslation        PROC PASCAL FAR\r
+        ARG     TV:DWORD\r
+        USES    ds, es, di\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        les     di, [TV]\r
+        mov     eax, es:[di].X\r
+        mov     [Translation.X], eax\r
+        mov     eax, es:[di].Y\r
+        mov     [Translation.Y], eax\r
+        mov     eax, es:[di].Z\r
+        mov     [Translation.Z], eax\r
+\r
+        ret\r
+tdSetTranslation        ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Transforms an array of TPOINT.\r
+;\r
+; Input:\r
+;       Source  = pointer to source array of TPOINT\r
+;       Dest    = pointer to destination array of TPOINT\r
+;       Count   = number of entries to transform\r
+; Output:\r
+;       none\r
+;\r
+tdTransform     PROC PASCAL FAR\r
+        ARG     Source:DWORD,   \\r
+                Dest:DWORD,     \\r
+                Count:WORD\r
+        LOCAL   Adjust:DWORD\r
+        USES    ds, si, es, di, fs\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        lfs     si, [Source]\r
+        les     di, [Dest]\r
+\r
+        ALIGN   DWORD\r
+@@Loop:\r
+; Transform Z coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [ZRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [ZRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [ZRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        mov     ebx, eax\r
+        shrd    eax, edx, 16\r
+        add     eax, [Translation.Z]    ; EAX = new Z coord (fixed 16:16)\r
+        mov     es:[di].Z, eax\r
+; Get perspective factor\r
+        mov     ebx, [PerspectiveDistance]\r
+        sub     eax, ebx\r
+        neg     eax                     ; EAX = PD - Z\r
+        xor     edx, edx\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    ebx                     ; EAX = fixed 16:16 result\r
+        mov     [Adjust], eax\r
+\r
+; Transform X coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [XRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [XRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [XRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        add     eax, [Translation.X]\r
+        imul    [Adjust]\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].X, eax\r
+\r
+; Transform Y coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [YRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [YRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [YRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        add     eax, [Translation.Y]\r
+        imul    [Adjust]\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].Y, eax\r
+\r
+        add     si, SIZE TPOINT\r
+        add     di, SIZE TPOINT\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        ret\r
+tdTransform     ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Transforms an array of TPOINT into an array of TIMAGEPOINT.\r
+;\r
+; Input:\r
+;       Source  = pointer to source array of TPOINT\r
+;       Dest    = pointer to destination array of TIMAGEPOINT\r
+;       Count   = number of entries to transform\r
+;       DeltaX  = translation distance for the X coordinate\r
+;       DeltaY  = translation distance for the Y coordinate\r
+; Output:\r
+;       the maximum Z value\r
+;\r
+tdTransformToImage      PROC PASCAL FAR\r
+        ARG     Source:DWORD,   \\r
+                Dest:DWORD,     \\r
+                Count:WORD,     \\r
+                DeltaX:WORD,    \\r
+                DeltaY:WORD\r
+        LOCAL   Adjust:DWORD,   \\r
+                Max:DWORD\r
+        USES    ds, si, es, di, fs\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        lfs     si, [Source]\r
+        les     di, [Dest]\r
+        mov     [Max], 80000000h\r
+\r
+@@Loop:\r
+; Check max Z\r
+        mov     eax, fs:[si].Z\r
+        cmp     eax, [Max]\r
+        jle     @@1\r
+        mov     [Max], eax\r
+@@1:\r
+\r
+; Transform X coordinate\r
+        mov     ax, WORD PTR fs:[si].X[2]\r
+        add     ax, [DeltaX]\r
+        mov     es:[di].IX, ax\r
+\r
+; Transform Y coordinate\r
+        mov     ax, WORD PTR fs:[si].Y[2]\r
+        add     ax, [DeltaY]\r
+        mov     es:[di].IY, ax\r
+\r
+        add     si, SIZE TPOINT\r
+        add     di, SIZE TIMAGEPOINT\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        mov     eax, [Max]\r
+        shld    edx, eax, 16\r
+        ret\r
+tdTransformToImage      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the light source.\r
+;\r
+; Input:\r
+;       Light   = pointer to light vector\r
+; Output:\r
+;       none\r
+;\r
+tdSetLight      PROC PASCAL FAR\r
+        ARG     L:DWORD\r
+        USES    ds, es, di\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        les     di, [L]\r
+        mov     eax, es:[di].X\r
+        mov     [Light.X], eax\r
+        mov     eax, es:[di].Y\r
+        mov     [Light.Y], eax\r
+        mov     eax, es:[di].Z\r
+        mov     [Light.Z], eax\r
+\r
+        ret\r
+tdSetLight      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Computes light intensity for an array of surfaces.\r
+;\r
+; Input:\r
+;       Normals = pointer to an array of surface normals\r
+;       Lights  = pointer to an array of integer to be filled with\r
+;                 light intensity\r
+;       Count   = number of elements to transform\r
+; Output:\r
+;       none\r
+;\r
+tdTransformLight        PROC PASCAL FAR\r
+        ARG     Normals:DWORD,  \\r
+                Lights:DWORD,   \\r
+                Count:WORD\r
+        USES    ds, si, es, di, fs\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     fs, ax\r
+        ASSUME  fs:MATH_DATA\r
+\r
+        lds     si, [Normals]\r
+        les     di, [Lights]\r
+        ASSUME  ds:NOTHING\r
+\r
+; Intensity is given by the dot product between the Light vector and\r
+; the surface normal\r
+@@Loop:\r
+        mov     eax, ds:[si].Z\r
+        imul    [Light.Z]\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, ds:[si].Y\r
+        imul    [Light.Y]\r
+        add     ebx, eax\r
+        adc     ecx, edx\r
+        mov     eax, ds:[si].X\r
+        imul    [Light.X]\r
+        add     eax, ebx\r
+        adc     edx, ecx                ; EDX:EAX = fixed 32:32 intensity\r
+        add     dx, [AmbientLight]\r
+        test    dx, dx\r
+        jg      @@1\r
+        xor     dx, dx                  ; Return 0 for no light\r
+@@1:\r
+        mov     es:[di], dx\r
+        inc     di\r
+        inc     di\r
+        add     si, SIZE TPOINT\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        ASSUME  fs:NOTHING\r
+        ret\r
+tdTransformLight        ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the light value given the normal to a surface.\r
+;\r
+; Input:\r
+;       Normal  = pointer to TPOINT surface normal vector\r
+; Output:\r
+;       AX      = light intensity (>=0)\r
+; Notes:\r
+;       the normal is rotated according to the current setting.\r
+;\r
+tdGetSurfaceLight       PROC PASCAL FAR\r
+        ARG     Normal:DWORD\r
+        USES    ds, esi, es, di\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        les     di, [Normal]\r
+\r
+; Transform Z coordinate\r
+        mov     eax, es:[di].X\r
+        imul    [ZRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, es:[di].Y\r
+        imul    [ZRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, es:[di].Z\r
+        imul    [ZRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        imul    [Light.Z]\r
+        shrd    eax, edx, 16\r
+        mov     esi, eax\r
+\r
+; Transform X coordinate\r
+        mov     eax, es:[di].X\r
+        imul    [XRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, es:[di].Y\r
+        imul    [XRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, es:[di].Z\r
+        imul    [XRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        imul    [Light.X]\r
+        shrd    eax, edx, 16\r
+        add     esi, eax\r
+\r
+; Transform Y coordinate\r
+        mov     eax, es:[di].X\r
+        imul    [YRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, es:[di].Y\r
+        imul    [YRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, es:[di].Z\r
+        imul    [YRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        imul    [Light.X]\r
+        shrd    eax, edx, 16\r
+        add     eax, esi\r
+        shr     eax, 16\r
+\r
+; Add ambient light\r
+        add     ax, [AmbientLight]\r
+        test    ax, ax\r
+        jge     @@Exit\r
+        xor     ax, ax\r
+\r
+@@Exit:\r
+        ret\r
+tdGetSurfaceLight       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Rotates an array of TPOINT.\r
+;\r
+; Input:\r
+;       Source  = pointer to source array of TPOINT\r
+;       Dest    = pointer to destination array of TPOINT\r
+;       Count   = number of entries to transform\r
+; Output:\r
+;       none\r
+;\r
+tdRotate        PROC PASCAL FAR\r
+        ARG     Source:DWORD,   \\r
+                Dest:DWORD,     \\r
+                Count:WORD\r
+        USES    ds, si, es, di, fs\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        lfs     si, [Source]\r
+        les     di, [Dest]\r
+\r
+@@Loop:\r
+; Transform Z coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [ZRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [ZRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [ZRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].Z, eax\r
+\r
+; Transform X coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [XRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [XRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [XRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].X, eax\r
+\r
+; Transform Y coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [YRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [YRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [YRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].Y, eax\r
+\r
+        add     si, SIZE TPOINT\r
+        add     di, SIZE TPOINT\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        ret\r
+tdRotate        ENDP\r
+\r
+tdFixedMul      PROC PASCAL FAR\r
+        ARG     F1:DWORD,       \\r
+                F2:DWORD\r
+\r
+        mov     eax, [F1]\r
+        imul    [F2]\r
+        shr     eax, 16\r
+\r
+        ret\r
+tdFixedMul      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns in EAX the square root of EDX:EAX.\r
+;\r
+subSqrt PROC NEAR\r
+        push    esi\r
+        push    edi\r
+\r
+        add     eax, eax\r
+        adc     edx, 0\r
+        mov     eax, edx                ; Just discard the low bits\r
+\r
+        mov     esi, eax\r
+        xor     edi, edi\r
+        shld    edi, esi, 16\r
+        shl     esi, 16\r
+@@Loop:\r
+        mov     ebx, eax\r
+        mul     eax\r
+        add     eax, esi\r
+        adc     edx, edi\r
+        shrd    eax, edx, 1\r
+        shr     edx, 1\r
+        div     ebx\r
+        cmp     eax, ebx\r
+        jne     @@Loop\r
+\r
+; Adjust EAX\r
+        shl     eax, 8\r
+\r
+        pop     edi\r
+        pop     esi\r
+        ret\r
+subSqrt ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Finds the unitary normal to a given surface.\r
+;\r
+; Input:\r
+;       Dest            = pointer to TPOINT (vector) result\r
+;       P1, P2, P3      = pointer to TPOINT points on surface\r
+; Output:\r
+;       none\r
+; Notes:\r
+;       the normal is given by the cross-product between (P3-P1) and\r
+;       (P2-P1), so its orientation depends on the parameters order.\r
+;\r
+tdGetNormal     PROC PASCAL FAR\r
+        ARG     Dest:DWORD,     \\r
+                P1:DWORD,       \\r
+                P2:DWORD,       \\r
+                P3:DWORD\r
+        LOCAL   V1:TPOINT,      \\r
+                V2:TPOINT,      \\r
+                N:TPOINT\r
+        USES    ds, si, es, di\r
+\r
+; Get vector V1\r
+        lds     si, [P1]\r
+        les     di, [P3]\r
+        mov     eax, es:[di].X\r
+        sub     eax, ds:[si].X\r
+        mov     [V1.X], eax\r
+        mov     eax, es:[di].Y\r
+        sub     eax, ds:[si].Y\r
+        mov     [V1.Y], eax\r
+        mov     eax, es:[di].Z\r
+        sub     eax, ds:[si].Z\r
+        mov     [V1.Z], eax\r
+\r
+; Get vector V2\r
+        les     di, [P2]\r
+        mov     eax, es:[di].X\r
+        sub     eax, ds:[si].X\r
+        mov     [V2.X], eax\r
+        mov     eax, es:[di].Y\r
+        sub     eax, ds:[si].Y\r
+        mov     [V2.Y], eax\r
+        mov     eax, es:[di].Z\r
+        sub     eax, ds:[si].Z\r
+        mov     [V2.Z], eax\r
+\r
+; Get normal vector (V1 x V2)\r
+        mov     eax, [V1.Z]\r
+        imul    [V2.Y]\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, [V1.Y]\r
+        imul    [V2.Z]\r
+        sub     eax, ebx\r
+        sbb     edx, ecx\r
+        shrd    eax, edx, 16\r
+        mov     [N.X], eax\r
+\r
+        mov     eax, [V1.X]\r
+        imul    [V2.Z]\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, [V1.Z]\r
+        imul    [V2.X]\r
+        sub     eax, ebx\r
+        sbb     edx, ecx\r
+        shrd    eax, edx, 16\r
+        mov     [N.Y], eax\r
+\r
+        mov     eax, [V1.Y]\r
+        imul    [V2.X]\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, [V1.X]\r
+        imul    [V2.Y]\r
+        sub     eax, ebx\r
+        sbb     edx, ecx\r
+        shrd    eax, edx, 16\r
+        mov     [N.Z], eax\r
+\r
+; Get normal length\r
+        mov     eax, [N.X]\r
+        imul    eax\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, [N.Y]\r
+        imul    eax\r
+        add     ebx, eax\r
+        adc     ecx, edx\r
+        mov     eax, [N.Z]\r
+        imul    eax\r
+        add     eax, ebx\r
+        adc     edx, ecx                ; EDX:EAX = N.X*N.X + N.Y*N.Y + N.Z*N.Z\r
+        call    subSqrt                 ; EAX = normal length\r
+        mov     ebx, eax\r
+\r
+; Adjust vector and save it\r
+        les     di, [Dest]\r
+        mov     eax, [N.X]\r
+        cdq\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    ebx\r
+        mov     es:[di].X, eax\r
+        mov     eax, [N.Y]\r
+        cdq\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    ebx\r
+        mov     es:[di].Y, eax\r
+        mov     eax, [N.Z]\r
+        cdq\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    ebx\r
+        mov     es:[di].Z, eax\r
+\r
+        ret\r
+tdGetNormal     ENDP\r
+\r
+TPOLY   STRUC\r
+        Vtx     DW      4 DUP(?)\r
+TPOLY   ENDS\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Performs surface removal on an array of polygons.\r
+;\r
+; Input:\r
+;       Poly    = pointer to an array of TPOLY\r
+;       Vertex  = pointer to an array of TPOINT\r
+;       Dest    = pointer to an array of integer\r
+;       Count   = number of polygons to check\r
+;       Step    = size of TPOLY structure\r
+; Output:\r
+;       if the n-th polygon is invisible the n-th entry of the\r
+;       Dest array is set to -1, other entries are not modified\r
+;       (so it's possible to use the Light array for Dest, because\r
+;       the light intensity is always >= 0)\r
+;\r
+tdBackPlaneCull PROC PASCAL FAR\r
+        ARG     Step:WORD,      \\r
+                Poly:DWORD,     \\r
+                Vertex:DWORD,   \\r
+                Dest:DWORD,     \\r
+                Count:WORD\r
+        USES    ds, si, es, di, fs\r
+        ASSUME  ds:NOTHING\r
+\r
+        mov     ds, WORD PTR Vertex[2]\r
+        les     di, [Poly]\r
+        mov     fs, WORD PTR Dest[2]\r
+\r
+@@Loop:\r
+        mov     ax, es:[di].Vtx[2]      ; Index of 2nd vertex\r
+        shl     ax, 2\r
+        mov     bx, ax\r
+        shl     ax, 1\r
+        add     bx, ax                  ; BX = index*SIZE TPOINT\r
+        add     bx, WORD PTR [Vertex]   ; BX = offset of 2nd vertex\r
+        mov     ax, es:[di].Vtx[4]      ; Index of 3rd vertex\r
+        shl     ax, 2\r
+        mov     si, ax\r
+        shl     ax, 1\r
+        add     si, ax\r
+        add     si, WORD PTR [Vertex]   ; SI = offset of 3rd vertex\r
+        mov     ecx, ds:[si].X\r
+        sub     ecx, ds:[bx].X          ; ECX = V3.X-V2.X\r
+        mov     edx, ds:[si].Y\r
+        sub     edx, ds:[bx].Y          ; EDX = V3.Y-V2.Y\r
+        mov     ax, es:[di].Vtx[0]      ; Index of 1st vertex\r
+        shl     ax, 2\r
+        mov     si, ax\r
+        shl     ax, 1\r
+        add     si, ax\r
+        add     si, WORD PTR [Vertex]   ; SI = offset of 1st vertex\r
+        mov     eax, ds:[si].X\r
+        sub     eax, ds:[bx].X          ; EAX = V1.X-V2.X\r
+        mov     esi, ds:[si].Y\r
+        sub     esi, ds:[bx].Y          ; ESI = V1.Y-V2.Y\r
+        imul    edx\r
+        mov     ebx, eax\r
+        xchg    ecx, edx                ; ECX:EBX = (V1.X-V2.X)*(V3.Y-V2.Y)\r
+        mov     eax, esi\r
+        imul    edx                     ; EDX:EAX = (V1.Y-V2.Y)*(V3.X-V2.X)\r
+        sub     eax, ebx\r
+        sbb     edx, ecx\r
+        jl      @@Next                  ; Polygon is visible\r
+        mov     bx, WORD PTR [Dest]     ; FS:BX -> current Dest entry\r
+        mov     WORD PTR fs:[bx], -1    ; Remove polygon\r
+@@Next:\r
+        add     WORD PTR [Dest], 2      ; Next entry for dest\r
+        add     di, [Step]              ; Next polygon\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        ret\r
+tdBackPlaneCull ENDP\r
+\r
+MATH_TEXT       ENDS\r
+END\r
diff --git a/16/xw/modex/THREED.H b/16/xw/modex/THREED.H
new file mode 100755 (executable)
index 0000000..b993ef8
--- /dev/null
@@ -0,0 +1,32 @@
+typedef struct {\r
+    long    x, y, z;\r
+} TVECTOR;\r
+\r
+#define PVECTOR TVECTOR far *\r
+\r
+#define TPOINT  TVECTOR\r
+#define PPOINT  PVECTOR\r
+\r
+#define VPTR    void far *\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+long far pascal tdFixedMul( long, long );\r
+int  far pascal tdGetSurfaceLight( PPOINT );\r
+long far pascal tdTransformToImage( VPTR, VPTR, short, short, short );\r
+\r
+void far pascal tdBackPlaneCull( VPTR, VPTR, VPTR, short, short );\r
+void far pascal tdGetNormal( VPTR, PPOINT, PPOINT, PPOINT );\r
+void far pascal tdRotate( VPTR, VPTR, short );\r
+void far pascal tdSetLight( PVECTOR );\r
+void far pascal tdSetRotation( short, short, short );\r
+void far pascal tdSetTranslation( PVECTOR );\r
+void far pascal tdSetPerspective( long, long, long );\r
+void far pascal tdTransform( VPTR, VPTR, short );\r
+void far pascal tdTransformLight( VPTR, VPTR, short );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
diff --git a/16/xw/modex/THREED.PAS b/16/xw/modex/THREED.PAS
new file mode 100755 (executable)
index 0000000..8b712c9
--- /dev/null
@@ -0,0 +1,40 @@
+unit ThreeD;\r
+interface\r
+\r
+type\r
+  TVector       = record\r
+    X, Y, Z     : longint;\r
+  end;\r
+  TPoint        = TVector;\r
+\r
+function tdFixedMul( F1, F2: longint ): longint;\r
+function tdGetSurfaceLight( var Normal: TPoint ): integer;\r
+function tdTransformToImage( var Source, Dest; Count, DeltaX, DeltaY: integer ): longint;\r
+\r
+procedure tdBackPlaneCull( var Poly, Vertex, Dest; Count, Step: word );\r
+procedure tdGetNormal( var Dest, P1, P2, P3: TVector );\r
+procedure tdRotate( var Source, Dest; Count: word );\r
+procedure tdSetLight( var Light: TVector );\r
+procedure tdSetRotation( RX, RY, RZ: word );\r
+procedure tdSetTranslation( var TV: TVector );\r
+procedure tdSetPerspective( PD, XF, YF: longint );\r
+procedure tdTransform( var Source, Dest; Count: word );\r
+procedure tdTransformLight( var Source, Dest; Count: word );\r
+\r
+implementation\r
+\r
+function tdGetSurfaceLight;                             external;\r
+procedure tdSetRotation( RX, RY, RZ: word );            external;\r
+procedure tdGetNormal;                                  external;\r
+procedure tdSetTranslation( var TV: TVector );          external;\r
+procedure tdTransform( var Source, Dest; Count: word ); external;\r
+procedure tdRotate;                                     external;\r
+function  tdTransformToImage;                           external;\r
+procedure tdSetLight( var Light: TVector );             external;\r
+procedure tdSetPerspective;                             external;\r
+procedure tdTransformLight;                             external;\r
+function tdFixedMul( F1, F2: longint ): longint;        external;\r
+procedure tdBackPlaneCull;                              external;\r
+{$L THREED}\r
+\r
+end.\r
diff --git a/16/xw/modex/demo01.c b/16/xw/modex/demo01.c
new file mode 100755 (executable)
index 0000000..0c9f3b0
--- /dev/null
@@ -0,0 +1,140 @@
+/*\r
+ *             DEMO01 - Sprites, page flipping and palette rotation\r
+ *             Copyright (c) 1994 Alessandro Scotti\r
+ */\r
+#include ../../x/modex.h\r
+\r
+#DEFINE MAX_SPRITE 100\r
+\r
+typedef unsigned char byte;\r
+typedef unsigned short word;\r
+typedef unsigned long  dword;\r
+\r
+/* Sprite structure */\r
+typedef struct {\r
+       int X, Y;                                                                                               /* Sprite coordinates */\r
+       int DX,DY;                                                                                              /* Deltas for sprite movement */\r
+       int W, H;                                                                                               /* Sprite width and height */\r
+       byte Image[16,16];      /* Sprite image data */\r
+} TSprite;\r
+\r
+/* RGB color structure */\r
+typedef struct {\r
+       byte R, G, B;\r
+} TRgb;\r
+Tsprite S[MAX_SPRITE];  /* An array of sprites */\r
+TRgb Palette[ byte ];                                                   /* Palette */\r
+word Page;                                                                                                                             /* Page offset */\r
+word i;\r
+\r
+/* Initializes a sprite structure */\r
+void sxInit(TSprite *S)\r
+{\r
+//word i;\r
+\r
+S->X = rand( 320 );    /* Initialize position with random values */\r
+S->Y = rand( 240 );\r
+S->DX = rand( 7 )-3; /* Initialize speed with random values */\r
+S->DY = rand( 7 )-3;\r
+S->W = 16;                                              /* Size is fixed in this program */\r
+S->H = 16;\r
+/* The image is a square with a hole inside */\r
+FillChar( S->Image, SizeOf(S->Image), rand(15)+1 );\r
+       for(i=5; i<=12;i++)\r
+       {\r
+               FillChar( S->Image[ i, 5 ], 8, 0 );\r
+       }\r
+}\r
+\r
+/* Moves a sprite */\r
+void sxMove(TSprite *S)\r
+{\r
+//Inc( S.X, S.DX );             /* Get new position */\r
+//Inc( S.Y, S.DY );\r
+/* Check sprite position, change delta if needed */\r
+if( S->X > 320 ){\r
+       S->X = 320;\r
+S->DX = -S->DX;\r
+}\r
+if( S->X < -16 ){\r
+       S->X = -16;\r
+S->DX = -S->DX;\r
+}\r
+if( S->Y > 240 ){\r
+       S.Y = 240;\r
+       S->DY = -S->DY;\r
+}\r
+if( S->Y < -16 ){\r
+       S->Y = -16;\r
+       S->DY = -S->DY;\r
+}\r
+/* Draw the sprite, note the Page offset added to the */\r
+/* Y coordinate of the image */\r
+mxPutImage( S.Image, S->X, Page+S->Y, S->W, S->H, OP_TRANS );\r
+}\r
+\r
+void main()\r
+{\r
+       int i;\r
+       //TSprite S;\r
+       /* Initialize library */\r
+       mxInit();\r
+       \r
+       /* Enter graphics mode */\r
+       mxSetMode( MX_320x240 );\r
+       \r
+       /* Print initialization message */\r
+       mxSetTextColor( 15, OP_TRANS );\r
+       mxOutStr( 4, 4, 'Initializing...' );\r
+       \r
+       /* Initialize sprites */\r
+       for(i=1;i<=MAX_SPRITE;i++)\r
+               sxInit( &S[i] );\r
+       \r
+       /* Draw background */\r
+       for(i=1;i<=192;i++)\r
+       {\r
+               mxCircle( 160, 480+120, I, I+63 );\r
+               mxCircle( 161, 480+120, I, I+63 );\r
+       }\r
+       \r
+       /* Compute and set palette */\r
+       for(i=1;i<= 192;Palette[i+63])\r
+       {\r
+               short R = 0;\r
+               short G = 0;\r
+               short B = 0;\r
+               if( i < 64 )\r
+                       R = i >> 1+31;\r
+               else if( i < 128 )\r
+                       G = (i-64) >> 1+31;\r
+               else\r
+                       B = (i-128) >> 1+31;\r
+       }\r
+       mxSetPalette( @Palette[64], 64, 192 );\r
+       \r
+       /* Main loop */\r
+       short Page = 240;\r
+       while(!kbhit())\r
+       {\r
+               /* Set clip region to current page */\r
+               mxSetClipRegion( 0, Page, 320, 240 );\r
+               mxSetClip( TRUE );\r
+               /* Restore background */\r
+               mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+               /* Draw sprites */\r
+               for(i=1; i <= MAX_SPRITE; sxMove( S[i] ));\r
+               /* Print message */\r
+               mxOutStr( 4, Page+4, 'Some sprites moving...' );\r
+               /* Flip page */\r
+               mxStartLine( Page );\r
+               Page = 240-Page;\r
+               /* Animate palette */\r
+               mxSetPalette( @Palette[64], 64, 192 );\r
+               mxRotatePalette( @Palette[64], 192, 3 );\r
+       }\r
+       \r
+       mxSetMode( MX_TEXT );\r
+       mxTerm;\r
+       \r
+}\r
diff --git a/16/xw/mxbb.asm b/16/xw/mxbb.asm
new file mode 100755 (executable)
index 0000000..ed24a27
--- /dev/null
@@ -0,0 +1,278 @@
+;-----------------------------------------------------------\r
+;\r
+; MXBB.ASM - Bit block transfer\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+;WARN    PRO\r
+;NOWARN  RES\r
+INCLUDE modex.def\r
+\r
+PUBLIC  mxBitBlt\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   subHorizontalLineInfo   : NEAR\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Moves a block of video memory.\r
+;\r
+; Input:\r
+;       SX, SY  = source coordinates\r
+;       Width   = source width\r
+;       Height  = source height\r
+;       DX, DY  = destination coordinates\r
+; Output:\r
+;       none\r
+;\r
+; Note: overlapping regions are not allowed.\r
+;\r
+mxBitBlt        PROC    FAR\r
+        ARG     DestY:WORD,             \\r
+                DestX:WORD,             \\r
+                Height:WORD,            \\r
+                Width:WORD,             \\r
+                SY:WORD,                \\r
+                SX:WORD                 = ARG_SIZE\r
+        LOCAL   PlaneWidth:WORD:4,      \\r
+                SourceOffset:WORD,      \\r
+                DestOffset:WORD,        \\r
+                Count:BYTE,             \\r
+                ReadPlane:BYTE,         \\r
+                WritePlane:BYTE,        \\r
+                LeftMask:BYTE,          \\r
+                RightMask:BYTE          = AUTO_SIZE\r
+       .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+\r
+; Exit now if null width\r
+        cmp     [Width], 0\r
+        je      @@Exit\r
+\r
+; Calls the proper procedure to handle transfer\r
+        mov     ax, [SX]\r
+        and     al, 03h                 ; AL = source plane\r
+        mov     dx, [DestX]\r
+        and     dl, 03h                 ; DL = destination plane\r
+        mov     bx, OFFSET subPlaneBlt\r
+        cmp     al, dl                  ; Same source and destination plane?\r
+        jne     @@BitBlt                ; No, use slow procedure\r
+        mov     bx, OFFSET subMoveBlt\r
+@@BitBlt:\r
+        call    bx\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+\r
+;-----------------------------------------------------------\r
+; Uses write mode 1 for maximum speed. Only works if source\r
+; and destination are plane-aligned.\r
+;\r
+subMoveBlt      PROC    NEAR\r
+; Get horizontal line info and address of destination\r
+        mov     bx, [DestX]\r
+        mov     ax, [DestY]\r
+        mov     cx, [Width]\r
+        call    subHorizontalLineInfo\r
+        mov     [LeftMask], al\r
+        mov     [RightMask], ah\r
+        mov     [Width], cx\r
+\r
+; Setup segments\r
+        mov     ax, [mx_VideoSegment]\r
+        mov     ds, ax\r
+        mov     es, ax\r
+\r
+; Get address of source pixel\r
+        mov     ax, [SY]\r
+        mul     [mx_BytesPerLine]\r
+        mov     si, [SX]\r
+        .shr    si, 2\r
+        add     si, ax\r
+\r
+; Set write mode 1\r
+        mov     dx, GDC\r
+        mov     ax, 4105h\r
+        out     dx, ax\r
+        cld\r
+\r
+; Move left block\r
+@@L0:\r
+        mov     ah, [LeftMask]\r
+        or      ah, ah\r
+        jz      @@C0\r
+        mov     dx, TS\r
+        mov     al, 02h\r
+        out     dx, ax                  ; Set write plane mask\r
+        mov     ax, [mx_BytesPerLine]\r
+        dec     ax\r
+        mov     cx, [Height]\r
+        .push   si, di\r
+@@L1:\r
+        movsb\r
+        add     si, ax\r
+        add     di, ax\r
+        dec     cx\r
+        jnz     @@L1\r
+        .pop    si, di\r
+        inc     si\r
+        inc     di\r
+\r
+; Move center block\r
+@@C0:\r
+        mov     bx, [Width]\r
+        test    bx, bx\r
+        jz      @@R0\r
+        mov     dx, TS\r
+        mov     ax, 0F02h\r
+        out     dx, ax                  ; Enable all planes\r
+        mov     ax, [mx_BytesPerLine]\r
+        sub     ax, bx\r
+        mov     dx, [Height]\r
+        .push   si, di\r
+@@C1:\r
+        mov     cx, bx                  ; CX = image width\r
+        rep     movsb                   ; Cannot use "movsw" here!\r
+        add     si, ax                  ; Next scan line\r
+        add     di, ax                  ; Next scan line\r
+        dec     dx                      ; All lines processed?\r
+        jnz     @@C1                    ; No, continue\r
+        .pop    si, di\r
+        add     si, bx\r
+        add     di, bx\r
+\r
+; Move right block\r
+@@R0:\r
+        mov     ah, [RightMask]\r
+        or      ah, ah\r
+        jz      @@Done\r
+        mov     dx, TS\r
+        mov     al, 02h\r
+        out     dx, ax                  ; Set write plane mask\r
+        mov     ax, [mx_BytesPerLine]\r
+        dec     ax\r
+        mov     cx, [Height]\r
+@@R1:\r
+        movsb\r
+        add     si, ax\r
+        add     di, ax\r
+        dec     cx\r
+        jnz     @@R1\r
+\r
+@@Done:\r
+        mov     dx, GDC\r
+        mov     ax, 4005h\r
+        out     dx, ax                  ; Restore write mode 0\r
+\r
+@@Exit:\r
+        ret\r
+subMoveBlt      ENDP\r
+\r
+;-----------------------------------------------------------\r
+; Moves one plane at a time.\r
+;\r
+subPlaneBlt     PROC    NEAR\r
+; Compute extra bytes and width count for each plane\r
+        mov     cx, [Width]\r
+        mov     bx, cx\r
+        shr     bx, 1\r
+        shr     bx, 1                   ; Width for each plane\r
+        and     cl, 03h\r
+        mov     al, 00001000b\r
+        shr     al, cl\r
+        mov     si, 3 SHL 1\r
+@@PatchLoop:\r
+        mov     PlaneWidth[si], bx\r
+        shr     al, 1\r
+        adc     bx, 0\r
+        dec     si\r
+        dec     si\r
+        jge     @@PatchLoop\r
+\r
+; Get pixel addresses\r
+        mov     ax, [mx_VideoSegment]\r
+        mov     ds, ax\r
+        mov     es, ax\r
+        mov     ax, [SY]\r
+        mul     [mx_BytesPerLine]\r
+        mov     si, [SX]\r
+        shr     si, 1\r
+        shr     si, 1\r
+        add     si, ax                  ; DS:SI points to source\r
+        mov     [SourceOffset], si\r
+        mov     ax, [DestY]\r
+        mul     [mx_BytesPerLine]\r
+        mov     di, [DestX]\r
+        shr     di, 1\r
+        shr     di, 1\r
+        add     di, ax                  ; ES:DI points to destination\r
+        mov     [DestOffset], di\r
+\r
+; Adjust plane for output to VGA registers\r
+        mov     ax, [SX]\r
+        and     al, 03h\r
+        mov     [ReadPlane], al\r
+        mov     cx, [DestX]\r
+        and     cl, 03h\r
+        mov     al, 00010001b\r
+        shl     al, cl\r
+        mov     [WritePlane], al\r
+\r
+; Ready to move now\r
+        cld\r
+        mov     [Count], 4              ; Four planes\r
+        lea     bx, PlaneWidth          ; SS:[BX] = width in bytes for plane\r
+@@PlaneLoop:\r
+        cmp     WORD PTR ss:[bx], 0\r
+        je      @@Done\r
+        mov     ah, [WritePlane]\r
+        and     ah, 0Fh\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax                  ; Select write plane\r
+        mov     ah, [ReadPlane]\r
+        mov     al, 04h\r
+        mov     dx, GDC\r
+        out     dx, ax                  ; Select read plane\r
+        mov     dx, [Height]\r
+        mov     ax, [mx_BytesPerLine]\r
+        sub     ax, ss:[bx]             ; AX = extra bytes per line\r
+@@Loop:\r
+        mov     cx, ss:[bx]\r
+        shr     cx, 1\r
+        rep     movsw\r
+        rcl     cx, 1\r
+        rep     movsb\r
+        add     si, ax\r
+        add     di, ax\r
+        dec     dx\r
+        jnz     @@Loop                  ; Repeat for all lines\r
+        inc     bx\r
+        inc     bx                      ; Select width for next plane\r
+        inc     [ReadPlane]\r
+        and     [ReadPlane], 03h        ; Should be faster on 386 using\r
+        jnz     @@ReadPlaneOk           ; BTR and ADC...\r
+        inc     [SourceOffset]\r
+@@ReadPlaneOk:\r
+        rol     [WritePlane], 1\r
+        adc     [DestOffset], 0\r
+        mov     si, [SourceOffset]\r
+        mov     di, [DestOffset]\r
+        dec     [Count]\r
+        jnz     @@PlaneLoop             ; Repeat for all planes\r
+\r
+@@Done:\r
+        ret\r
+subPlaneBlt     ENDP\r
+\r
+mxBitBlt        ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxcc.asm b/16/xw/mxcc.asm
new file mode 100755 (executable)
index 0000000..4f78adb
--- /dev/null
@@ -0,0 +1,644 @@
+;-----------------------------------------------------------\r
+;\r
+; MXCC.ASM - Fast clip line function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  xsubClipLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+        ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_VideoSegment : WORD\r
+\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+\r
+tblGroups       LABEL WORD\r
+        DW      10,     tbl00\r
+        DW      10,     tbl10\r
+        DW      9,      tbl20\r
+        DW      -1,     0\r
+        DW      10,     tbl40\r
+        DW      10,     tbl50\r
+        DW      9,      tbl60\r
+        DW      -1,     0\r
+        DW      6,      tbl80\r
+        DW      6,      tbl90\r
+        DW      5,      tblA0\r
+        DW      -1,     0\r
+        DW      -1,     0\r
+        DW      -1,     0\r
+        DW      -1,     0\r
+        DW      -1,     0\r
+tbl00   DW cc00, cc01, cc02, ccFF, cc04, cc05, cc06, ccFF, cc08, cc09, cc0A\r
+tbl10   DW cc10, ccFF, cc12, ccFF, cc14, ccFF, cc16, ccFF, cc18, ccFF, cc1A\r
+tbl20   DW cc20, cc21, ccFF, ccFF, cc24, cc25, ccFF, ccFF, cc28, cc29\r
+tbl40   DW cc40, cc41, cc42, ccFF, ccFF, ccFF, ccFF, ccFF, cc48, cc49, cc4A\r
+tbl50   DW cc50, ccFF, cc52, ccFF, ccFF, ccFF, ccFF, ccFF, cc58, ccFF, cc5A\r
+tbl60   DW cc60, cc61, ccFF, ccFF, ccFF, ccFF, ccFF, ccFF, cc68, cc69\r
+tbl80   DW cc80, cc81, cc82, ccFF, cc84, cc85, cc86\r
+tbl90   DW cc90, ccFF, cc92, ccFF, cc94, ccFF, cc96\r
+tblA0   DW ccA0, ccA1, ccFF, ccFF, ccA4, ccA5\r
+\r
+ccTT:   clc\r
+        ret\r
+ccFF:   stc\r
+        ret\r
+\r
+; Group 00 -------------------------------------------------\r
+;\r
+cc00:\r
+        clc\r
+        ret\r
+cc01:\r
+        jmp     ClipQLeft\r
+cc02:\r
+        jmp     ClipQRight\r
+cc04:\r
+        jmp     ClipQTop\r
+cc05:\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY1]\r
+        jge     ccTT\r
+        jmp     ClipQTop\r
+cc06:\r
+        call    ClipQRight\r
+        cmp     si, [mx_ClipY1]\r
+        jge     ccTT\r
+        jmp     ClipQTop\r
+cc08:\r
+        jmp     ClipQBottom\r
+cc09:\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY2]\r
+        jle     ccTT\r
+        jmp     ClipQBottom\r
+cc0A:\r
+        call    ClipQRight\r
+        cmp     si, [mx_ClipY2]\r
+        jle     ccTT\r
+        jmp     ClipQBottom\r
+\r
+; Group 10 -------------------------------------------------\r
+;\r
+cc10FF:\r
+        stc\r
+        ret\r
+cc10TT:\r
+        clc\r
+        ret\r
+cc10:\r
+        jmp     ClipPLeft\r
+cc12:\r
+        call    ClipPLeft\r
+        jmp     ClipQRight\r
+cc14:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      cc10FF\r
+        jmp     ClipQTop\r
+cc16:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      cc10FF\r
+        call    ClipQTop\r
+        cmp     cx, [mx_ClipX2]\r
+        jle     cc10TT\r
+        jmp     ClipQRight\r
+cc18:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      cc10FF\r
+        jmp     ClipQBottom\r
+cc1A:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      cc10FF\r
+        call    ClipQBottom\r
+        cmp     cx, [mx_ClipX2]\r
+        jle     cc10TT\r
+        jmp     ClipQRight\r
+\r
+; Group 20 -------------------------------------------------\r
+;\r
+cc20TT:\r
+        clc\r
+        ret\r
+cc20FF:\r
+        stc\r
+        ret\r
+cc20:\r
+        jmp     ClipPRight\r
+cc21:\r
+        call    ClipPRight\r
+        jmp     ClipQLeft\r
+cc24:\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      cc20FF\r
+        jmp     ClipQTop\r
+cc25:\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      cc20FF\r
+        call    ClipQTop\r
+        cmp     cx, [mx_ClipX1]\r
+        jge     cc20TT\r
+        jmp     ClipQLeft\r
+cc28:\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      cc20FF\r
+        jmp     ClipQBottom\r
+cc29:\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      cc20FF\r
+        call    ClipQBottom\r
+        cmp     cx, [mx_ClipX1]\r
+        jge     cc20TT\r
+        jmp     ClipQLeft\r
+\r
+; Group 40 -------------------------------------------------\r
+;\r
+cc40TT:\r
+        clc\r
+        ret\r
+cc40FF:\r
+        stc\r
+        ret\r
+cc40:\r
+        jmp     ClipPTop\r
+cc41:\r
+        call    ClipPTop\r
+        cmp     di, [mx_ClipX1]\r
+        jl      cc40FF\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY1]\r
+        jge     cc40TT\r
+        jmp     ClipQTop\r
+cc42:\r
+        call    ClipPTop\r
+        cmp     di, [mx_ClipX2]\r
+        jg      cc40FF\r
+        jmp     ClipQRight\r
+cc48:\r
+        call    ClipPTop\r
+        jmp     ClipQBottom\r
+cc49:\r
+        call    ClipPTop\r
+        cmp     di, [mx_ClipX1]\r
+        jl      cc40FF\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY2]\r
+        jle     cc40TT\r
+        jmp     ClipQBottom\r
+cc4A:\r
+        call    ClipPTop\r
+        cmp     di, [mx_ClipX2]\r
+        jg      cc40FF\r
+        call    ClipQRight\r
+        cmp     si, [mx_ClipY2]\r
+        jle     cc40TT\r
+        jmp     ClipQBottom\r
+\r
+\r
+; Group 50 -------------------------------------------------\r
+;\r
+cc50TT:\r
+        clc\r
+        ret\r
+cc50FF:\r
+        stc\r
+        ret\r
+cc50:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY1]\r
+        jge     cc50TT\r
+        jmp     ClipPTop\r
+cc52:\r
+        call    ClipQRight\r
+        cmp     si, [mx_ClipY1]\r
+        jl      cc50FF\r
+        call    ClipPTop\r
+        cmp     di, [mx_ClipX1]\r
+        jge     cc50TT\r
+        jmp     ClipPLeft\r
+cc58:\r
+        call    ClipQBottom\r
+        cmp     cx, [mx_ClipX1]\r
+        jl      cc50FF\r
+        call    ClipPTop\r
+        cmp     di, [mx_ClipX1]\r
+        jge     cc50TT\r
+        jmp     ClipPLeft\r
+cc5A:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      cc50FF\r
+        call    ClipQRight\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      cc50FF\r
+        cmp     si, [mx_ClipY2]\r
+        jle     cc50TT\r
+        jmp     ClipQBottom\r
+\r
+; Group 60 -------------------------------------------------\r
+;\r
+cc60TT:\r
+        clc\r
+        ret\r
+cc60FF:\r
+        stc\r
+        ret\r
+cc60:\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY1]\r
+        jge     cc60TT\r
+        jmp     ClipPTop\r
+cc61:\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY2]\r
+        jl      cc60FF\r
+        call    ClipPTop\r
+        cmp     di, [mx_ClipX2]\r
+        jle     cc60TT\r
+        jmp     ClipPRight\r
+cc68:\r
+        call    ClipQBottom\r
+        cmp     cx, [mx_ClipX2]\r
+        jg      cc60FF\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY1]\r
+        jge     cc60TT\r
+        jmp     ClipPTop\r
+cc69:\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY1]\r
+        jl      cc60FF\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      cc60FF\r
+        cmp     si, [mx_ClipY2]\r
+        jle     cc69_1\r
+        call    ClipQBottom\r
+cc69_1:\r
+        cmp     bx, [mx_ClipY1]\r
+        jge     cc60TT\r
+        jmp     ClipPTop\r
+\r
+; Group 80 -------------------------------------------------\r
+;\r
+cc80TT:\r
+        clc\r
+        ret\r
+cc80FF:\r
+        stc\r
+        ret\r
+cc80:\r
+        jmp     ClipPBottom\r
+cc81:\r
+        call    ClipPBottom\r
+        cmp     di, [mx_ClipX1]\r
+        jl      cc80FF\r
+        jmp     ClipQLeft\r
+cc82:\r
+        call    ClipPBottom\r
+        cmp     di, [mx_ClipX2]\r
+        jg      cc80FF\r
+        jmp     ClipQRight\r
+cc84:\r
+        call    ClipPBottom\r
+        jmp     ClipQTop\r
+cc85:\r
+        call    ClipPBottom\r
+        cmp     di, [mx_ClipX1]\r
+        jl      cc80FF\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY1]\r
+        jge     cc80FF\r
+        jmp     ClipQTop\r
+cc86:\r
+        call    ClipPBottom\r
+        cmp     di, [mx_ClipX2]\r
+        jg      cc80FF\r
+        call    ClipQRight\r
+        cmp     si, [mx_ClipY1]\r
+        jge     cc80TT\r
+        jmp     ClipQTop\r
+\r
+; Group 90 -------------------------------------------------\r
+;\r
+cc90TT:\r
+        clc\r
+        ret\r
+cc90FF:\r
+        stc\r
+        ret\r
+cc90:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY2]\r
+        jle     cc90TT\r
+        jmp     ClipPBottom\r
+cc92:\r
+        call    ClipQRight\r
+        cmp     si, [mx_ClipY2]\r
+        jg      cc90FF\r
+        call    ClipPBottom\r
+        cmp     di, [mx_ClipX1]\r
+        jge     cc90TT\r
+        jmp     ClipPLeft\r
+cc94:\r
+        call    ClipQTop\r
+        cmp     cx, [mx_ClipX1]\r
+        jl      cc90FF\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY2]\r
+        jle     cc90TT\r
+        jmp     ClipPBottom\r
+cc96:\r
+        call    ClipPLeft\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      cc90FF\r
+        call    ClipQRight\r
+        cmp     si, [mx_ClipY2]\r
+        jg      cc90FF\r
+        cmp     bx, [mx_ClipY2]\r
+        jle     cc96_1\r
+        call    ClipPBottom\r
+cc96_1:\r
+        cmp     si, [mx_ClipY1]\r
+        jge     cc90TT\r
+        jmp     ClipQTop\r
+\r
+; Group A0 -------------------------------------------------\r
+;\r
+ccA0TT:\r
+        clc\r
+        ret\r
+ccA0FF:\r
+        stc\r
+        ret\r
+ccA0:\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY2]\r
+        jle     ccA0TT\r
+        jmp     ClipPBottom\r
+ccA1:\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY2]\r
+        jg      ccA0FF\r
+        call    ClipPBottom\r
+        cmp     di, [mx_ClipX2]\r
+        jle     ccA0TT\r
+        jmp     ClipPRight\r
+ccA4:\r
+        call    ClipQTop\r
+        cmp     cx, [mx_ClipX2]\r
+        jg      ccA0FF\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY2]\r
+        jle     ccA0TT\r
+        jmp     ClipPBottom\r
+ccA5:\r
+        call    ClipQLeft\r
+        cmp     si, [mx_ClipY2]\r
+        jg      ccA0FF\r
+        call    ClipPRight\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      ccA0FF\r
+        cmp     si, [mx_ClipY1]\r
+        jge     ccA5_1\r
+        call    ClipQTop\r
+ccA5_1:\r
+        cmp     bx, [mx_ClipY2]\r
+        jle     ccA0TT\r
+        jmp     ClipPBottom\r
+\r
+; Y1 = (Y2-Y1)*(mx_ClipX1-X1)/(X2-X1)+Y1 = (SI-BX)*(mx_ClipX1-DI)/(CX-DI)+BX\r
+; X1 = mx_ClipX1\r
+ClipPLeft:\r
+        mov     ax, si\r
+        sub     ax, bx\r
+        mov     dx, [mx_ClipX1]\r
+        sub     dx, di\r
+        imul    dx\r
+        mov     bp, cx\r
+        sub     bp, di\r
+        idiv    bp\r
+        add     bx, ax\r
+        mov     di, [mx_ClipX1]\r
+        clc\r
+        ret\r
+\r
+; Y1 = (Y2-Y1)*(mx_ClipX2-X1)/(X2-X1)+Y1 = (SI-BX)*(mx_ClipX2-DI)/(CX-DI)+BX\r
+; X1 = mx_ClipX2\r
+ClipPRight:\r
+        mov     ax, si\r
+        sub     ax, bx\r
+        mov     dx, [mx_ClipX2]\r
+        sub     dx, di\r
+        imul    dx\r
+        mov     bp, cx\r
+        sub     bp, di\r
+        idiv    bp\r
+        add     bx, ax\r
+        mov     di, [mx_ClipX2]\r
+        clc\r
+        ret\r
+\r
+; X1 = (X2-X1)*(mx_ClipY2-Y1)/(Y2-Y1)+X1 = (CX-DI)*(mx_ClipY2-BX)/(SI-BX)+DI\r
+; Y1 = mx_ClipY2\r
+ClipPBottom:\r
+        mov     ax, cx\r
+        sub     ax, di\r
+        mov     dx, [mx_ClipY2]\r
+        sub     dx, bx\r
+        imul    dx\r
+        mov     bp, si\r
+        sub     bp, bx\r
+        idiv    bp\r
+        add     di, ax\r
+        mov     bx, [mx_ClipY2]\r
+        clc\r
+        ret\r
+\r
+; X1 = (X2-X1)*(mx_ClipY1-Y1)/(Y2-Y1)+X1 = (CX-DI)*(mx_ClipY1-BX)/(SI-BX)+DI\r
+; Y1 = mx_ClipY1\r
+ClipPTop:\r
+        mov     ax, cx\r
+        sub     ax, di\r
+        mov     dx, [mx_ClipY1]\r
+        sub     dx, bx\r
+        imul    dx\r
+        mov     bp, si\r
+        sub     bp, bx\r
+        idiv    bp\r
+        add     di, ax\r
+        mov     bx, [mx_ClipY1]\r
+        clc\r
+        ret\r
+\r
+; Y2 = (Y1-Y2)*(mx_ClipX1-X2)/(X1-X2)+Y2 = (BX-SI)*(mx_ClipX1-CX)/(DI-CX)+SI\r
+; X2 = mx_ClipX1\r
+ClipQLeft:\r
+        mov     ax, bx\r
+        sub     ax, si\r
+        mov     dx, [mx_ClipX1]\r
+        sub     dx, cx\r
+        imul    dx\r
+        mov     bp, di\r
+        sub     bp, cx\r
+        idiv    bp\r
+        add     si, ax\r
+        mov     cx, [mx_ClipX1]\r
+        clc\r
+        ret\r
+\r
+; Y2 = (Y1-Y2)*(mx_ClipX2-X2)/(X1-X2)+Y2 = (BX-SI)*(mx_ClipX2-CX)/(DI-CX)+SI\r
+; X2 = mx_ClipX1\r
+ClipQRight:\r
+        mov     ax, bx\r
+        sub     ax, si\r
+        mov     dx, [mx_ClipX2]\r
+        sub     dx, cx\r
+        imul    dx\r
+        mov     bp, di\r
+        sub     bp, cx\r
+        idiv    bp\r
+        add     si, ax\r
+        mov     cx, [mx_ClipX2]\r
+        clc\r
+        ret\r
+\r
+; X2 = (X1-X2)*(mx_ClipY2-Y2)/(Y1-Y2)+X2 = (DI-CX)*(mx_ClipY2-SI)/(BX-SI)+CX\r
+; Y2 = mx_ClipY1\r
+ClipQBottom:\r
+        mov     ax, di\r
+        sub     ax, cx\r
+        mov     dx, [mx_ClipY2]\r
+        sub     dx, si\r
+        imul    dx\r
+        mov     bp, bx\r
+        sub     bp, si\r
+        idiv    bp\r
+        add     cx, ax\r
+        mov     si, [mx_ClipY2]\r
+        clc\r
+        ret\r
+\r
+; X2 = (X1-X2)*(mx_ClipY1-Y2)/(Y1-Y2)+X2 = (DI-CX)*(mx_ClipY1-SI)/(BX-SI)+CX\r
+; Y2 = mx_ClipY1\r
+ClipQTop:\r
+        mov     ax, di\r
+        sub     ax, cx\r
+        mov     dx, [mx_ClipY1]\r
+        sub     dx, si\r
+        imul    dx\r
+        mov     bp, bx\r
+        sub     bp, si\r
+        idiv    bp\r
+        add     cx, ax\r
+        mov     si, [mx_ClipY1]\r
+        clc\r
+        ret\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Checks the coordinates of a line against the active\r
+; clip region.\r
+; Uses the Sobkow-Pospisil-Yang (SPY) algorithm: this was\r
+; supposed to be twice as fast as Cohen-Sutherland, but my\r
+; tests show only a very small increase in speed and a noticeable\r
+; increase of the program size! Maybe this is caused by the\r
+; slow speed of VGA cards, so probably a better test should\r
+; be performed with lines drawn in RAM.\r
+;\r
+; Input:\r
+;       AX, BX  = X1, Y1\r
+;       CX, DX  = X2, Y2\r
+; Output:\r
+;       CF      = set if line is full clipped\r
+;       AX, BX  = clipped X1, Y1\r
+;       CX, DX  = clipped X2, Y2\r
+; Note:\r
+;       destroys SI, DI\r
+;\r
+xsubClipLine     PROC    NEAR\r
+        push    bp\r
+        xor     si, si                  ; SPY code\r
+\r
+        cmp     dx, [mx_ClipY2]\r
+        jle     @@1\r
+        or      si, 08h\r
+        jmp     @@2\r
+@@1:\r
+        cmp     dx, [mx_ClipY1]\r
+        jge     @@2\r
+        or      si, 04h\r
+@@2:\r
+\r
+        cmp     cx, [mx_ClipX2]\r
+        jle     @@3\r
+        or      si, 02h\r
+        jmp     @@4\r
+@@3:\r
+        cmp     cx, [mx_ClipX1]\r
+        jge     @@4\r
+        or      si, 01h\r
+@@4:\r
+\r
+        cmp     bx, [mx_ClipY2]\r
+        jle     @@5\r
+        or      si, 80h\r
+        jmp     @@6\r
+@@5:\r
+        cmp     bx, [mx_ClipY1]\r
+        jge     @@6\r
+        or      si, 40h\r
+@@6:\r
+\r
+        cmp     ax, [mx_ClipX2]\r
+        jle     @@7\r
+        or      si, 20h\r
+        jmp     @@8\r
+@@7:\r
+        cmp     ax, [mx_ClipX1]\r
+        jge     @@8\r
+        or      si, 10h\r
+@@8:\r
+\r
+        mov     di, si\r
+        and     di, 000Fh               ; Index of procedure\r
+        and     si, 00F0h\r
+        .shr    si, 2                   ; Index of group (times 4)\r
+        cmp     di, cs:tblGroups[si]    ; Is index within range?\r
+        jg      @@Exit                  ; No, line is full clipped\r
+        mov     si, cs:tblGroups[si+2]  ; Get offset of group table\r
+        shl     di, 1                   ; We must index word elements\r
+        add     si, di                  ; Make full offset\r
+        mov     di, ax                  ; Move X1 to DI and free AX\r
+        mov     si, cs:[si]             ; Get subroutine address\r
+        xchg    dx, si                  ; Move Y2 to SI and free DX\r
+        call    dx                      ; Call the proper subroutine\r
+        mov     ax, di                  ; Restore AX to X1\r
+        mov     dx, si                  ; Restore DX to Y2\r
+        pop     bp\r
+        ret\r
+\r
+@@Exit:\r
+        pop     bp\r
+        stc\r
+        ret\r
+xsubClipLine     ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxcg.asm b/16/xw/mxcg.asm
new file mode 100755 (executable)
index 0000000..42163d7
--- /dev/null
@@ -0,0 +1,69 @@
+;-----------------------------------------------------------\r
+;\r
+; MXCG.ASM - Color to gray conversion\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxColorToGray\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Converts RGB colors to gray shades.\r
+;\r
+; Input:\r
+;       CPal    = pointer to color palette\r
+;       GPal    = pointer to destination (gray) palette\r
+;       Count   = number of colors to convert\r
+; Output:\r
+;       none\r
+;\r
+; Note: CPal and GPal may point to the same buffer.\r
+;\r
+mxColorToGray   PROC    FAR\r
+        ARG     Count:WORD,     \\r
+                DPal:DWORD,     \\r
+                SPal:DWORD      = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si, es, di\r
+\r
+        mov     cx, [Count]\r
+        jcxz    @@Exit\r
+        lds     si, [SPal]\r
+        les     di, [DPal]\r
+        cld\r
+; We use the standard formula\r
+;       gray=(red*30 + green*59 + blue*11)/100\r
+; in the equivalent form\r
+;       gray=(red*77 + green*151 + blue*28)/256\r
+; which doesn't need the last divide.\r
+        mov     bx, 77 SHL 8 + 151\r
+@@Loop:\r
+        lodsb                           ; Red\r
+        mul     bh\r
+        mov     dx, ax\r
+        lodsb                           ; Green\r
+        mul     bl\r
+        add     dx, ax\r
+        lodsb                           ; Blue\r
+        mov     ah, 28\r
+        mul     ah\r
+        add     ax, dx\r
+        mov     al, ah\r
+        stosw                           ; Save new RGB\r
+        stosb\r
+        loop    @@Loop\r
+\r
+@@Exit:\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxColorToGray   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxcl.asm b/16/xw/mxcl.asm
new file mode 100755 (executable)
index 0000000..aaa0bac
--- /dev/null
@@ -0,0 +1,151 @@
+;-----------------------------------------------------------\r
+;\r
+; MXCL.ASM - Bresenham circle\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxCircle\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Draws a circle using the Bresenham algorithm.\r
+;\r
+; Input:\r
+;       XC, YC  = center coordinates\r
+;       Radius  = circle radius\r
+;       Color   = circle color\r
+; Output:\r
+;       none\r
+; Note:\r
+;       computes only points in the first octant, all other\r
+;       points are obtained by symmetry.\r
+;\r
+mxCircle        PROC FAR\r
+        ARG     Color:BYTE:2,           \\r
+                Radius:WORD,            \\r
+                YC:WORD,                \\r
+                XC:WORD                 = ARG_SIZE\r
+        LOCAL   Delta:WORD              = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, di\r
+\r
+        xor     si, si                  ; X\r
+        mov     di, [Radius]            ; Y\r
+        mov     ax, 3\r
+        sub     ax, di\r
+        sub     ax, di\r
+        mov     [Delta], ax             ; Delta = 3-R*2\r
+\r
+        mov     ds, [mx_VideoSegment]\r
+\r
+@@Loop:\r
+        cmp     si, di                  ;\r
+        jg      @@Done                  ; Exit when X > Y\r
+; Draw points\r
+        mov     ax, si\r
+        mov     bx, di\r
+        call    @@subPutPixel\r
+        mov     ax, si\r
+        neg     ax\r
+        mov     bx, di\r
+        call    @@subPutPixel\r
+        mov     ax, si\r
+        mov     bx, di\r
+        neg     bx\r
+        call    @@subPutPixel\r
+        mov     ax, si\r
+        neg     ax\r
+        mov     bx, di\r
+        neg     bx\r
+        call    @@subPutPixel\r
+        mov     ax, di\r
+        mov     bx, si\r
+        call    @@subPutPixel\r
+        mov     ax, di\r
+        neg     ax\r
+        mov     bx, si\r
+        call    @@subPutPixel\r
+        mov     ax, di\r
+        mov     bx, si\r
+        neg     bx\r
+        call    @@subPutPixel\r
+        mov     ax, di\r
+        neg     ax\r
+        mov     bx, si\r
+        neg     bx\r
+        call    @@subPutPixel\r
+; Moves coordinates to next point\r
+        mov     ax, [Delta]\r
+        test    ax, ax\r
+        jl      @@Next\r
+        mov     ax, di\r
+        .shl    ax, 2\r
+        sub     ax, 4\r
+        sub     [Delta], ax\r
+        dec     di\r
+@@Next:\r
+        mov     ax, si\r
+        .shl    ax, 2\r
+        add     ax, 6\r
+        add     [Delta], ax\r
+        inc     si\r
+        jmp     @@Loop\r
+\r
+@@Done:\r
+        xor     ax, ax\r
+        .pop    ds, si, di\r
+        .leave  ARG_SIZE\r
+\r
+;---------------------------------------\r
+; Put pixel function.\r
+; Input:\r
+;       BX      = X coordinate (relative to center)\r
+;       AX      = Y coordinate (relative to center)\r
+;       DS      = video segment\r
+@@subPutPixel:\r
+        add     bx, [XC]                ; Get absolute coordinates\r
+        add     ax, [YC]\r
+\r
+        cmp     bx, [mx_ClipX1]         ; Clip pixel\r
+        jl      @@subExit\r
+        cmp     bx, [mx_ClipX2]\r
+        jg      @@subExit\r
+        cmp     ax, [mx_ClipY1]\r
+        jl      @@subExit\r
+        cmp     ax, [mx_ClipY2]\r
+        jg      @@subExit\r
+\r
+        mul     [mx_BytesPerLine]       ; Get pixel offset\r
+        mov     cx, bx                  ; Save X coordinate\r
+        .shr    bx, 2\r
+        add     bx, ax                  ; DS:BX = pixel offset\r
+\r
+        and     cl, 3                   ; Set write plane\r
+        mov     ax, 0102h\r
+        shl     ah, cl\r
+        mov     dx, TS\r
+        out     dx, ax\r
+\r
+        mov     al, [Color]             ; Write pixel\r
+        mov     ds:[bx], al\r
+\r
+@@subExit:\r
+        retn\r
+mxCircle        ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxcr.asm b/16/xw/mxcr.asm
new file mode 100755 (executable)
index 0000000..ca1fa7b
--- /dev/null
@@ -0,0 +1,380 @@
+;-----------------------------------------------------------\r
+;\r
+; MXCR.ASM - Clip functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxSetSysClipRegion\r
+PUBLIC  mxGetClipRegion\r
+PUBLIC  mxSetClipRegion\r
+PUBLIC  mxSetClip\r
+PUBLIC  mxGetClip\r
+\r
+PUBLIC  subClipBox\r
+PUBLIC  subClipImage\r
+\r
+PUBLIC  mx_ClipX1\r
+PUBLIC  mx_ClipY1\r
+PUBLIC  mx_ClipX2\r
+PUBLIC  mx_ClipY2\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_CodeSegment  : WORD\r
+\r
+mx_ClipX1       DW      ?               ; Clip coordinates\r
+mx_ClipY1       DW      ?\r
+mx_ClipX2       DW      ?\r
+mx_ClipY2       DW      ?\r
+\r
+mx_SysClipX1    DW      ?               ; System clip coordinates\r
+mx_SysClipY1    DW      ?               ; (active when mx_ClipStatus is FALSE)\r
+mx_SysClipX2    DW      ?\r
+mx_SysClipY2    DW      ?\r
+\r
+mx_UserClipX1   DW      ?               ; User clip coordinates\r
+mx_UserClipY1   DW      ?               ; (active when mx_ClipStatus is TRUE)\r
+mx_UserClipX2   DW      ?\r
+mx_UserClipY2   DW      ?\r
+\r
+mx_ClipStatus   DB      ?\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Toggles clipping between user and system regions.\r
+;\r
+; Input:\r
+;       ClipStatus      = TRUE (FALSE) to enable (disable) clipping\r
+; Output:\r
+;       AX      = old clip status\r
+;\r
+mxSetClip       PROC    FAR\r
+        ARG     ClipStatus:BYTE:2       = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, [mx_UserClipX1]\r
+        mov     bx, [mx_UserClipY1]\r
+        mov     cx, [mx_UserClipX2]\r
+        mov     dx, [mx_UserClipY2]\r
+        cmp     [ClipStatus], TRUE\r
+        je      @@Done\r
+        mov     ax, [mx_SysClipX1]\r
+        mov     bx, [mx_SysClipY1]\r
+        mov     cx, [mx_SysClipX2]\r
+        mov     dx, [mx_SysClipY2]\r
+@@Done:\r
+        mov     [mx_ClipX1], ax\r
+        mov     [mx_ClipY1], bx\r
+        mov     [mx_ClipX2], cx\r
+        mov     [mx_ClipY2], dx\r
+\r
+        mov     al, [ClipStatus]\r
+        xchg    al, [mx_ClipStatus]\r
+        xor     ah, ah\r
+\r
+        .pop    ds\r
+        .leave  ARG_SIZE\r
+mxSetClip       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current clipping status.\r
+;\r
+; Input:\r
+;       none\r
+; Output:\r
+;       TRUE (FALSE) if clipping enabled (disabled)\r
+;\r
+mxGetClip       PROC    FAR\r
+        ASSUME  ds:NOTHING\r
+        mov     al, [mx_ClipStatus]\r
+        xor     ah, ah\r
+        ret\r
+mxGetClip       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the system clip region and disables user clipping.\r
+;\r
+; Input:\r
+;       Width   = width in pixels of clip region\r
+;       Height  = height in pixels of clip region\r
+; Output:\r
+;       old clip status.\r
+;\r
+mxSetSysClipRegion      PROC    FAR\r
+        ARG     Height:WORD,            \\r
+                Width:WORD              = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        xor     ax, ax                  ; Sys clip region always starts at (0,0)\r
+        mov     [mx_SysClipX1], ax\r
+        mov     [mx_SysClipY1], ax\r
+        mov     ax, [Width]\r
+        dec     ax\r
+        mov     [mx_SysClipX2], ax\r
+        mov     ax, [Height]\r
+        dec     ax\r
+        mov     [mx_SysClipY2], ax\r
+\r
+    IF USE286 EQ TRUE\r
+        push    FALSE\r
+    ELSE\r
+        mov     ax, FALSE\r
+        push    ax\r
+    ENDIF\r
+        call    mxSetClip\r
+\r
+        .pop    ds\r
+        .leave  ARG_SIZE\r
+mxSetSysClipRegion      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the clip region.\r
+;\r
+; Input:\r
+;       X, Y    = coordinates of top left corner of clip region\r
+;       Width   = width in pixels of clip region\r
+;       Height  = height in pixels of clip region\r
+; Output:\r
+;       none (no checking on parameters)\r
+;\r
+mxSetClipRegion PROC    FAR\r
+        ARG     Height:WORD,            \\r
+                Width:WORD,             \\r
+                Y:WORD,                 \\r
+                X:WORD                  = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, [X]\r
+        mov     [mx_UserClipX1], ax\r
+        mov     ax, [Y]\r
+        mov     [mx_UserClipY1], ax\r
+        mov     ax, [Width]\r
+        add     ax, [X]\r
+        dec     ax\r
+        mov     [mx_UserClipX2], ax\r
+        mov     ax, [Height]\r
+        add     ax, [Y]\r
+        dec     ax\r
+        mov     [mx_UserClipY2], ax\r
+\r
+        mov     al, [mx_ClipStatus]\r
+        cmp     al, TRUE\r
+        jne     @@Exit\r
+        push    ax\r
+        call    mxSetClip\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds\r
+        .leave  ARG_SIZE\r
+mxSetClipRegion ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current user clip region.\r
+;\r
+; Input:\r
+;       X, Y    = pointers to integer coordinates of top left corner\r
+;       Width   = pointer to word width of clip region\r
+;       Height  = pointer to word height of clip region\r
+; Output:\r
+;       AX      = current clip status\r
+;\r
+mxGetClipRegion PROC    FAR\r
+        ARG     Height:DWORD,           \\r
+                Width:DWORD,            \\r
+                Y:DWORD,                \\r
+                X:DWORD                 = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   es, di\r
+\r
+        mov     ax, [mx_UserClipX1]\r
+        les     di, [X]\r
+        mov     es:[di], ax\r
+        mov     ax, [mx_UserClipY1]\r
+        les     di, [Y]\r
+        mov     es:[di], ax\r
+\r
+        mov     ax, [mx_UserClipX2]\r
+        sub     ax, [mx_UserClipX1]\r
+        inc     ax\r
+        les     di, [Width]\r
+        mov     es:[di], ax\r
+        mov     ax, [mx_UserClipY2]\r
+        sub     ax, [mx_UserClipY1]\r
+        inc     ax\r
+        les     di, [Height]\r
+        mov     es:[di], ax\r
+\r
+        mov     al, [mx_ClipStatus]\r
+        xor     ah, ah\r
+        .pop    es, di\r
+        .leave  ARG_SIZE\r
+mxGetClipRegion ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Internal use: checks the coordinates of a rectangle against\r
+; the active clip region.\r
+; This function assumes that a "raw" image has to be clipped,\r
+; so it returns in SI the number of "raw" bytes to skip if\r
+; X, Y were clipped.\r
+;\r
+; Input:\r
+;       BX, AX  = X, Y coordinates of rectangle (signed)\r
+;       CX      = box width\r
+;       DX      = box height\r
+; Output:\r
+;       CF      = set if rectangle is full clipped\r
+;       BX, AX  = new X, Y coordinates of rectangle\r
+;       CX, DX  = clipped width and height\r
+;       SI      = number of bytes to skip before copying a buffer\r
+;       DI destroyed\r
+;\r
+subClipImage    PROC    NEAR\r
+        ASSUME  ds:NOTHING\r
+        xor     si, si\r
+\r
+; Check clip height\r
+        mov     di, [mx_ClipY1]\r
+        cmp     ax, di\r
+        jge     @@CheckBottom\r
+        sub     di, ax                  ; Number of lines to clip\r
+        sub     dx, di                  ; New box height\r
+        jle     @@Exit\r
+        mov     ax, di\r
+        mov     di, dx                  ; Save box height into DI\r
+        mul     cx                      ; DX:AX = number of bytes to skip\r
+        mov     si, ax\r
+        mov     dx, di                  ; Restore box height\r
+        mov     ax, [mx_ClipY1]\r
+@@CheckBottom:\r
+        mov     di, [mx_ClipY2]\r
+        cmp     ax, di\r
+        jg      @@Exit\r
+        inc     di\r
+        sub     di, dx\r
+        sub     di, ax\r
+        jge     @@DoneHeight            ; None, continue\r
+        add     dx, di                  ; Clip lines\r
+@@DoneHeight:\r
+\r
+; Check clip width\r
+@@CheckLeft:\r
+        mov     di, [mx_ClipX1]\r
+        cmp     bx, di\r
+        jge     @@CheckRight\r
+        sub     di, bx                  ; Number of columns to clip left\r
+        sub     cx, di\r
+        jle     @@Exit\r
+        add     si, di                  ; Update skip count\r
+        mov     bx, [mx_ClipX1]\r
+@@CheckRight:\r
+        mov     di, [mx_ClipX2]\r
+        cmp     bx, di\r
+        jg      @@Exit\r
+        inc     di\r
+        sub     di, bx\r
+        sub     di, cx\r
+        jge     @@DoneWidth             ; None, exit\r
+        add     cx, di                  ; New box width\r
+@@DoneWidth:\r
+\r
+; Set return flag and exit\r
+@@Done:\r
+        clc\r
+        ret\r
+@@Exit:\r
+        stc\r
+        ret\r
+subClipImage    ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Internal use: checks the coordinates of a rectangle against\r
+; the active clip region.\r
+;\r
+; Input:\r
+;       BX, AX  = X, Y coordinates of rectangle (signed)\r
+;       CX      = box width\r
+;       DX      = box height\r
+; Output:\r
+;       CF      = set if rectangle is full clipped\r
+;       BX, AX  = new X, Y coordinates of rectangle\r
+;       CX, DX  = clipped width and height\r
+;       DI destroyed\r
+;\r
+subClipBox      PROC    NEAR\r
+        ASSUME  ds:NOTHING\r
+\r
+; Check clip height\r
+        mov     di, [mx_ClipY1]\r
+        cmp     ax, di\r
+        jge     @@CheckBottom\r
+        sub     di, ax                  ; Number of lines to clip\r
+        sub     dx, di                  ; New box height\r
+        jle     @@Exit\r
+        mov     ax, [mx_ClipY1]\r
+@@CheckBottom:\r
+        mov     di, [mx_ClipY2]\r
+        cmp     ax, di\r
+        jg      @@Exit\r
+        inc     di\r
+        sub     di, dx\r
+        sub     di, ax                  ; Clipped some point?\r
+        jge     @@DoneHeight            ; No, continue\r
+        add     dx, di                  ; Clip lines (DI is negative)\r
+@@DoneHeight:\r
+\r
+; Check clip width\r
+@@CheckLeft:\r
+        mov     di, [mx_ClipX1]\r
+        cmp     bx, di\r
+        jge     @@CheckRight\r
+        sub     di, bx                  ; Number of columns to clip left\r
+        sub     cx, di\r
+        jle     @@Exit\r
+        mov     bx, [mx_ClipX1]\r
+@@CheckRight:\r
+        mov     di, [mx_ClipX2]\r
+        cmp     bx, di\r
+        jg      @@Exit\r
+        inc     di\r
+        sub     di, bx\r
+        sub     di, cx                  ; Clipped some point?\r
+        jge     @@DoneWidth             ; No, exit\r
+        add     cx, di                  ; New box width (DI is negative)\r
+@@DoneWidth:\r
+\r
+; Set return flag and exit\r
+@@Done:\r
+        clc\r
+        ret\r
+@@Exit:\r
+        stc\r
+        ret\r
+subClipBox      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxel.asm b/16/xw/mxel.asm
new file mode 100755 (executable)
index 0000000..2c9dda2
--- /dev/null
@@ -0,0 +1,167 @@
+;-----------------------------------------------------------\r
+;\r
+; MXEL.ASM - Mid-point ellipse\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxEllipse\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Draws an ellipse using the mid-point algorithm.\r
+;\r
+; Input:\r
+;       XC, YC  = center coordinates\r
+;       A       = horizontal radius\r
+;       B       = vertical radius\r
+;       Color   = ellipse color\r
+; Output:\r
+;       none\r
+; Note:\r
+;       computes only points in the first quadrant, all other\r
+;       points are obtained by symmetry.\r
+;\r
+mxEllipse       PROC FAR\r
+        ARG     Color:BYTE:2,   \\r
+                B:WORD,         \\r
+                A:WORD,         \\r
+                YC:WORD,        \\r
+                XC:WORD         = ARG_SIZE\r
+        LOCAL   A2:DWORD,       \\r
+                B2:DWORD,       \\r
+                CC:DWORD,       \\r
+                DD:DWORD,       \\r
+                X:DWORD,        \\r
+                Y:DWORD         = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, di\r
+\r
+        .chk386 mxEllipse, @@Exit\r
+\r
+; Initialize variables\r
+        xor     eax, eax\r
+        mov     [X], ax         ; X = 0\r
+        mov     ax, [A]\r
+        mul     eax             ; EAX = A*A\r
+        mov     [DD], eax       ; DD = A*A\r
+        shl     eax, 1\r
+        mov     [CC], eax       ; CC = 2*A*A\r
+        shl     eax, 1\r
+        mov     [A2], eax       ; A2 = 4*A*A\r
+        movzx   edx, [B]\r
+        mov     [Y], edx\r
+        mul     edx             ; EAX = 4*A*A*B\r
+        sub     [DD], eax       ; DD = A*A - 4*A*A*B\r
+        movzx   eax, [B]\r
+        mul     eax             ; EAX = B*B\r
+        shl     eax, 2          ; EAX = 4*B*B\r
+        mov     [B2], eax       ; B2 = 4*B*B\r
+        add     [CC], eax       ; CC = 2*A*A + 4*B*B\r
+        add     [D1], eax       ; DD = A*A - 4*A*A*B + 4*B*B\r
+\r
+; Draw initial points\r
+        call    subPlot4\r
+\r
+; First loop\r
+@@Loop1:\r
+        mov     eax, [X]        ; Check slope\r
+        mul     [B2]\r
+        mov     ecx, eax\r
+        mov     eax, [Y]\r
+        mul     [A2]\r
+        sub     eax, ecx\r
+        sub     eax, [CC]       ; EAX = Y*A2 - X*B2 - CC\r
+        jle     @@Done1         ; Crossed critical point, jump to next loop\r
+\r
+        mov     ecx, [DD]       ; Get error\r
+        test    ecx, ecx        ; Positive?\r
+        jl      @@Draw1         ; No, use default step\r
+\r
+        mov     eax, 1\r
+        sub     eax, [Y]\r
+        mul     [A2]\r
+        shl     eax, 1\r
+        add     ecx, eax        ; Bump error\r
+        dec     WORD PTR [Y]    ; Decrement Y coordinate\r
+\r
+@@Draw1:\r
+        mov     eax, [X]\r
+        shl     eax, 1\r
+        add     eax, 3\r
+        mul     [B2]\r
+        add     ecx, eax        ; Bump error\r
+        mov     [DD], ecx       ; Save error\r
+        inc     WORD PTR [X]    ; Increment X coordinate\r
+\r
+        call    subPlot4        ; Draw points\r
+        jmp     @@Loop1\r
+@@Done1:\r
+\r
+; Initialize variables\r
+        shr     [B2], 2\r
+        mov     eax, [X]\r
+        mul     eax\r
+        add     [X]\r
+        shl     eax, 2\r
+        inc     eax\r
+        mul     [B2]\r
+        mov     [DD], eax\r
+        mov     eax, [Y]\r
+        mul     eax\r
+        add     [Y]\r
+        dec     eax\r
+        add     [Y]\r
+        sub     eax, [B2]\r
+        add     [DD], eax\r
+        shl     [B2], 3\r
+        inc     WORD PTR [X]\r
+\r
+; Second loop\r
+@@Loop2:\r
+        cmp     WORD PTR [Y], 0\r
+        ja      @@Done2\r
+\r
+        mov     ecx, [DD]\r
+        test    ecx, ecx\r
+        jge     @@Draw2\r
+\r
+        mov     eax, [X]\r
+        inc     eax\r
+        mul     [B2]\r
+        add     ecx, eax\r
+        inc     WORD PTR [X]\r
+\r
+@@Draw2:\r
+        mov     eax, [Y]\r
+        shl     eax, 1\r
+        sub     eax, 3\r
+        neg     eax\r
+        imul    [A2]\r
+        add     ecx, eax\r
+        dec     WORD PTR [Y]\r
+\r
+        call    subPlot4\r
+        jmp     @@Loop2\r
+@@Done2:\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .leave  ARG_SIZE\r
+mxEllipse       ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxfb.asm b/16/xw/mxfb.asm
new file mode 100755 (executable)
index 0000000..41ea5de
--- /dev/null
@@ -0,0 +1,194 @@
+;-----------------------------------------------------------\r
+;\r
+; MXFB.ASM - Fill box function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxFillBox\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine         : WORD\r
+EXTRN   mx_VideoSegment         : WORD\r
+EXTRN   subClipBox              : NEAR\r
+EXTRN   subHorizontalLineInfo   : NEAR\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Raster op functions. Raster op is limited to OP_MOVE,\r
+; OP_AND, OP_OR and OP_XOR. The VGA hardware is used to\r
+; perform the selected logical functions on up to four\r
+; pixel at a time.\r
+;\r
+subRepFill      PROC    NEAR\r
+        mov     ah, al\r
+        shr     cx, 1\r
+        rep     stosw\r
+        rcl     cx, 1\r
+        rep     stosb\r
+        ret\r
+subRepFill      ENDP\r
+;\r
+subFill         PROC    NEAR\r
+@@Loop:\r
+        mov     ds:[bx], al\r
+        add     bx, dx\r
+        loop    @@Loop\r
+        ret\r
+subFill         ENDP\r
+;\r
+subRepMove      PROC    NEAR\r
+        mov     si, di\r
+@@Loop:\r
+        mov     ah, ds:[si]             ; Dummy read to latch the data\r
+        mov     ds:[si], al\r
+        inc     si\r
+        loop    @@Loop\r
+        ret\r
+subRepMove      ENDP\r
+;\r
+subMove         PROC    NEAR\r
+@@Loop:\r
+        mov     ah, ds:[bx]             ; Dummy read to latch the data\r
+        mov     ds:[bx], al\r
+        add     bx, dx\r
+        loop    @@Loop\r
+        ret\r
+subMove         ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a rectangle with a specified color.\r
+;\r
+; Input:\r
+;       X, Y            = X, Y coordinates of rectangle\r
+;       Width           = width of rectangle\r
+;       Height          = height of rectangle\r
+;       Color           = fill color\r
+;       Op              = raster operator\r
+; Output:\r
+;       none\r
+;\r
+; Note: raster op is limited to OP_MOVE, OP_AND, OP_OR and OP_XOR.\r
+;\r
+mxFillBox       PROC    FAR\r
+        ARG     Op:WORD,                \\r
+                Color:BYTE:2,           \\r
+                Height:WORD,            \\r
+                Width:WORD,             \\r
+                Y:WORD,                 \\r
+                X:WORD                  = ARG_SIZE\r
+        LOCAL   LeftMask:BYTE,          \\r
+                RightMask:BYTE,         \\r
+                FillFunction:WORD,      \\r
+                RepFillFunction:WORD    = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+        ASSUME  ds:NOTHING\r
+\r
+; Clip rectangle\r
+        mov     bx, [X]\r
+        mov     ax, [Y]\r
+        mov     cx, [Width]\r
+        mov     dx, [Height]\r
+        call    subClipBox\r
+        jc      @@Exit                  ; Full clipped\r
+\r
+        mov     [Height], dx            ; Save clipped height\r
+        call    subHorizontalLineInfo   ; Get additional info, init DI\r
+        mov     [Width], cx\r
+        mov     [LeftMask], al\r
+        mov     [RightMask], ah\r
+\r
+; Initialize segments\r
+        mov     ax, [mx_VideoSegment]\r
+        mov     es, ax                  ; ES:DI points to pixel\r
+        mov     ds, ax\r
+        cld                             ; Clear direction flag\r
+\r
+; Select fill functions\r
+        mov     [FillFunction], OFFSET subFill\r
+        mov     [RepFillFunction], OFFSET subRepFill\r
+        mov     ax, [Op]                ; Get raster op\r
+        cmp     al, OP_XOR\r
+        ja      @@1                     ; Assume it's a fill\r
+        cmp     al, OP_MOVE\r
+        je      @@1\r
+        .shl    al, 3\r
+        mov     ah, al\r
+        mov     al, 03h\r
+        mov     dx, GDC\r
+        out     dx, ax                  ; Set GDC logical function\r
+        mov     [FillFunction], OFFSET subMove\r
+        mov     [RepFillFunction], OFFSET subRepMove\r
+@@1:\r
+\r
+; Fill left block\r
+@@L0:\r
+        mov     ah, [LeftMask]\r
+        or      ah, ah\r
+        jz      @@C0                    ; Nothing to do, go to center block\r
+        mov     dx, TS\r
+        mov     al, 02h\r
+        out     dx, ax                  ; Set write plane mask\r
+        mov     dx, [mx_BytesPerLine]\r
+        mov     cx, [Height]\r
+        mov     bx, di\r
+        mov     al, [Color]\r
+        call    [FillFunction]          ; Fill this column\r
+        inc     di                      ; Update starting video offset\r
+\r
+; Fill center block\r
+@@C0:\r
+        mov     cx, [Width]\r
+        jcxz    @@R0                    ; Nothing to do, go to right block\r
+        mov     dx, TS\r
+        mov     ax, 0F02h\r
+        out     dx, ax                  ; Write to all planes\r
+        mov     al, [Color]\r
+        mov     bx, di\r
+        mov     dx, [Height]\r
+        push    di                      ; Save pixel address\r
+@@C1:\r
+        mov     di, bx                  ; Update video offset\r
+        call    [RepFillFunction]       ; Fill current scan line\r
+        mov     cx, [Width]             ; Restore byte count\r
+        add     bx, [mx_BytesPerLine]   ; Bump to next scan line\r
+        dec     dx                      ; Done all lines?\r
+        jnz     @@C1                    ; No, continue\r
+        pop     di                      ; Restore pixel address\r
+        add     di, [Width]             ; Go to right block\r
+\r
+; Fill right block\r
+@@R0:\r
+        mov     ah, [RightMask]\r
+        or      ah, ah\r
+        jz      @@Done                  ; Nothing to do, exit\r
+        mov     dx, TS\r
+        mov     al, 02h\r
+        out     dx, ax                  ; Set write plane mask\r
+        mov     dx, [mx_BytesPerLine]\r
+        mov     cx, [Height]\r
+        mov     bx, di\r
+        mov     al, [Color]\r
+        call    [FillFunction]          ; Fill this column\r
+\r
+; Restore VGA registers\r
+@@Done:\r
+        mov     dx, GDC\r
+        mov     ax, 0003h\r
+        out     dx, ax                  ; Set logical function to "move"\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxFillBox       ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxfp.asm b/16/xw/mxfp.asm
new file mode 100755 (executable)
index 0000000..8eea25b
--- /dev/null
@@ -0,0 +1,326 @@
+;-----------------------------------------------------------\r
+;\r
+; MXFP.ASM - Fade palette function\r
+; Copyright (c) 1992-1994 ARTIS s.r.l.\r
+; Author: Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxFadePalette\r
+\r
+MAXCOLOR        EQU     256\r
+FADE_IN         EQU     0\r
+FADE_OUT        EQU     1\r
+\r
+; The actual speed of fading depends on the number of passes (FADE_SPEED) and\r
+; the delay between two consecutive passes (FADE_DELAY). Below are the\r
+; default values, used when no parameters are specified.\r
+;\r
+FADE_DELAY      EQU     1               ; Vert. retraces between video updates\r
+FADE_SPEED      EQU     48              ; Speed of effect (max 127)\r
+\r
+; Bit field record for fade commands\r
+;\r
+FADE_COMMAND    RECORD  fpDELAY:8,fpSPEED:7,fpDIRECTION:1\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+DB      'Copyright (c) 1992-1994 ARTIS s.r.l. All rights reserved.'\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fades a VGA palette.\r
+;\r
+; Input:\r
+;       Buffer          = pointer to source/destination palette\r
+;       Command         = fading direction and optional parameters\r
+;       Start           = index of first color to fade\r
+;       Count           = number of color to fade\r
+;       Red             = destination red\r
+;       Green           = destination green\r
+;       Blue            = destination blue\r
+; Output:\r
+;       none\r
+; Notes:\r
+;    -  about 1.5 Kbytes of stack space are needed for internal buffers;\r
+;    -  the Command argument usually is 0 to fade in and 1 to fade out,\r
+;       however additional parameters may be specified. To set the effect\r
+;       speed, i.e. the number of iterations needed to completely fade a\r
+;       palette, shift the value one bit left and "or" it with the\r
+;       direction bit (range is 0..127). To set the delay between two\r
+;       consecutive passes, shift it eight bits left (range is 0..255).\r
+;\r
+mxFadePalette   PROC FAR\r
+        ARG     bBlue:WORD,                     \\r
+                bGreen:WORD,                    \\r
+                bRed:WORD,                      \\r
+                wCount:WORD,                    \\r
+                wStartIdx:WORD,                 \\r
+                wCommand:WORD,                  \\r
+                vfpPalette:DWORD = ARG_SIZE\r
+        LOCAL   bSPalette:BYTE:MAXCOLOR*3,      \\r
+                bDPalette:BYTE:MAXCOLOR*3,      \\r
+                bLoopIndex:BYTE,                \\r
+                bLoopStep:BYTE,                 \\r
+                bLoopCount:BYTE,                \\r
+                wDelay:WORD,                    \\r
+                wSpeed:WORD     = AUTO_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  AUTO_SIZE\r
+        .push   si, di, ds, es                  ; Save registers\r
+;\r
+; Check parameters and setup variables\r
+;\r
+@@GetDelay:\r
+        mov     [wDelay], FADE_DELAY            ; Set default delay\r
+        mov     ax, [wCommand]                  ; Get command word\r
+        and     ax, MASK fpDELAY                ; Mask delay command\r
+        jz      @@GetSpeed                      ; No command, get speed\r
+    IF USE286 EQ TRUE\r
+        shr     ax, fpDELAY\r
+    ELSE\r
+        mov     cl, fpDELAY                     ; Get size of delay field\r
+        shr     ax, cl                          ; Right justify the field\r
+    ENDIF\r
+        mov     [wDelay], ax                    ; Set new delay\r
+\r
+@@GetSpeed:\r
+        mov     ax, [wCommand]                  ; Get command\r
+        and     ax, MASK fpSPEED                ; Mask speed\r
+    IF USE286 EQ TRUE\r
+        shr     ax, fpSPEED\r
+    ELSE\r
+        mov     cl, fpSPEED                     ; Get size of speed field\r
+        shr     ax, cl                          ; Right justify the field\r
+    ENDIF\r
+        or      ax, ax                          ; Any speed specified?\r
+        jnz     @@SetVariables                  ; Yes, set variables\r
+        mov     ax, FADE_SPEED                  ; Set default speed\r
+\r
+@@SetVariables:\r
+        mov     [wSpeed], ax                    ; Set speed\r
+        inc     ax                              ; Number of iterations\r
+        mov     [bLoopCount], al                ; Set loop count\r
+        mov     [bLoopStep], 1                  ; Assume we're fading in\r
+        mov     [bLoopIndex], 0\r
+;\r
+; Check bounds for bad values\r
+;\r
+        mov     ax, [wStartIdx]                 ; Get first index\r
+        cmp     ax, MAXCOLOR                    ; Is in the valid range?\r
+        jae     @@Exit                          ; No, exit\r
+        add     ax, [wCount]                    ; Get last index\r
+        cmp     ax, MAXCOLOR                    ; Is in the valid range?\r
+        jbe     @@BoundsOk                      ; Yes, continue\r
+        mov     ax, MAXCOLOR\r
+        sub     ax, [wStartIdx]\r
+        mov     [wCount], ax                    ; Set count to maximum value\r
+        or      ax, ax\r
+        jz      @@Exit                          ; Nothing to do, exit\r
+@@BoundsOk:\r
+;\r
+; Copy the source palette in a local array: if we fade in it's ready to\r
+; use, otherwise we'll overwrite it later\r
+;\r
+        mov     cx, [wCount]\r
+        mov     ax, cx\r
+        shl     ax, 1\r
+        add     cx, ax                          ; CX = wCount * 3\r
+        mov     ax, ss\r
+        mov     es, ax\r
+        lea     di, [bSPalette]                 ; ES:DI points to local palette\r
+        mov     ax, [wStartIdx]\r
+        mov     si, ax\r
+        shl     ax, 1\r
+        add     ax, si\r
+        lds     si, [vfpPalette]                ; DS:SI points to user palette\r
+        add     si, ax                          ; Skip unused entries\r
+        cld\r
+        shr     cx, 1\r
+        rep     movsw\r
+        rcl     cx, 1\r
+        rep     movsb\r
+;\r
+; Check direction\r
+;\r
+        test    [wCommand], MASK fpDIRECTION    ; Are we fading in?\r
+        jz      @@Main                          ; Yes, ok to continue\r
+        mov     ax, [wSpeed]                    ; Get speed\r
+        mov     [bLoopIndex], al                ; Exchange first and last index\r
+        mov     [bLoopStep], -1                 ; Move backward\r
+        mov     ax, ss                          ; Overwrite our copy of\r
+        mov     ds, ax                          ; user palette with the\r
+        mov     es, ax                          ; current active palette\r
+        lea     di, [bSPalette]\r
+        mov     ax, [wStartIdx]\r
+        mov     cx, [wCount]\r
+        call    ReadPalette                     ; Read current palette\r
+;\r
+; Prepare variables and registers for fading\r
+;\r
+@@Main:\r
+        mov     bh, BYTE PTR [bRed]             ; Destination red\r
+        and     bh, 00111111b                   ; Be sure it's a valid VGA value\r
+        mov     bl, BYTE PTR [bGreen]           ; Destination green\r
+        and     bl, 00111111b                   ; Be sure it's a valid VGA value\r
+        mov     dh, BYTE PTR [bBlue]            ; Destination blue\r
+        and     dh, 00111111b                   ; Be sure it's a valid VGA value\r
+        mov     dl, [bLoopIndex]                ; Loop index\r
+        mov     ax, ss                          ; All tables are stored\r
+        mov     ds, ax                          ; in the stack segment,\r
+        mov     es, ax                          ; set DS and ES\r
+;\r
+; Main loop\r
+;\r
+@@Loop:\r
+        mov     ax, [wCount]                    ; Store count in AX\r
+        mov     cx, [wSpeed]                    ; Set maximum speed in CX\r
+        lea     si, [bSPalette]                 ; DS:SI points to source palette\r
+        lea     di, [bDPalette]                 ; ES:DI points to dest. palette\r
+        call    RecalcPalette                   ; Build a faded palette\r
+\r
+        .push   bx, dx                          ; Save registers we need\r
+        lea     si, [bDPalette]                 ; DS:SI points to palette\r
+        mov     ax, [wStartIdx]                 ; First index to write\r
+        mov     bx, [wCount]                    ; Total entries to write\r
+        mov     cx, [wDelay]                    ; Fade delay between updates\r
+        call    WritePalette                    ; Write palette\r
+        .pop    bx, dx                          ; Restore BX and DX\r
+\r
+        add     dl, [bLoopStep]                 ; Change fade intensity\r
+        dec     [bLoopCount]                    ; Done?\r
+        jnz     @@Loop                          ; No, loop again\r
+\r
+@@Exit:\r
+        .pop    si, di, ds, es                  ; Restore registers\r
+        .leave  ARG_SIZE\r
+mxFadePalette   ENDP\r
+\r
+;------- INTERNAL USE ONLY ------------------------------------------------\r
+;\r
+; Calculates a partially faded palette.\r
+;\r
+; Input:\r
+;       AX      = number of entries in palette\r
+;       CX      = maximum fade intensity (same as fade speed)\r
+;       DS:SI   = pointer to source palette\r
+;       ES:DI   = pointer to destination palette\r
+;       BH      = destination red\r
+;       BL      = destination green\r
+;       DH      = destination blue\r
+;       DL      = relative intensity of destination palette\r
+; Note:\r
+;       it's important that a new palette can be calculated in less\r
+;       than 1/70th of second. Fading to any RGB value requires use\r
+;       of "imul" instructions: "idiv" may be replaced with faster\r
+;       "sar", but only when the number of passes is a power of two,\r
+;       thus reducing the range of selectable speeds.\r
+;       In both cases an extimate of CPU cycles required by this\r
+;       procedure shows that it's too slow to run on a 4.77 Mhz 8086\r
+;       CPU and a 256 color palette, so we keep "idiv" and hope\r
+;       the target machine to be at least a 6 Mhz 80286 (that's not\r
+;       asking too much...).\r
+;\r
+RecalcPalette   PROC NEAR\r
+        cld\r
+        push    bp                              ; Save BP\r
+        mov     bp, ax                          ; Copy counter in BP\r
+@@Loop:\r
+        lodsb                                   ; Red: read value\r
+        sub     al, bh                          ; Subtract destination value\r
+        imul    dl                              ; Scale to desired weight\r
+        idiv    cl                              ; Put value in AL\r
+        add     al, bh                          ; Add destination value...\r
+        stosb                                   ; ...and store it\r
+        lodsb                                   ; Green: read value\r
+        sub     al, bl                          ; Subtract destination value\r
+        imul    dl                              ; Scale to desired weight\r
+        idiv    cl                              ; Put value in AL\r
+        add     al, bl                          ; Add destination value...\r
+        stosb                                   ; ...and store it\r
+        lodsb                                   ; Blue: read value\r
+        sub     al, dh                          ; Subtract destination value\r
+        imul    dl                              ; Scale to desired weight\r
+        idiv    cl                              ; Put value in AL\r
+        add     al, dh                          ; Add destination value...\r
+        stosb                                   ; ...and store it\r
+        dec     bp\r
+        jnz     @@Loop\r
+        pop     bp                              ; Restore BP\r
+        ret\r
+RecalcPalette   ENDP\r
+\r
+;------- INTERNAL USE ONLY ------------------------------------------------\r
+;\r
+; Writes a 256 color palette.\r
+;\r
+; Input:\r
+;       AX      = index of first color to write\r
+;       BX      = number of colors to write (each color is an RGB triplet)\r
+;       CX      = number of vertical retraces to wait before writing to DACs\r
+;       DS:SI   = pointer to first entry of palette\r
+;\r
+WritePalette    PROC NEAR\r
+        ASSUME  ds:NOTHING\r
+        mov     ah, al                          ; Save index\r
+        mov     dx, 03DAh                       ; Input status register\r
+@@Delay1:\r
+        in      al, dx\r
+        test    al, 08h\r
+        jnz     @@Delay1                        ; Wait for display mode\r
+@@Delay2:\r
+        in      al, dx\r
+        test    al, 08h\r
+        jz      @@Delay2                        ; Wait for vertical retrace mode\r
+        loop    @@Delay1                        ; Repeat CX times\r
+@@Write:\r
+        mov     cx, bx                          ; Get number of colors\r
+        mov     dx, 03C8h                       ; PEL write address register\r
+        mov     al, ah                          ; Restore index\r
+        out     dx, al                          ; Select index of first color\r
+        inc     dx                              ; PEL data register\r
+        cld                                     ; Move forward\r
+        cli                                     ; Disable interrupts\r
+@@Loop:\r
+        lodsb\r
+        out     dx, al                          ; Red\r
+        lodsb\r
+        out     dx, al                          ; Green\r
+        lodsb\r
+        out     dx, al                          ; Blue\r
+        loop    @@Loop                          ; Loop until done\r
+        sti                                     ; Enable interrupts\r
+        ret\r
+WritePalette    ENDP\r
+\r
+;------- INTERNAL USE ONLY ------------------------------------------------\r
+;\r
+; Reads the current palette.\r
+;\r
+; Input:\r
+;       AX      = index of first color to read\r
+;       CX      = number of colors\r
+;       ES:DI   = pointer to destination buffer\r
+;\r
+ReadPalette     PROC    NEAR\r
+        mov     dx, 03C7h\r
+        out     dx, al\r
+        inc     dx\r
+        inc     dx\r
+        cld\r
+@@Loop:\r
+        in      al, dx\r
+        stosb\r
+        in      al, dx\r
+        stosb\r
+        in      al, dx\r
+        stosb\r
+        loop    @@Loop\r
+        ret\r
+ReadPalette     ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxgc.asm b/16/xw/mxgc.asm
new file mode 100755 (executable)
index 0000000..85edf7a
--- /dev/null
@@ -0,0 +1,54 @@
+;-----------------------------------------------------------\r
+;\r
+; MXGC.ASM - Get color function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxGetColor\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current setting of the selected DAC register.\r
+;\r
+; Input:\r
+;       Index   = color index (0-255)\r
+;       R, G, B = byte pointers to red, green and blue\r
+; Output:\r
+;       none\r
+;\r
+mxGetColor      PROC FAR\r
+        ARG     B:DWORD,        \\r
+                G:DWORD,        \\r
+                R:DWORD,        \\r
+                Index:WORD      = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+\r
+        mov     ax, [Index]\r
+        mov     dx, 3C7h                ; PEL read address register\r
+        out     dx, al\r
+        inc     dx\r
+        inc     dx\r
+\r
+        lds     si, [R]\r
+        in      al, dx\r
+        mov     ds:[si], al\r
+        lds     si, [G]\r
+        in      al, dx\r
+        mov     ds:[si], al\r
+        lds     si, [B]\r
+        in      al, dx\r
+        mov     ds:[si], al\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetColor      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxgi.asm b/16/xw/mxgi.asm
new file mode 100755 (executable)
index 0000000..7037d41
--- /dev/null
@@ -0,0 +1,132 @@
+;-----------------------------------------------------------\r
+;\r
+; MXGI.ASM - Get image\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxGetImage\r
+\r
+EXTRN   subClipImage            : NEAR\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies an image from screen to memory.\r
+;\r
+; Input:\r
+;       Image   = pointer to buffer for image\r
+;       X, Y    = coordinates of image on screen\r
+;       Width   = width of image in pixels\r
+;       Height  = height of image in pixels\r
+; Output:\r
+;       none\r
+;\r
+mxGetImage      PROC    FAR\r
+        ARG     Height:WORD,            \\r
+                Width:WORD,             \\r
+                Y:WORD,                 \\r
+                X:WORD,                 \\r
+                Image:DWORD             = ARG_SIZE\r
+        LOCAL   PlaneWidth:WORD:4,      \\r
+                PixelOffset:WORD,       \\r
+                MoveFunction:WORD,      \\r
+                ReadPlane:BYTE,         \\r
+                Count:BYTE              = AUTO_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+\r
+; Clip image\r
+        mov     bx, [X]\r
+        mov     ax, [Y]\r
+        mov     cx, [Width]\r
+        mov     dx, [Height]\r
+        call    subClipImage\r
+        jc      @@Exit                  ; Full clipped\r
+        mov     [Height], dx\r
+        add     WORD PTR Image[0], si   ; Skip clipped pixels\r
+\r
+; Get pixel address\r
+        mul     [mx_BytesPerLine]\r
+        mov     si, bx\r
+        shr     si, 1\r
+        shr     si, 1\r
+        add     si, ax\r
+        mov     [PixelOffset], si\r
+        mov     ds, [mx_VideoSegment]   ; DS:SI points to pixel\r
+        and     bl, 03h\r
+        mov     [ReadPlane], bl\r
+\r
+; Compute extra bytes and width count for each plane\r
+        mov     bx, cx\r
+        shr     bx, 1\r
+        shr     bx, 1                   ; Width for each plane\r
+        and     cl, 03h\r
+        mov     al, 00001000b\r
+        shr     al, cl\r
+        mov     di, 3 SHL 1\r
+@@PatchLoop:\r
+        mov     PlaneWidth[di], bx\r
+        shr     al, 1\r
+        adc     bx, 0\r
+        dec     di\r
+        dec     di\r
+        jge     @@PatchLoop\r
+\r
+; Get image\r
+        cld\r
+        mov     [Count], 4              ; Four planes\r
+        lea     bx, PlaneWidth          ; SS:[BX] = width in bytes for plane\r
+        mov     es, WORD PTR Image[2]   ; ES:DI will point to image\r
+        mov     ah, [ReadPlane]\r
+@@PlaneLoop:\r
+        cmp     WORD PTR ss:[bx], 0     ; Exit if nothing more to do\r
+        je      @@Exit                  ; (also, never try to move zero bytes!)\r
+        mov     di, WORD PTR Image[0]\r
+        mov     al, 04h\r
+        mov     dx, GDC\r
+        out     dx, ax                  ; Select read plane\r
+        mov     dx, [Height]\r
+        mov     si, [PixelOffset]       ; DS:SI points to video memory\r
+@@Loop:\r
+        .push   si, di\r
+        mov     cx, WORD PTR ss:[bx]    ; Number of bytes to move\r
+@@MoveLoop:\r
+        movsb\r
+        add     di, 3\r
+        dec     cx\r
+        jnz     @@MoveLoop\r
+        .pop    si, di\r
+        add     di, [Width]             ; Go to next image line\r
+        add     si, [mx_BytesPerLine]   ; Go to next screen row\r
+        dec     dx\r
+        jnz     @@Loop                  ; Repeat for all lines\r
+        inc     bx\r
+        inc     bx                      ; Select width for next plane\r
+        inc     ah\r
+        test    ah, 04h                 ; Plane wraparound?\r
+        jz      @@PlaneOk               ; No\r
+        inc     [PixelOffset]           ; Yes, bump video pointer\r
+        and     ah, 03h\r
+@@PlaneOk:\r
+        inc     WORD PTR Image[0]\r
+        dec     [Count]\r
+        jnz     @@PlaneLoop             ; Repeat for all planes\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxGetImage      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxgm.asm b/16/xw/mxgm.asm
new file mode 100755 (executable)
index 0000000..a67476a
--- /dev/null
@@ -0,0 +1,63 @@
+;-----------------------------------------------------------\r
+;\r
+; MXGM.ASM - Gamma correction\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxGammaCorrect\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+mx_tblGamma     LABEL BYTE\r
+    DB  00, 10, 14, 17, 19, 21, 23, 24, 26, 27, 28, 29, 31, 32, 33, 34\r
+    DB  35, 36, 37, 37, 38, 39, 40, 41, 41, 42, 43, 44, 44, 45, 46, 46\r
+    DB  47, 48, 48, 49, 49, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55\r
+    DB  56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Correct palette colors (gamma is 2.3).\r
+;\r
+; Input:\r
+;       CPal    = pointer to color palette\r
+;       GPal    = pointer to destination (gamma corrected) palette\r
+;       Count   = number of colors to convert\r
+; Output:\r
+;       none\r
+;\r
+; Note: CPal and GPal may point to the same buffer.\r
+;\r
+mxGammaCorrect  PROC    FAR\r
+        ARG     Count:WORD,     \\r
+                DPal:DWORD,     \\r
+                SPal:DWORD      = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si, es, di\r
+\r
+        mov     cx, [Count]\r
+        jcxz    @@Exit                  ; Exit now if nothing to do\r
+        lds     si, [SPal]\r
+        les     di, [DPal]\r
+        mov     bx, OFFSET mx_tblGamma  ; Setup BX for XLAT instruction\r
+        cld\r
+        mov     ax, cx                  ; AX = Count\r
+        add     cx, cx                  ; CX = Count*2\r
+        add     cx, ax                  ; CX = Count*3\r
+@@Loop:\r
+        lodsb\r
+        xlat    mx_tblGamma\r
+        stosb\r
+        loop    @@Loop\r
+\r
+@@Exit:\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxGammaCorrect  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxgp.asm b/16/xw/mxgp.asm
new file mode 100755 (executable)
index 0000000..6c14317
--- /dev/null
@@ -0,0 +1,56 @@
+;-----------------------------------------------------------\r
+;\r
+; MXGP.ASM - Get palette function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxGetPalette\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current setting of the VGA palette.\r
+;\r
+; Input:\r
+;       Buffer          = pointer to palette data (R,G,B)\r
+;       Start           = index of first color to get\r
+;       Count           = number of color to get\r
+; Output:\r
+;       none\r
+;\r
+mxGetPalette    PROC    FAR\r
+        ARG     Count:WORD,             \\r
+                Start:WORD,             \\r
+                Buffer:DWORD            = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   es, di\r
+\r
+        les     di, [Buffer]\r
+        mov     cx, [Count]\r
+        mov     ax, [Start]\r
+        mov     dx, 3C7h                ; PEL read address register\r
+        out     dx, al\r
+        inc     dx\r
+        inc     dx\r
+        cld\r
+@@Loop:\r
+        in      al, dx\r
+        stosb\r
+        in      al, dx\r
+        stosb\r
+        in      al, dx\r
+        stosb\r
+        loop    @@Loop                  ; Loop until done\r
+\r
+        .pop    es, di\r
+        .leave  ARG_SIZE\r
+mxGetPalette    ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxgv.asm b/16/xw/mxgv.asm
new file mode 100755 (executable)
index 0000000..2a54b1d
--- /dev/null
@@ -0,0 +1,25 @@
+;-----------------------------------------------------------\r
+;\r
+; MXGV.ASM - Get version function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxGetVersion\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the library version.\r
+;\r
+mxGetVersion    PROC    FAR\r
+        mov     ax, MXVERSION\r
+        ret\r
+mxGetVersion    ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxhl.asm b/16/xw/mxhl.asm
new file mode 100755 (executable)
index 0000000..049a056
--- /dev/null
@@ -0,0 +1,76 @@
+;-----------------------------------------------------------\r
+;\r
+; MXHL.ASM - Horizontal line mask utility\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  subHorizontalLineInfo\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+tblLeftSize     DW      00h, 03h, 02h, 01h\r
+tblLeftMask     DB      00h, 0Eh, 0Ch, 08h\r
+tblRightMask    DB      00h, 01h, 03h, 07h\r
+tblPatchMask    DB      02h, 06h\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Prepares register for fast horizontal line drawing.\r
+;\r
+; Input:\r
+;       BX, AX  = X, Y address of left pixel\r
+;       CX      = line width\r
+; Output:\r
+;       DI      = left pixel offset in video memory\r
+;       AL      = left block write plane mask (0 = none)\r
+;       AH      = right block write plane mask (0 = none)\r
+;       CX      = center block width in 4-pixel blocks\r
+;\r
+subHorizontalLineInfo   PROC NEAR\r
+        ASSUME  ds:NOTHING\r
+\r
+        mul     [mx_BytesPerLine]\r
+        mov     di, bx\r
+        shr     di, 1\r
+        shr     di, 1\r
+        add     di, ax                  ; Offset of left pixel\r
+\r
+        and     bx, 03h\r
+        mov     al, tblLeftMask[bx]\r
+        shl     bx, 1\r
+        sub     cx, tblLeftSize[bx]\r
+        jge     @@1                     ; Ok to continue\r
+\r
+; Special case: start and end in the middle of a 4-pixel block.\r
+; There are only three cases:\r
+;    Pixels     Left mask       CX      CX+2    Patch mask      Result\r
+; 1)  ..o.        ..xx          -1      1       .xx.            ..x.\r
+; 2)  .oo.        .xxx          -1      1       .xx.            .xx.\r
+; 3)  .o..        .xxx          -2      0       .x..            .x..\r
+; All other cases are automatically handled with the standard masks.\r
+        mov     bx, cx\r
+        inc     bx\r
+        inc     bx\r
+        and     al, tblPatchMask[bx]    ; Combine masks\r
+        xor     ah, ah                  ; No right block\r
+        xor     cx, cx                  ; No center block\r
+        jmp     @@Exit\r
+\r
+@@1:\r
+        mov     bx, cx\r
+        and     bx, 03h\r
+        mov     ah, tblRightMask[bx]\r
+        shr     cx, 2\r
+\r
+@@Exit:\r
+        ret\r
+subHorizontalLineInfo   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxit.asm b/16/xw/mxit.asm
new file mode 100755 (executable)
index 0000000..c0d9ced
--- /dev/null
@@ -0,0 +1,98 @@
+;-----------------------------------------------------------\r
+;\r
+; MXIT.ASM - Initialization/termination functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxInit\r
+PUBLIC  mxTerm\r
+\r
+PUBLIC  mx_VideoSegment\r
+PUBLIC  mx_CodeSegment\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+DB      'MODEX library - Copyright (c) 1992-1994 Alessandro Scotti'\r
+\r
+mx_VideoSegment DW      0A000h\r
+mx_CodeSegment  DW      SEG MX_TEXT\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Initialization.\r
+;\r
+; Input:\r
+;       none\r
+; Output:\r
+;       AX      = 0 on success\r
+;\r
+mxInit  PROC FAR\r
+        LOCAL   Result:WORD,            \\r
+                VideoSeg:WORD,          \\r
+                CStoDSalias:WORD        = AUTO_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+\r
+        mov     [Result], -1            ; Assume an error\r
+        mov     [VideoSeg], 0A000h      ; Real mode video segment\r
+        mov     [CStoDSalias], cs       ; Real mode data alias for CS\r
+\r
+; Check if running in protected mode under DPMI\r
+        mov     ax, 1686h\r
+        int     2Fh\r
+        or      ax, ax\r
+         jnz    @@1                     ; DPMI not found, continue in real mode\r
+\r
+; Get a data alias for CS\r
+        mov     ax, 000Ah               ; DMPI: create data alias\r
+        mov     bx, cs\r
+        int     31h\r
+         jc     @@Exit                  ; Exit if service failed\r
+        mov     [CStoDSalias], ax       ; Save data alias for CS\r
+; Get a protected-mode selector for the video segment\r
+        mov     ax, 0002h\r
+        mov     bx, 0A000h              ; Real mode segment of video\r
+        int     31h                     ; DPMI: get segment selector\r
+         jc     @@Exit                  ; Exit if service failed\r
+        mov     [VideoSeg], ax          ; Save protected mode video selector\r
+\r
+; Initialize variables\r
+@@1:\r
+        mov     ds, [CStoDSalias]\r
+        ASSUME  ds:MX_TEXT\r
+        mov     [mx_CodeSegment], ds\r
+        mov     ax, [VideoSeg]\r
+        mov     [mx_VideoSegment], ax\r
+\r
+; Don't bother with VGA check for now...\r
+\r
+        mov     [Result], 0\r
+\r
+@@Exit:\r
+        mov     ax, [Result]\r
+        .pop    ds, si, es, di\r
+        .leave\r
+mxInit  ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Termination.\r
+;\r
+; Input:\r
+;       none\r
+; Output:\r
+;       always 0.\r
+;\r
+mxTerm  PROC FAR\r
+        ASSUME  ds:NOTHING\r
+        xor     ax, ax\r
+        ret\r
+mxTerm  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxll.asm b/16/xw/mxll.asm
new file mode 100755 (executable)
index 0000000..34fec04
--- /dev/null
@@ -0,0 +1,82 @@
+;-----------------------------------------------------------\r
+;\r
+; MXLL.ASM - Load latches\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxLoadLatches\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Loads the specified value into the VGA latches.\r
+;\r
+; Input:\r
+;       BL      = value to load into latches\r
+; Output:\r
+;       none\r
+; Changes:\r
+;       bit mask register to FFh;\r
+;       function select register to "move";\r
+;       write mode to 00h.\r
+; Note:\r
+;       this is for internal use only.\r
+;\r
+mxLoadLatches   PROC    NEAR\r
+        ASSUME  ds:NOTHING\r
+\r
+        .push   ds, si\r
+        mov     dx, GDC\r
+        mov     ax, 0FF08h\r
+        out     dx, ax                  ; Set bit mask to FFh\r
+        mov     ax, 0003h\r
+        out     dx, ax                  ; Set function to "move"\r
+        mov     ax, 0005h\r
+        out     dx, ax                  ; Set write mode\r
+        mov     ax, [mx_VideoSegment]\r
+        mov     ds, ax\r
+        mov     si, 0FFFFh\r
+        mov     bh, 8                   ; BH = write plane mask\r
+        mov     cx, 3                   ; CX = count = read plane\r
+; Saves old values and force BL into latches\r
+@@SetLoop:\r
+        mov     dx, GDC\r
+        mov     al, 04h\r
+        mov     ah, cl\r
+        out     dx, ax                  ; Select read plane\r
+        mov     dx, TS\r
+        mov     al, 02h\r
+        mov     ah, bh\r
+        out     dx, ax                  ; Select write plane\r
+        mov     al, ds:[si]\r
+        push    ax\r
+        mov     ds:[si], bl\r
+        mov     al, ds:[di]             ; Force value into latch\r
+        shr     bh, 1                   ; Next write plane\r
+        loop    @@SetLoop\r
+; Restore previous values\r
+        mov     cx, 3\r
+        mov     bh, 8\r
+        mov     dx, TS\r
+@@ResetLoop:\r
+        mov     al, 02h\r
+        mov     ah, bh\r
+        out     dx, ax                  ; Select write plane\r
+        pop     ax\r
+        mov     ds:[si], al\r
+        shr     bh, 1                   ; Next write plane\r
+        loop    @@ResetLoop\r
+; Exit\r
+        .pop    ds, si\r
+        ret\r
+mxLoadLatches   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxln.asm b/16/xw/mxln.asm
new file mode 100755 (executable)
index 0000000..fbc4ab9
--- /dev/null
@@ -0,0 +1,414 @@
+;-----------------------------------------------------------\r
+;\r
+; MXLN.ASM - Line function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+        ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_VideoSegment : WORD\r
+\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+\r
+tblDrawFunc     LABEL   WORD\r
+        DW      subWidthMove\r
+        DW      subHeightMove\r
+        DW      subWidthOp\r
+        DW      subHeightOp\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Draws a line from (X1,Y1) to (X2,Y2) using the Bresenham\r
+; algorithm.\r
+;\r
+; Input:\r
+;       X1, Y1  = start point\r
+;       X2, Y2  = end point\r
+;       Color   = line color\r
+;       Op      = raster operator\r
+; Output:\r
+;       none\r
+;\r
+; Note: the end point (X2,Y2) *IS* drawed. I don't like this very much\r
+; but clipping is much simpler.\r
+;\r
+mxLine  PROC FAR\r
+        ARG     Op:WORD,        \\r
+                Color:WORD,     \\r
+                Y2:WORD,        \\r
+                X2:WORD,        \\r
+                Y1:WORD,        \\r
+                X1:WORD         = ARG_SIZE\r
+        LOCAL   Width:WORD,     \\r
+                Height:WORD,    \\r
+                ErrorAdd:WORD,  \\r
+                ErrorSub:WORD,  \\r
+                DeltaX:WORD,    \\r
+                DeltaY:WORD,    \\r
+                P1:BYTE,        \\r
+                P2:BYTE,        \\r
+                WritePlane:BYTE = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, di\r
+        ASSUME  ds:NOTHING\r
+\r
+        mov     ax, [X1]\r
+        mov     bx, [Y1]\r
+        mov     cx, [X2]\r
+        mov     dx, [Y2]\r
+        call    subClipLine\r
+        jc      @@Exit                  ; Line is full clipped\r
+\r
+; Get width\r
+        mov     si, cx\r
+        xchg    ax, si                  ; SI = X1, AX = X2\r
+        sub     ax, si\r
+        jge     @@1\r
+; Swap points, we want X1 < X2\r
+        xchg    si, cx                  ; Swap X1 and X2\r
+        xchg    bx, dx                  ; Swap Y1 and Y2\r
+        neg     ax\r
+@@1:\r
+        mov     [Width], ax\r
+\r
+; Get height\r
+        mov     cx, [mx_BytesPerLine]   ; We don't need X2 anymore\r
+        mov     ax, dx\r
+        sub     ax, bx\r
+        jge     @@2\r
+        neg     cx                      ; Move from bottom to top\r
+        neg     ax                      ; Get absolute value of AX\r
+@@2:\r
+        mov     [Height], ax\r
+        mov     [DeltaY], cx\r
+\r
+; Get pixel address and write plane\r
+        mov     ax, bx\r
+        mul     [mx_BytesPerLine]\r
+        mov     cx, si                  ; CX = X1\r
+        shr     si, 1\r
+        shr     si, 1\r
+        add     si, ax                  ; SI = pixel offset\r
+        and     cl, 03h\r
+        mov     ax, 1102h\r
+        shl     ah, cl\r
+        mov     [WritePlane], ah\r
+        mov     dx, TS\r
+        out     dx, ax                  ; Set write plane\r
+        mov     ax, [mx_VideoSegment]\r
+        mov     ds, ax                  ; DS:SI points to (X1,Y1)\r
+\r
+; Select the function to handle the drawing loop\r
+        xor     bx, bx\r
+        mov     al, BYTE PTR [Op]\r
+        cmp     al, OP_MOVE\r
+        je      @@3\r
+        and     al, 03h\r
+        shl     al, 1\r
+        shl     al, 1\r
+        shl     al, 1\r
+        mov     ah, al\r
+        mov     al, 03h\r
+        mov     dx, GDC\r
+        out     dx, ax                  ; Set logical function\r
+        inc     bx\r
+        inc     bx\r
+@@3:\r
+        mov     ax, [Width]\r
+        mov     cx, [Height]\r
+; Horizontal, vertical and diagonal lines are not optimized yet\r
+        cmp     ax, cx\r
+        jae     @@4\r
+        inc     bx\r
+@@4:\r
+        shl     bx, 1\r
+        call    tblDrawFunc[bx]\r
+\r
+; Reset logical function if needed\r
+        cmp     BYTE PTR [Op], OP_MOVE\r
+        je      @@Exit\r
+        mov     ax, 0003h\r
+        mov     dx, GDC\r
+        out     dx, ax\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, di\r
+        .leave  ARG_SIZE\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Checks the coordinates of a line against the active\r
+; clip region.\r
+; Uses a variation of the Cohen-Sutherland algorithm developed\r
+; by Victor Duvanenko.\r
+;\r
+; Input:\r
+;       AX, BX  = X1, Y1\r
+;       CX, DX  = X2, Y2\r
+; Output:\r
+;       CF      = set if line is full clipped\r
+;       AX, BX  = clipped X1, Y1\r
+;       CX, DX  = clipped X2, Y2\r
+; Note:\r
+;       destroys SI, DI\r
+;\r
+subClipLine     PROC    NEAR\r
+        mov     di, ax                  ; Copy X1 to DI and free AX\r
+        mov     si, dx                  ; Copy Y2 to SI and free DX\r
+; Compute clip codes for point (X2,Y2)=(CX,SI)\r
+        xor     al, al\r
+@@P2X1: cmp     cx, [mx_ClipX1]\r
+        jge     @@P2X2\r
+        or      al, 1\r
+@@P2X2: cmp     cx, [mx_ClipX2]\r
+        jle     @@P2Y1\r
+        or      al, 2\r
+@@P2Y1: cmp     si, [mx_ClipY1]\r
+        jge     @@P2Y2\r
+        or      al, 4\r
+@@P2Y2: cmp     si, [mx_ClipY2]\r
+        jle     @@P2XY\r
+        or      al, 8\r
+@@P2XY: mov     [P2], al\r
+; Compute clip codes for point (X1,Y1)=(DI,BX)\r
+        xor     al, al\r
+@@P1X1: cmp     di, [mx_ClipX1]\r
+        jge     @@P1X2\r
+        or      al, 1\r
+@@P1X2: cmp     di, [mx_ClipX2]\r
+        jle     @@P1Y1\r
+        or      al, 2\r
+@@P1Y1: cmp     bx, [mx_ClipY1]\r
+        jge     @@P1Y2\r
+        or      al, 4\r
+@@P1Y2: cmp     bx, [mx_ClipY2]\r
+        jle     @@P1XY\r
+        or      al, 8\r
+@@P1XY: mov     [P1], al\r
+; Check codes for trivial cases\r
+        mov     ah, [P2]\r
+        test    al, ah                  ; Is line invisible?\r
+        jnz     @@FullClip              ; Yes, exit\r
+        or      ah, al                  ; Both points clipped?\r
+        jz      @@Done                  ; Yes, exit\r
+; Calculate deltas\r
+        mov     ax, cx\r
+        sub     ax, di\r
+        mov     [DeltaX], ax\r
+        mov     ax, si\r
+        sub     ax, bx\r
+        mov     [DeltaY], ax\r
+        mov     al, [P1]                ; Init clipping code\r
+; Clipping loop\r
+@@ClipLoop:\r
+        test    al, al                  ; Is first point clipped?\r
+        jnz     @@ClipX1                ; No, continue\r
+        xchg    cx, di                  ; Swap points...\r
+        xchg    bx, si\r
+        xchg    al, [P2]                ; ...and codes\r
+; Clip left: Y1 = Y1 + DeltaY*(mx_ClipX1-X1)/DeltaX\r
+@@ClipX1:\r
+        test    al, 1\r
+        jz      @@ClipX2\r
+        mov     ax, [mx_ClipX1]\r
+        sub     ax, di\r
+        mov     di, [mx_ClipX1]\r
+        jmp     @@ClipX1X2\r
+; Clip right: Y1 = Y1 + DeltaY*(mx_ClipX2-X1)/DeltaX\r
+@@ClipX2:\r
+        test    al, 2\r
+        jz      @@ClipY1\r
+        mov     ax, [mx_ClipX2]\r
+        sub     ax, di\r
+        mov     di, [mx_ClipX2]\r
+@@ClipX1X2:\r
+        imul    [DeltaY]\r
+        idiv    [DeltaX]\r
+        add     bx, ax\r
+        mov     al, 8\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      @@CheckLoop\r
+        mov     al, 4\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      @@CheckLoop\r
+        xor     al, al\r
+        jmp     @@CheckLoop\r
+; Clip top: X1 = X1 + DeltaX*(mx_ClipY1-Y1)/DeltaY\r
+@@ClipY1:\r
+        test    al, 4\r
+        jz      @@ClipY2\r
+        mov     ax, [mx_ClipY1]\r
+        sub     ax, bx\r
+        mov     bx, [mx_ClipY1]\r
+        jmp     @@ClipY1Y2\r
+; Clip bottom: X1 = X1 + DeltaX*(mx_ClipY2-Y1)/DeltaY\r
+@@ClipY2:\r
+        mov     ax, [mx_ClipY2]\r
+        sub     ax, bx\r
+        mov     bx, [mx_ClipY2]\r
+@@ClipY1Y2:\r
+        imul    [DeltaX]\r
+        idiv    [DeltaY]\r
+        add     di, ax\r
+        mov     al, 1\r
+        cmp     di, [mx_ClipX1]\r
+        jl      @@CheckLoop\r
+        mov     al, 2\r
+        cmp     di, [mx_ClipX2]\r
+        jg      @@CheckLoop\r
+        xor     al, al\r
+@@CheckLoop:\r
+        mov     ah, [P2]\r
+        test    al, ah\r
+        jnz     @@FullClip\r
+        or      ah, al\r
+        jnz     @@ClipLoop\r
+\r
+@@Done:\r
+        mov     ax, di\r
+        mov     dx, si\r
+        clc\r
+        ret\r
+@@FullClip:\r
+        stc\r
+        ret\r
+subClipLine     ENDP\r
+\r
+; Called when Width >= Height and Op = OP_MOVE\r
+subWidthMove    PROC NEAR\r
+        mov     di, ax\r
+        neg     di                      ; Initialize error term\r
+        shl     cx, 1\r
+        mov     [ErrorAdd], cx\r
+        mov     cx, ax\r
+        shl     ax, 1\r
+        mov     [ErrorSub], ax\r
+        mov     al, 02h\r
+        mov     ah, [WritePlane]\r
+        mov     bl, BYTE PTR [Color]\r
+        mov     dx, TS\r
+        inc     cx\r
+@@Loop:\r
+        mov     ds:[si], bl\r
+        dec     cx\r
+        jz      @@Exit\r
+        rol     ah, 1\r
+        adc     si, 0\r
+        out     dx, ax\r
+        add     di, [ErrorAdd]\r
+        jl      @@Loop\r
+        add     si, [DeltaY]\r
+        sub     di, [ErrorSub]\r
+        jmp     @@Loop\r
+@@Exit:\r
+        ret\r
+subWidthMove    ENDP\r
+\r
+; Called when Width < Height and Op = OP_MOVE\r
+subHeightMove   PROC NEAR\r
+        mov     di, cx\r
+        neg     di                      ; Initialize error term\r
+        shl     ax, 1\r
+        mov     [ErrorAdd], ax\r
+        mov     ax, cx\r
+        shl     ax, 1\r
+        mov     [ErrorSub], ax\r
+        mov     bl, BYTE PTR [Color]\r
+        mov     ah, [WritePlane]\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        inc     cx\r
+@@Loop:\r
+        mov     ds:[si], bl\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, [DeltaY]\r
+        add     di, [ErrorAdd]\r
+        jl      @@Loop\r
+        rol     ah, 1                   ; Next write plane\r
+        adc     si, 0                   ; Bump video offset if plane overflows\r
+        out     dx, ax\r
+        sub     di, [ErrorSub]          ; Adjust error down\r
+        jmp     @@Loop\r
+@@Exit:\r
+        ret\r
+subHeightMove   ENDP\r
+\r
+; Called when Width >= Height and Op <> OP_MOVE\r
+subWidthOp      PROC NEAR\r
+        mov     di, ax\r
+        neg     di                      ; Initialize error term\r
+        shl     cx, 1\r
+        mov     [ErrorAdd], cx\r
+        mov     cx, ax\r
+        shl     ax, 1\r
+        mov     [ErrorSub], ax\r
+        mov     al, 02h\r
+        mov     ah, [WritePlane]\r
+        mov     bl, BYTE PTR [Color]\r
+        mov     dx, TS\r
+        inc     cx\r
+@@Loop:\r
+        mov     bh, ds:[si]             ; Latch data\r
+        mov     ds:[si], bl\r
+        dec     cx\r
+        jz      @@Exit\r
+        rol     ah, 1\r
+        adc     si, 0\r
+        out     dx, ax\r
+        add     di, [ErrorAdd]\r
+        jl      @@Loop\r
+        add     si, [DeltaY]\r
+        sub     di, [ErrorSub]\r
+        jmp     @@Loop\r
+@@Exit:\r
+        ret\r
+subWidthOp      ENDP\r
+\r
+; Called when Width < Height and Op <> OP_MOVE\r
+subHeightOp     PROC NEAR\r
+        mov     di, cx\r
+        neg     di                      ; Initialize error term\r
+        shl     ax, 1\r
+        mov     [ErrorAdd], ax\r
+        mov     ax, cx\r
+        shl     ax, 1\r
+        mov     [ErrorSub], ax\r
+        mov     bl, BYTE PTR [Color]\r
+        mov     ah, [WritePlane]\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        inc     cx\r
+@@Loop:\r
+        mov     bh, ds:[si]\r
+        mov     ds:[si], bl\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, [DeltaY]\r
+        add     di, [ErrorAdd]\r
+        jl      @@Loop\r
+        rol     ah, 1                   ; Next write plane\r
+        adc     si, 0                   ; Bump video offset if plane overflows\r
+        out     dx, ax\r
+        sub     di, [ErrorSub]          ; Adjust error down\r
+        jmp     @@Loop\r
+@@Exit:\r
+        ret\r
+subHeightOp     ENDP\r
+\r
+mxLine  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxot.asm b/16/xw/mxot.asm
new file mode 100755 (executable)
index 0000000..6254766
--- /dev/null
@@ -0,0 +1,330 @@
+;-----------------------------------------------------------\r
+;\r
+; MXOT.ASM - Text functions\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES                             ; We use the reserved name 'WIDTH'\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxOutChar\r
+PUBLIC  mxOutText\r
+PUBLIC  mxSetFont\r
+PUBLIC  mxSetTextColor\r
+PUBLIC  mxGetTextStep\r
+PUBLIC  mxSetTextStep\r
+\r
+MAX_WIDTH       EQU     16              ; Must be <= 16\r
+MAX_HEIGHT      EQU     32\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_CodeSegment  : WORD\r
+EXTRN   mxPutImage      : FAR\r
+\r
+; Default 8x8 font\r
+fnt_Default     LABEL\r
+        INCLUDE DEFAULT.FNT\r
+\r
+; Table of system fonts\r
+tbl_SystemFont   LABEL   WORD\r
+        DW      fnt_Default, 8, 8\r
+\r
+MX_MAXSYSFONT   EQU     ($-OFFSET tbl_SystemFont) SHR 2\r
+\r
+mx_FontPtr      DW      OFFSET fnt_Default, SEG MX_TEXT\r
+mx_FontWidth    DW      8               ; Font width in pixels\r
+mx_FontHeight   DW      8               ; Font height in pixels\r
+mx_FontCharSize DW      8               ; Size in bytes of a font character\r
+mx_FontColor    DW      00FFh           ; Color: foreground + background*256\r
+mx_FontOp       DW      OP_MOVE         ; Raster op\r
+mx_DeltaX       DW      8               ; Horizontal step\r
+mx_DeltaY       DW      0               ; Vertical step\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the current font.\r
+;\r
+; Input:\r
+;       Font    = pointer to font data\r
+;       Width   = width of font character in pixels\r
+;       Height  = height of font character in pixels\r
+; Output:\r
+;       AX = 0 on success, else invalid parameters\r
+;\r
+; Note: when the high word of Font (i.e. the segment) is zero, the low\r
+;       word is used to select one of the system fonts.\r
+;\r
+mxSetFont       PROC FAR\r
+        ARG     Height:WORD,    \\r
+                Width:WORD,     \\r
+                Font:DWORD      = ARG_SIZE\r
+        .enter  0\r
+        .push   ds\r
+\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, WORD PTR Font[2]    ; Get font segment\r
+        test    ax, ax                  ; Null segment?\r
+        jnz     @@UserFont              ; No, install user font\r
+\r
+; Install system font\r
+        mov     ax, WORD PTR Font[0]    ; Get font number\r
+        cmp     ax, MX_MAXSYSFONT       ; Check range\r
+        jb      @@SystemFont\r
+        xor     ax, ax                  ; Out of range, use default font\r
+@@SystemFont:\r
+        shl     ax, 1\r
+        shl     ax, 1\r
+        mov     bx, ax\r
+        mov     ax, tbl_SystemFont[bx]  ; Get font offset\r
+        mov     WORD PTR mx_FontPtr[0], ax\r
+        mov     WORD PTR mx_FontPtr[2], cs\r
+        mov     al, BYTE PTR tbl_SystemFont[bx+2]\r
+        xor     ah, ah\r
+        mov     [mx_FontWidth], ax\r
+        mov     [mx_DeltaX], ax\r
+        mov     dl, BYTE PTR tbl_SystemFont[bx+3]\r
+        xor     dh, dh\r
+        mov     [mx_FontHeight], dx\r
+        mul     dx\r
+        mov     [mx_FontCharSize], ax\r
+        mov     [mx_DeltaX], ax\r
+        xor     ax, ax\r
+        mov     [mx_DeltaY], ax\r
+        jmp     @@Exit\r
+\r
+; Install user font\r
+@@UserFont:\r
+        mov     ax, -1                  ; Assume an error\r
+        mov     bx, [Width]\r
+        cmp     bx, MAX_WIDTH\r
+        ja      @@Exit                  ; Invalid character width\r
+        mov     dx, [Height]\r
+        cmp     dx, MAX_HEIGHT\r
+        ja      @@Exit                  ; Invalid character height\r
+        mov     [mx_FontWidth], bx\r
+        mov     [mx_FontHeight], dx\r
+        mov     ax, bx\r
+        add     ax, 7\r
+        .shr    ax, 3\r
+        mul     dx\r
+        mov     [mx_FontCharSize], ax\r
+        mov     ax, WORD PTR Font[0]\r
+        mov     WORD PTR mx_FontPtr[0], ax\r
+        mov     ax, WORD PTR Font[2]\r
+        mov     WORD PTR mx_FontPtr[2], ax\r
+        xor     ax, ax\r
+\r
+@@Exit:\r
+        .pop    ds\r
+        ASSUME  ds:NOTHING\r
+        .leave  ARG_SIZE\r
+mxSetFont       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the text color and raster op.\r
+;\r
+; Input:\r
+;       Color   = text color (foreground + background*256)\r
+;       Op      = raster op\r
+; Output:\r
+;       none\r
+;\r
+mxSetTextColor  PROC FAR\r
+        ARG     Op:WORD,        \\r
+                Color:WORD      = ARG_SIZE\r
+        .enter  0\r
+        .push   ds\r
+\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, [Color]\r
+        mov     [mx_FontColor], ax\r
+        mov     ax, [Op]\r
+        mov     [mx_FontOp], ax\r
+\r
+        xor     ax, ax\r
+        .pop    ds\r
+        ASSUME  ds:NOTHING\r
+        .leave  ARG_SIZE\r
+mxSetTextColor  ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a character using the current font and attributes.\r
+;\r
+; Input:\r
+;       X, Y    = video coordinates\r
+;       C       = character to print\r
+; Output:\r
+;       none\r
+;\r
+mxOutChar       PROC FAR\r
+        ARG     C:BYTE:2,       \\r
+                Y:WORD,         \\r
+                X:WORD          = ARG_SIZE\r
+        LOCAL   Image:BYTE:MAX_WIDTH*MAX_HEIGHT,        \\r
+                Count:WORD                              = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+        ASSUME  ds:NOTHING\r
+\r
+; Gets the pointer to font data for the selected character\r
+        lds     si, DWORD PTR [mx_FontPtr]\r
+        mov     al, [C]\r
+        xor     ah, ah\r
+        mul     [mx_FontCharSize]       ; Offset into font\r
+        add     si, ax                  ; DS:SI -> font data for character\r
+\r
+; Converts font data into a 256-color linear image\r
+        mov     ax, ss\r
+        mov     es, ax\r
+        lea     di, [Image]\r
+        mov     dx, [mx_FontColor]\r
+        mov     ax, [mx_FontHeight]\r
+        mov     [Count], ax\r
+@@HeightLoop:\r
+        mov     cx, [mx_FontWidth]\r
+        mov     bh, ds:[si]\r
+        inc     si                      ; Get a byte from font data\r
+        cmp     cx, 8\r
+        jbe     @@WidthLoop             ; Ok for width <= 8\r
+        mov     bl, ds:[si]             ; Get another byte\r
+        inc     si\r
+@@WidthLoop:\r
+        mov     al, dl                  ; Assume foreground color\r
+        shl     bx, 1                   ; Is font bit set?\r
+        jc      @@1                     ; Yes, foreground is just great\r
+        mov     al, dh                  ; Get background color\r
+@@1:\r
+        mov     es:[di], al             ; Put pixel into image\r
+        inc     di\r
+        dec     cx\r
+        jnz     @@WidthLoop\r
+        dec     [Count]\r
+        jnz     @@HeightLoop\r
+\r
+; Now pass image to mx_PutImage\r
+        lea     ax, [Image]\r
+        push    es\r
+        push    ax                      ; Pointer to image\r
+        push    [X]\r
+        push    [Y]                     ; Image coordinates\r
+        push    [mx_FontWidth]\r
+        push    [mx_FontHeight]         ; Image size\r
+        push    [mx_FontOp]             ; Raster op\r
+        call    mxPutImage              ; Write character\r
+\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxOutChar       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a string at the coordinates specified.\r
+;\r
+; Input:\r
+;       X, Y    = text coordinates\r
+;       S       = pointer to ASCIIZ string\r
+; Output:\r
+;       none\r
+;\r
+mxOutText       PROC FAR\r
+        ARG     S:DWORD,        \\r
+                Y:WORD,         \\r
+                X:WORD          = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+        ASSUME  ds:NOTHING\r
+\r
+        lds     si, [S]\r
+@@Loop:\r
+        mov     al, ds:[si]\r
+        test    al, al                  ; End of string?\r
+        jz      @@Exit                  ; Yes, exit\r
+        inc     si\r
+        push    [X]                     ; Display character\r
+        push    [Y]\r
+        push    ax\r
+        call    mxOutChar\r
+        mov     ax, [mx_DeltaX]\r
+        add     [X], ax                 ; Bump X coordinate\r
+        mov     ax, [mx_DeltaY]\r
+        add     [Y], ax                 ; Bump Y coordinate\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+        ret\r
+mxOutText       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the distance between characters.\r
+;\r
+; Input:\r
+;       DeltaX  = horizontal distance in pixels\r
+;       DeltaY  = vertical distance in pixels\r
+; Output:\r
+;       none\r
+;\r
+; Note: this function may be used to set the text direction.\r
+;\r
+mxSetTextStep   PROC FAR\r
+        ARG     DeltaY:WORD,    \\r
+                DeltaX:WORD     = ARG_SIZE\r
+        .enter  0\r
+        .push   ds\r
+\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, [DeltaX]\r
+        mov     [mx_DeltaX], ax\r
+        mov     ax, [DeltaY]\r
+        mov     [mx_DeltaY], ax\r
+\r
+        .pop    ds\r
+        .leave  ARG_SIZE\r
+mxSetTextStep   ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Gets the current distance between characters.\r
+;\r
+; Input:\r
+;       DeltaX  = pointer to horizontal distance in pixels (integer)\r
+;       DeltaY  = pointer to vertical distance in pixels (integer)\r
+; Output:\r
+;       none\r
+;\r
+mxGetTextStep   PROC FAR\r
+        ARG     DeltaY:DWORD,   \\r
+                DeltaX:DWORD    = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+        ASSUME  ds:NOTHING\r
+\r
+        mov     ax, [mx_DeltaX]\r
+        lds     si, [DeltaX]\r
+        mov     ds:[si], ax\r
+        mov     ax, [mx_DeltaY]\r
+        lds     si, [DeltaY]\r
+        mov     ds:[si], ax\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetTextStep   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxpb.asm b/16/xw/mxpb.asm
new file mode 100755 (executable)
index 0000000..8c6aa44
--- /dev/null
@@ -0,0 +1,22 @@
+;-----------------------------------------------------------\r
+;\r
+; MXPB.ASM - Scan buffer for convex polygon fills\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mx_ScanBuffer\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+ALIGN   4\r
+\r
+mx_ScanBuffer   LABEL\r
+        DW      POLYSCANBUFSIZE DUP(?)\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxpf.asm b/16/xw/mxpf.asm
new file mode 100755 (executable)
index 0000000..db0da89
--- /dev/null
@@ -0,0 +1,420 @@
+;-----------------------------------------------------------\r
+;\r
+; MXPG.ASM - Convex polygon fill\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxFillPoly\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; "Local" definitions\r
+;\r
+TPOINT  STRUC\r
+        X       DW      ?\r
+        Y       DW      ?\r
+TPOINT  ENDS\r
+\r
+; Do NOT change order!\r
+TSCAN   STRUC\r
+        Y1      DW      ?\r
+        Y2      DW      ?\r
+TSCAN   ENDS\r
+\r
+MAXSCANCOLUMNS  EQU     POLYSCANBUFSIZE / SIZE TSCAN\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_CodeSegment  : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+EXTRN   mx_ScanBuffer   : NEAR\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Scans an edge using the DDA (digital differential analyzer) algorithm.\r
+;\r
+; Input:\r
+;       DS:BX   = pointer to start point (X1, Y1)\r
+;       DS:SI   = pointer to end point (X2, Y2)\r
+;       ES:DI   = pointer to edge buffer\r
+; Output:\r
+;       ES:DI   = updated pointer to edge buffer\r
+; Notes:\r
+;       must preserve DS:SI.\r
+;\r
+subScan         PROC NEAR\r
+        mov     cx, ds:[si].X\r
+        sub     cx, ds:[bx].X           ; Get width\r
+        jg      @@1\r
+        ret\r
+@@1:\r
+        push    bp                      ; Save BP\r
+\r
+        mov     ax, ds:[si].Y\r
+        mov     bx, ds:[bx].Y\r
+        sub     ax, bx                  ; Get height\r
+        jg      @@T2B                   ; Scan top to bottom\r
+        jl      @@B2T                   ; Scan bottom to top\r
+\r
+; Special case: vertical line\r
+        mov     ax, bx\r
+@@V:\r
+        mov     es:[di].Y1, ax\r
+        add     di, SIZE TSCAN\r
+        dec     cx\r
+       jnz     @@V\r
+        jmp     @@Exit\r
+\r
+; Scan top to bottom\r
+@@T2B:\r
+        cwd\r
+        div     cx\r
+        mov     bp, ax\r
+        xor     ax, ax\r
+        div     cx\r
+        xchg    ax, bx                  ; BP:BX = fixed 16:16 step\r
+        mov     dx, 8000h\r
+@@T2BLoop:\r
+        mov     es:[di].Y1, ax\r
+        add     di, SIZE TSCAN\r
+        add     dx, bx\r
+        adc     ax, bp\r
+        dec     cx\r
+        jnz     @@T2BLoop\r
+        jmp     @@Exit\r
+\r
+; Scan bottom to top\r
+@@B2T:\r
+        neg     ax\r
+        cwd\r
+        div     cx\r
+        mov     bp, ax\r
+        xor     ax, ax\r
+        div     cx\r
+        xchg    ax, bx\r
+        mov     dx, 8000h\r
+@@B2TLoop:\r
+        mov     es:[di].Y1, ax\r
+        add     di, SIZE TSCAN\r
+        sub     dx, bx\r
+        sbb     ax, bp\r
+        dec     cx\r
+        jnz     @@B2TLoop\r
+\r
+@@Exit:\r
+        pop     bp                      ; Restore BP\r
+        ret\r
+subScan         ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a convex polygon with the specified color.\r
+;\r
+; Input:\r
+;       Count   = number of vertexes\r
+;       Map     = indexes of points and colors (integer)\r
+;       Points  = array of points (integer X, Y coordinates)\r
+;       Color   = base color\r
+; Output:\r
+;       none\r
+; Notes:\r
+;       vertexes must be in counterclockwise order, arrays are 0-based.\r
+;\r
+mxFillPoly      PROC FAR\r
+        ARG     Color:WORD,     \\r
+                Points:DWORD,   \\r
+                Map:DWORD,      \\r
+                Count:WORD      = ARG_SIZE\r
+        LOCAL   WritePlane:BYTE:2,      \\r
+                ScanOffsetT:WORD,       \\r
+                ScanOffsetB:WORD,       \\r
+                ScanCount:WORD,         \\r
+                Holder:WORD,            \\r
+                Height:WORD,            \\r
+                MinIdxT:WORD,           \\r
+                MinIdxB:WORD,           \\r
+                MaxIdx:WORD,            \\r
+                Width:WORD,             \\r
+                BoxX1:WORD,             \\r
+                BoxY1:WORD,             \\r
+                BoxX2:WORD,             \\r
+                BoxY2::WORD             = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+        ASSUME  ds:NOTHING\r
+\r
+; Check that at least three vertexes are specified\r
+        mov     cx, [Count]\r
+        cmp     cx, 3\r
+        jb      @@Exit\r
+\r
+;------------------------------\r
+; Find bounding box for polygon\r
+        les     di, [Map]\r
+        lds     si, [Points]            ; Pointer to vertex array\r
+        mov     [BoxX1], 32767\r
+        mov     [BoxX2], -32768\r
+        mov     [BoxY1], 32767\r
+        mov     [BoxY2], -32768\r
+\r
+        xor     dx, dx\r
+@@MinMaxLoop:\r
+        mov     bx, es:[di]             ; Get index of vertex\r
+        .shl    bx, 2                   ; Get offset in point array\r
+        add     bx, si\r
+\r
+; Check X range\r
+@@CheckMinX:\r
+        mov     ax, ds:[bx].X           ; Get X coordinate\r
+        cmp     ax, [BoxX1]\r
+        jge     @@CheckMaxX\r
+        mov     [BoxX1], ax\r
+        mov     [MinIdxT], dx\r
+        mov     [MinIdxB], dx\r
+@@CheckMaxX:\r
+        cmp     ax, [BoxX2]\r
+        jle     @@CheckMinY\r
+        mov     [BoxX2], ax\r
+        mov     [MaxIdx], dx\r
+\r
+; Check Y range\r
+@@CheckMinY:\r
+        mov     ax, ds:[bx].Y\r
+        cmp     ax, [BoxY1]\r
+        jge     @@CheckMaxY\r
+        mov     [BoxY1], ax\r
+@@CheckMaxY:\r
+        cmp     ax, [BoxY2]\r
+        jle     @@CheckDone\r
+        mov     [BoxY2], ax\r
+\r
+; Repeat thru all points\r
+@@CheckDone:\r
+        inc     di                      ; Next map entry\r
+        inc     dx\r
+        inc     di\r
+        inc     dx\r
+        dec     cx\r
+        jnz     @@MinMaxLoop\r
+\r
+;---------------------------------\r
+; Check if polygon is full clipped\r
+        mov     ax, [BoxX2]\r
+        cmp     ax, [mx_ClipX1]         ; Is poly full clipped?\r
+        jl      @@Exit\r
+        mov     bx, [BoxX1]\r
+        cmp     bx, [mx_ClipX2]         ; Is poly full clipped?\r
+        jg      @@Exit\r
+        sub     ax, bx                  ; Get width\r
+        jle     @@Exit                  ; Exit if not positive\r
+        mov     ax, [BoxY2]\r
+        cmp     ax, [mx_ClipY1]         ; Is poly full clipped?\r
+        jl      @@Exit\r
+        mov     bx, [BoxY1]\r
+        cmp     bx, [mx_ClipY2]         ; Is poly full clipped?\r
+        jg      @@Exit\r
+        sub     ax, bx                  ; Get height\r
+        jle     @@Exit                  ; Exit if not positive\r
+\r
+        dec     [Count]\r
+        shl     [Count], 1              ; We'll work with word offsets\r
+        mov     es, [mx_CodeSegment]\r
+\r
+;--------------\r
+; Scan top edge\r
+        mov     ax, OFFSET mx_ScanBuffer\r
+        mov     [ScanOffsetT], ax\r
+        mov     si, [MinIdxT]           ; Offset of bottom point index\r
+@@STLoop:\r
+        lds     bx, [Map]               ; DS:BX -> map table\r
+        mov     di, ds:[bx+si]          ; Index of top point #1\r
+        dec     si                      ; Next point\r
+        dec     si\r
+        test    si, si\r
+        jnl     @@ST1\r
+        mov     si, [Count]\r
+@@ST1:\r
+        mov     [MinIdxT], si           ; Save new index of top point\r
+        mov     si, ds:[bx+si]          ; Get index of top point #2\r
+        .shl    di, 2                   ; Convert indexes to offsets\r
+        .shl    si, 2\r
+        lds     bx, [Points]            ; DS:BX -> point array\r
+        add     si, bx                  ; DS:SI -> top point #2\r
+        add     bx, di                  ; DS:BX -> top point #1\r
+        mov     di, [ScanOffsetT]\r
+        call    subScan                 ; Scan edge\r
+        mov     [ScanOffsetT], di\r
+        mov     si, [MinIdxT]\r
+        cmp     si, [MaxIdx]            ; End of edge?\r
+        jne     @@STLoop                ; No, continue\r
+\r
+;-----------------\r
+; Scan bottom edge\r
+        mov     ax, OFFSET mx_ScanBuffer + OFFSET Y2\r
+        mov     [ScanOffsetB], ax\r
+        mov     si, [MinIdxB]           ; Offset of bottom point index\r
+@@SBLoop:\r
+        lds     bx, [Map]               ; DS:BX -> map table\r
+        mov     di, ds:[bx+si]          ; Index of bottom point #1\r
+        inc     si                      ; Next bottom point\r
+        inc     si\r
+        cmp     si, [Count]\r
+        jbe     @@SB1\r
+        xor     si, si\r
+@@SB1:\r
+        mov     [MinIdxB], si           ; Save new index of bottom point\r
+        mov     si, ds:[bx+si]          ; Get index of bottom point #2\r
+        .shl    di, 2                   ; Convert indexes to offsets\r
+        .shl    si, 2\r
+        lds     bx, [Points]            ; DS:BX -> point array\r
+        add     si, bx                  ; DS:SI -> top point #2\r
+        add     bx, di                  ; DS:BX -> top point #1\r
+        mov     di, [ScanOffsetB]\r
+        call    subScan                 ; Scan edge\r
+        mov     [ScanOffsetB], di\r
+        mov     si, [MinIdxB]\r
+        cmp     si, [MaxIdx]            ; End of edge?\r
+        jne     @@SBLoop                ; No, continue\r
+\r
+;--------------------\r
+; Clip left and right\r
+        mov     si, OFFSET mx_ScanBuffer\r
+        mov     ax, [BoxX1]\r
+        mov     cx, [BoxX2]\r
+        sub     cx, ax                  ; CX = bounding box width\r
+        mov     bx, [mx_ClipX1]\r
+        sub     bx, ax\r
+        jle     @@ClipL1                ; No need to clip left\r
+        sub     cx, bx                  ; Update width\r
+        add     ax, bx                  ; BoxX1 = mx_ClipX1\r
+        mov     [BoxX1], ax\r
+        .shl    bx, 2                   ; Warning!!! This is an hand-coded\r
+        add     si, bx                  ; multiply by the size of TSCAN\r
+@@ClipL1:\r
+        mov     bx, ax\r
+        add     bx, cx                  ; Last scan column\r
+        sub     bx, [mx_ClipX2]\r
+        jle     @@ClipL2                ; No need to clip right\r
+        sub     cx, bx                  ; Clip right\r
+@@ClipL2:\r
+        test    cx, cx                  ; Is clipped width positive?\r
+        jle     @@Exit                  ; No, exit\r
+        mov     [ScanCount], cx         ; Save number of columns to draw\r
+        mov     [ScanOffsetT], si       ; Remember offset of (clipped) buffer\r
+        mov     ds, [mx_CodeSegment]    ; DS:SI -> scan buffer\r
+\r
+;------------------------------\r
+; Check if Y clipping is needed\r
+        mov     ax, [BoxY1]\r
+        cmp     ax, [mx_ClipY1]\r
+        jl      @@ClipTB                ; Need to clip top\r
+        mov     ax, [BoxY2]\r
+        cmp     ax, [mx_ClipY2]\r
+        jg      @@ClipTB                ; Need to clip bottom\r
+        jmp     @@ClipYExit             ; Skip Y clipping\r
+\r
+;--------------------\r
+; Clip top and bottom\r
+@@ClipTB:\r
+        mov     di, cx                  ; DI = scan count\r
+        inc     di                      ; Increment count for pre-loop test\r
+        sub     si, SIZE TSCAN\r
+@@ClipYLoop:\r
+        dec     di                      ; Any column left?\r
+        jz      @@ClipYExit             ; No, exit\r
+        add     si, SIZE TSCAN\r
+        mov     ax, ds:[si].Y1          ; Y1\r
+        mov     cx, ds:[si].Y2          ; Y2\r
+        mov     dx, [mx_ClipY2]\r
+        cmp     ax, dx                  ; Full clipped?\r
+        jg      @@ClipYClip             ; Yes, skip this column\r
+        cmp     cx, dx                  ; Need to clip bottom?\r
+        jle     @@ClipY1                ; No, continue\r
+; Clip bottom\r
+        mov     ds:[si].Y2, dx\r
+        mov     bx, cx\r
+        sub     bx, dx                  ; Clip distance\r
+        sub     cx, ax                  ; Height\r
+        jle     @@ClipYClip\r
+        mov     cx, ds:[si].Y2\r
+@@ClipY1:\r
+        mov     dx, [mx_ClipY1]\r
+        cmp     cx, dx                  ; Full top clipped?\r
+        jl      @@ClipYClip             ; Yes, skip\r
+        sub     cx, ax                  ; Get height\r
+        jle     @@ClipYClip             ; Skip if not positive\r
+        cmp     ax, dx                  ; Need to clip top?\r
+        jge     @@ClipYLoop             ; No, continue\r
+; Clip top\r
+        mov     ds:[si].Y1, dx          ; Y1 = mx_ClipY1\r
+        sub     dx, ax                  ; DX = number of pixels clipped\r
+        cmp     cx, dx\r
+        ja      @@ClipYLoop             ; Not clipped, continue\r
+@@ClipYClip:\r
+        mov     ds:[si].Y1, -1          ; Mark column as clipped\r
+        jmp     @@ClipYLoop\r
+@@ClipYExit:\r
+\r
+;-------------\r
+; Draw columns\r
+        mov     es, [mx_VideoSegment]\r
+        mov     si, [ScanOffsetT]\r
+        mov     cl, BYTE PTR [BoxX1]    ; Init write plane\r
+        and     cl, 03h\r
+        mov     al, 11h\r
+        shl     al, cl\r
+        mov     [WritePlane], al\r
+        .shr    [BoxX1], 2\r
+@@DrawLoop:\r
+        mov     ax, ds:[si].Y1\r
+        test    ax, ax                  ; Was column clipped?\r
+        js      @@DrawNext              ; Yes, skip\r
+        mov     cx, ds:[si].Y2\r
+        sub     cx, ax                  ; CX = height\r
+        jle     @@DrawNext\r
+        mul     [mx_BytesPerLine]       ; Get pixel address\r
+        add     ax, [BoxX1]\r
+        mov     di, ax\r
+        mov     ah, [WritePlane]\r
+        mov     dx, TS\r
+        mov     al, 02h\r
+        out     dx, ax\r
+        mov     ax, [Color]\r
+        mov     dx, [mx_BytesPerLine]\r
+        shr     cx, 1\r
+        jnc     @@FillScan\r
+        mov     es:[di], al\r
+        add     di, dx\r
+        jcxz    @@DrawNext\r
+@@FillScan:\r
+        mov     es:[di], al\r
+        add     di, dx\r
+        mov     es:[di], al\r
+        add     di, dx\r
+        dec     cx\r
+        jnz     @@FillScan\r
+@@DrawNext:\r
+        rol     [WritePlane], 1\r
+        adc     [BoxX1], 0              ; Bump pointer to video memory if needed\r
+        add     si, SIZE TSCAN\r
+        dec     [ScanCount]\r
+        jnz     @@DrawLoop\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxFillPoly      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxpg.asm b/16/xw/mxpg.asm
new file mode 100755 (executable)
index 0000000..caa7cf1
--- /dev/null
@@ -0,0 +1,589 @@
+;-----------------------------------------------------------\r
+;\r
+; MXPG.ASM - Convex polygon fill with Gouraud shading\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxGouraudPoly\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; "Local" definitions\r
+;\r
+TPOINT  STRUC\r
+        X       DW      ?\r
+        Y       DW      ?\r
+TPOINT  ENDS\r
+\r
+; Do NOT change order!\r
+TSCAN   STRUC\r
+        Y1      DW      ?\r
+        E1      DB      ?\r
+        C1      DB      ?\r
+        Y2      DW      ?\r
+        E2      DB      ?\r
+        C2      DB      ?\r
+TSCAN   ENDS\r
+\r
+MAXSCANCOLUMNS  EQU     POLYSCANBUFSIZE / SIZE TSCAN\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_CodeSegment  : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+EXTRN   mx_ScanBuffer   : NEAR\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Scans an edge using the DDA (digital differential analyzer) algorithm.\r
+; Also interpolates color for shading.\r
+;\r
+; Input:\r
+;       DS:BX   = pointer to start point (X1, Y1)\r
+;       DS:SI   = pointer to end point (X2, Y2)\r
+;       ES:DI   = pointer to edge buffer\r
+;       DX      = start color\r
+;       AX      = end color\r
+; Output:\r
+;       ES:DI   = updated pointer to edge buffer\r
+; Notes:\r
+;       must preserve DS:SI.\r
+;\r
+subScan         PROC NEAR\r
+        mov     cx, ds:[si].X\r
+        sub     cx, ds:[bx].X           ; Get width\r
+        jg      @@1\r
+        ret\r
+@@1:\r
+        push    bp                      ; Save BP\r
+        push    di                      ; Save scan info offset\r
+        push    cx                      ; Save height\r
+        push    ax                      ; Save colors\r
+        push    dx\r
+\r
+        mov     ax, ds:[si].Y\r
+        mov     bx, ds:[bx].Y\r
+        sub     ax, bx                  ; Get height\r
+        jg      @@T2B                   ; Scan top to bottom\r
+        jl      @@B2T                   ; Scan bottom to top\r
+\r
+; Special case: vertical line\r
+        mov     ax, bx\r
+@@V:\r
+        mov     es:[di].Y1, ax\r
+        add     di, SIZE TSCAN\r
+        dec     cx\r
+       jnz     @@V\r
+        jmp     @@GetColorInfo\r
+\r
+; Scan top to bottom\r
+@@T2B:\r
+        cwd\r
+        div     cx\r
+        mov     bp, ax\r
+        xor     ax, ax\r
+        div     cx\r
+        xchg    ax, bx                  ; BP:BX = fixed 16:16 step\r
+        mov     dx, 8000h\r
+@@T2BLoop:\r
+        mov     es:[di].Y1, ax\r
+        add     di, SIZE TSCAN\r
+        add     dx, bx\r
+        adc     ax, bp\r
+        dec     cx\r
+        jnz     @@T2BLoop\r
+        jmp     @@GetColorInfo\r
+\r
+; Scan bottom to top\r
+@@B2T:\r
+        neg     ax\r
+        cwd\r
+        div     cx\r
+        mov     bp, ax\r
+        xor     ax, ax\r
+        div     cx\r
+        xchg    ax, bx\r
+        mov     dx, 8000h\r
+@@B2TLoop:\r
+        mov     es:[di].Y1, ax\r
+        add     di, SIZE TSCAN\r
+        sub     dx, bx\r
+        sbb     ax, bp\r
+        dec     cx\r
+        jnz     @@B2TLoop\r
+\r
+; Now get the color info\r
+@@GetColorInfo:\r
+        pop     bx                      ; Restore colors\r
+        pop     ax\r
+        pop     cx                      ; Height\r
+        pop     di                      ; ES:DI -> scan info\r
+\r
+        sub     ax, bx                  ; Get color range\r
+        jg      @@CL2R\r
+        jl      @@CR2L\r
+\r
+; Special case: same color\r
+        mov     ah, bl\r
+        mov     al, 80h\r
+@@CV:\r
+        mov     WORD PTR es:[di].E1, ax\r
+        add     di, SIZE TSCAN\r
+        dec     cx\r
+        jnz     @@CV\r
+        jmp     @@Exit\r
+\r
+; Scan left to right\r
+@@CL2R:\r
+        cwd\r
+        div     cx\r
+        mov     bp, ax\r
+        xor     ax, ax\r
+        div     cx\r
+        xchg    ax, bx                  ; BP:BX = fixed 16:16 step\r
+        mov     dx, 8000h\r
+@@CL2RLoop:\r
+        mov     es:[di].C1, al\r
+        mov     es:[di].E1, dh\r
+        add     di, SIZE TSCAN\r
+        add     dx, bx\r
+        adc     ax, bp\r
+        dec     cx\r
+        jnz     @@CL2RLoop\r
+        jmp     @@Exit\r
+\r
+; Scan right to left\r
+@@CR2L:\r
+        neg     ax\r
+        cwd\r
+        div     cx\r
+        mov     bp, ax\r
+        xor     ax, ax\r
+        div     cx\r
+        xchg    ax, bx\r
+        mov     dx, 8000h\r
+\r
+@@CR2LLoop:\r
+        mov     es:[di].C1, al\r
+        mov     es:[di].E1, dh\r
+        add     di, SIZE TSCAN\r
+        sub     dx, bx\r
+        sbb     ax, bp\r
+        dec     cx\r
+        jnz     @@CR2LLoop\r
+\r
+@@Exit:\r
+        pop     bp\r
+        ret\r
+subScan         ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a scan column.\r
+;\r
+; Input:\r
+;       DS:SI   = current TSCAN\r
+;       ES:DI   = address of top pixel\r
+;       CX      = number of pixels to write\r
+;       DX      = base color\r
+; Output:\r
+;       none\r
+;\r
+subFillScan     PROC NEAR\r
+        mov     ax, WORD PTR ds:[si].E2\r
+        mov     bx, WORD PTR ds:[si].E1\r
+        cmp     ah, bh\r
+        jg      @@L2R                   ; Color increases\r
+        jl      @@R2L                   ; Color decreases\r
+\r
+; Special case: color doesn't change\r
+        add     ax, dx\r
+        mov     dx, [mx_BytesPerLine]\r
+@@V:\r
+        mov     es:[di], ah\r
+        add     di, dx\r
+        dec     cx\r
+        jnz     @@V\r
+        ret\r
+\r
+; Color increases\r
+@@L2R:\r
+        .push   bp, si\r
+        mov     si, bx\r
+        add     si, dx                  ; Relocate color\r
+        sub     ax, bx\r
+        xor     dx, dx\r
+        div     cx\r
+        mov     bp, ax                  ; BP = color step, integer part\r
+        xor     ax, ax\r
+        div     cx\r
+        mov     bx, ax                  ; BX = color step, fractional part\r
+        mov     dx, 8000h\r
+        mov     ax, [mx_BytesPerLine]\r
+        xchg    si, ax\r
+@@L2RLoop:\r
+        mov     es:[di], ah\r
+        add     dx, bx\r
+        adc     ax, bp\r
+        add     di, si\r
+        dec     cx\r
+        jnz     @@L2RLoop\r
+        .pop    bp, si\r
+        ret\r
+\r
+; Color decreases\r
+@@R2L:\r
+        .push   bp, si\r
+        mov     si, bx\r
+        add     si, dx                  ; Relocate color\r
+        sub     ax, bx\r
+        neg     ax\r
+        xor     dx, dx\r
+        div     cx\r
+        mov     bp, ax                  ; BP = color step, integer part\r
+        xor     ax, ax\r
+        div     cx\r
+        mov     bx, ax                  ; BX = color step, fractional part\r
+        mov     dx, 8000h\r
+        mov     ax, [mx_BytesPerLine]\r
+        xchg    si, ax\r
+@@R2LLoop:\r
+        mov     es:[di], ah\r
+        sub     dx, bx\r
+        sbb     ax, bp\r
+        add     di, si\r
+        dec     cx\r
+        jnz     @@R2LLoop\r
+        .pop    bp, si\r
+        ret\r
+subFillScan     ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Fills a convex polygon with the specified color.\r
+; Interpolates pixel colors using the Gouraud algorithm.\r
+;\r
+; Input:\r
+;       Count   = number of vertexes\r
+;       Map     = indexes of points and colors (integer)\r
+;       Points  = array of points (integer X, Y coordinates)\r
+;       Colors  = array of colors (integer)\r
+;       Color   = base color\r
+; Output:\r
+;       none\r
+; Notes:\r
+;       vertexes must be in counterclockwise order, arrays are 0-based.\r
+;\r
+mxGouraudPoly  PROC FAR\r
+        ARG     Color:WORD,     \\r
+                Colors:DWORD,   \\r
+                Points:DWORD,   \\r
+                Map:DWORD,      \\r
+                Count:WORD      = ARG_SIZE\r
+        LOCAL   WritePlane:BYTE:2,      \\r
+                ScanOffsetT:WORD,       \\r
+                ScanOffsetB:WORD,       \\r
+                ScanCount:WORD,         \\r
+                Holder:WORD,            \\r
+                Height:WORD,            \\r
+                MinIdxT:WORD,           \\r
+                MinIdxB:WORD,           \\r
+                MaxIdx:WORD,            \\r
+                Width:WORD,             \\r
+                BoxX1:WORD,             \\r
+                BoxY1:WORD,             \\r
+                BoxX2:WORD,             \\r
+                BoxY2::WORD             = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+        ASSUME  ds:NOTHING\r
+\r
+; Check that at least three vertexes are specified\r
+        mov     cx, [Count]\r
+        cmp     cx, 3\r
+        jb      @@Exit\r
+\r
+;------------------------------\r
+; Find bounding box for polygon\r
+        les     di, [Map]\r
+        lds     si, [Points]            ; Pointer to vertex array\r
+        mov     [BoxX1], 32767\r
+        mov     [BoxX2], -32768\r
+        mov     [BoxY1], 32767\r
+        mov     [BoxY2], -32768\r
+\r
+        xor     dx, dx\r
+@@MinMaxLoop:\r
+        mov     bx, es:[di]             ; Get index of vertex\r
+        .shl    bx, 2                   ; Get offset in point array\r
+        add     bx, si\r
+\r
+; Check X range\r
+@@CheckMinX:\r
+        mov     ax, ds:[bx].X           ; Get X coordinate\r
+        cmp     ax, [BoxX1]\r
+        jge     @@CheckMaxX\r
+        mov     [BoxX1], ax\r
+        mov     [MinIdxT], dx\r
+        mov     [MinIdxB], dx\r
+@@CheckMaxX:\r
+        cmp     ax, [BoxX2]\r
+        jle     @@CheckMinY\r
+        mov     [BoxX2], ax\r
+        mov     [MaxIdx], dx\r
+\r
+; Check Y range\r
+@@CheckMinY:\r
+        mov     ax, ds:[bx].Y\r
+        cmp     ax, [BoxY1]\r
+        jge     @@CheckMaxY\r
+        mov     [BoxY1], ax\r
+@@CheckMaxY:\r
+        cmp     ax, [BoxY2]\r
+        jle     @@CheckDone\r
+        mov     [BoxY2], ax\r
+\r
+; Repeat thru all points\r
+@@CheckDone:\r
+        inc     di                      ; Next map entry\r
+        inc     di\r
+        inc     dx\r
+        inc     dx\r
+        dec     cx\r
+        jnz     @@MinMaxLoop\r
+\r
+;---------------------------------\r
+; Check if polygon is full clipped\r
+        mov     ax, [BoxX2]\r
+        cmp     ax, [mx_ClipX1]         ; Is poly full clipped?\r
+        jl      @@Exit\r
+        mov     bx, [BoxX1]\r
+        cmp     bx, [mx_ClipX2]         ; Is poly full clipped?\r
+        jg      @@Exit\r
+        sub     ax, bx                  ; Get width\r
+        jle     @@Exit                  ; Exit if not positive\r
+        mov     ax, [BoxY2]\r
+        cmp     ax, [mx_ClipY1]         ; Is poly full clipped?\r
+        jl      @@Exit\r
+        mov     bx, [BoxY1]\r
+        cmp     bx, [mx_ClipY2]         ; Is poly full clipped?\r
+        jg      @@Exit\r
+        sub     ax, bx                  ; Get height\r
+        jle     @@Exit                  ; Exit if not positive\r
+\r
+        dec     [Count]\r
+        shl     [Count], 1              ; We'll work with word offsets\r
+        mov     es, [mx_CodeSegment]\r
+\r
+;--------------\r
+; Scan top edge\r
+        mov     ax, OFFSET mx_ScanBuffer\r
+        mov     [ScanOffsetT], ax\r
+        mov     si, [MinIdxT]           ; Offset of bottom point index\r
+@@STLoop:\r
+        lds     bx, [Map]               ; DS:BX -> map table\r
+        mov     di, ds:[bx+si]          ; Index of top point #1\r
+        dec     si                      ; Next point\r
+        dec     si\r
+        test    si, si\r
+        jnl     @@ST1\r
+        mov     si, [Count]\r
+@@ST1:\r
+        mov     [MinIdxT], si           ; Save new index of top point\r
+        mov     si, ds:[bx+si]          ; Get index of top point #2\r
+        lds     bx, [Colors]            ; Get pointer to color array\r
+        shl     di, 1                   ; Convert indexes to offsets\r
+        shl     si, 1\r
+        mov     ax, ds:[bx+si]          ; Get colors\r
+        mov     dx, ds:[bx+di]\r
+        lds     bx, [Points]            ; DS:BX -> point array\r
+        shl     si, 1\r
+        shl     di, 1\r
+        add     si, bx                  ; DS:SI -> top point #2\r
+        add     bx, di                  ; DS:BX -> top point #1\r
+        mov     di, [ScanOffsetT]\r
+        call    subScan                 ; Scan edge\r
+        mov     [ScanOffsetT], di\r
+        mov     si, [MinIdxT]\r
+        cmp     si, [MaxIdx]            ; End of edge?\r
+        jne     @@STLoop                ; No, continue\r
+\r
+;-----------------\r
+; Scan bottom edge\r
+        mov     ax, OFFSET mx_ScanBuffer + OFFSET Y2\r
+        mov     [ScanOffsetB], ax\r
+        mov     si, [MinIdxB]           ; Offset of bottom point index\r
+@@SBLoop:\r
+        lds     bx, [Map]               ; DS:BX -> map table\r
+        mov     di, ds:[bx+si]          ; Index of bottom point #1\r
+        inc     si                      ; Next bottom point\r
+        inc     si\r
+        cmp     si, [Count]\r
+        jbe     @@SB1\r
+        xor     si, si\r
+@@SB1:\r
+        mov     [MinIdxB], si           ; Save new index of bottom point\r
+        mov     si, ds:[bx+si]          ; Get index of bottom point #2\r
+        lds     bx, [Colors]            ; Get pointer to color array\r
+        shl     di, 1                   ; Convert indexes to offsets\r
+        shl     si, 1\r
+        mov     ax, ds:[bx+si]          ; Get colors\r
+        mov     dx, ds:[bx+di]\r
+        lds     bx, [Points]            ; DS:BX -> point array\r
+        shl     si, 1\r
+        shl     di, 1\r
+        add     si, bx                  ; DS:SI -> top point #2\r
+        add     bx, di                  ; DS:BX -> top point #1\r
+        mov     di, [ScanOffsetB]\r
+        call    subScan                 ; Scan edge\r
+        mov     [ScanOffsetB], di\r
+        mov     si, [MinIdxB]\r
+        cmp     si, [MaxIdx]            ; End of edge?\r
+        jne     @@SBLoop                ; No, continue\r
+\r
+;--------------------\r
+; Clip left and right\r
+        mov     si, OFFSET mx_ScanBuffer\r
+        mov     ax, [BoxX1]\r
+        mov     cx, [BoxX2]\r
+        sub     cx, ax                  ; CX = bounding box width\r
+        mov     bx, [mx_ClipX1]\r
+        sub     bx, ax\r
+        jle     @@ClipL1                ; No need to clip left\r
+        sub     cx, bx                  ; Update width\r
+        add     ax, bx                  ; BoxX1 = mx_ClipX1\r
+        mov     [BoxX1], ax\r
+        .shl    bx, 3                   ; Warning!!! This is an hand-coded\r
+        add     si, bx                  ; multiply by the size of TSCAN\r
+@@ClipL1:\r
+        mov     bx, ax\r
+        add     bx, cx                  ; Last scan column\r
+        sub     bx, [mx_ClipX2]\r
+        jle     @@ClipL2                ; No need to clip right\r
+        sub     cx, bx                  ; Clip right\r
+@@ClipL2:\r
+        test    cx, cx                  ; Is clipped width positive?\r
+        jle     @@Exit                  ; No, exit\r
+        mov     [ScanCount], cx         ; Save number of columns to draw\r
+        mov     [ScanOffsetT], si       ; Remember offset of (clipped) buffer\r
+        mov     ds, [mx_CodeSegment]    ; DS:SI -> scan buffer\r
+\r
+;------------------------------\r
+; Check if Y clipping is needed\r
+        mov     ax, [BoxY1]\r
+        cmp     ax, [mx_ClipY1]\r
+        jl      @@ClipTB                ; Need to clip top\r
+        mov     ax, [BoxY2]\r
+        cmp     ax, [mx_ClipY2]\r
+        jg      @@ClipTB                ; Need to clip bottom\r
+        jmp     @@ClipYExit             ; Skip Y clipping\r
+\r
+;--------------------\r
+; Clip top and bottom\r
+@@ClipTB:\r
+        mov     di, cx                  ; DI = scan count\r
+        inc     di                      ; Increment count for pre-loop test\r
+        sub     si, SIZE TSCAN\r
+@@ClipYLoop:\r
+        dec     di                      ; Any column left?\r
+        jz      @@ClipYExit             ; No, exit\r
+        add     si, SIZE TSCAN\r
+        mov     ax, ds:[si].Y1          ; Y1\r
+        mov     cx, ds:[si].Y2          ; Y2\r
+        mov     dx, [mx_ClipY2]\r
+        cmp     ax, dx                  ; Full clipped?\r
+        jg      @@ClipYClip             ; Yes, skip this column\r
+        cmp     cx, dx                  ; Need to clip bottom?\r
+        jle     @@ClipY1                ; No, continue\r
+; Clip bottom, need to scale colors too\r
+        mov     ds:[si].Y2, dx\r
+        mov     bx, cx\r
+        sub     bx, dx                  ; Clip distance\r
+        sub     cx, ax                  ; Height\r
+        jle     @@ClipYClip\r
+        mov     ax, WORD PTR ds:[si].E1\r
+        sub     ax, WORD PTR ds:[si].E2\r
+        imul    bx\r
+        idiv    cx\r
+        add     WORD PTR ds:[si].E2, ax\r
+        mov     ax, ds:[si].Y1          ; Restore AX and CX\r
+        mov     cx, ds:[si].Y2\r
+@@ClipY1:\r
+        mov     dx, [mx_ClipY1]\r
+        cmp     cx, dx                  ; Full top clipped?\r
+        jl      @@ClipYClip             ; Yes, skip\r
+        sub     cx, ax                  ; Get height\r
+        jle     @@ClipYClip             ; Skip if not positive\r
+        cmp     ax, dx                  ; Need to clip top?\r
+        jge     @@ClipYLoop             ; No, continue\r
+; Clip top, need to scale colors too\r
+        mov     ds:[si].Y1, dx          ; Y1 = mx_ClipY1\r
+        sub     dx, ax                  ; DX = number of pixels clipped\r
+        cmp     cx, dx\r
+        jbe     @@ClipYClip             ; Full clipped, skip\r
+        mov     ax, WORD PTR ds:[si].E2\r
+        sub     ax, WORD PTR ds:[si].E1 ; AX = color distance\r
+        imul    dx\r
+        idiv    cx\r
+        add     WORD PTR ds:[si].E1, ax ; Update starting color\r
+        jmp     @@ClipYLoop\r
+@@ClipYClip:\r
+        mov     ds:[si].Y1, -1          ; Mark column as clipped\r
+        jmp     @@ClipYLoop\r
+@@ClipYExit:\r
+\r
+;-------------\r
+; Draw columns\r
+        mov     es, [mx_VideoSegment]\r
+        mov     si, [ScanOffsetT]\r
+        mov     cl, BYTE PTR [BoxX1]    ; Init write plane\r
+        and     cl, 03h\r
+        mov     al, 11h\r
+        shl     al, cl\r
+        mov     [WritePlane], al\r
+        .shr    [BoxX1], 2\r
+        mov     ax, [Color]             ; Make 8:8 fixed color\r
+        mov     ah, al\r
+        xor     al, al\r
+        mov     [Color], ax\r
+@@DrawLoop:\r
+        mov     ax, ds:[si].Y1\r
+        test    ax, ax                  ; Was column clipped?\r
+        js      @@DrawNext              ; Yes, skip\r
+        mov     cx, ds:[si].Y2\r
+        sub     cx, ax                  ; CX = height\r
+        jle     @@DrawNext\r
+        mul     [mx_BytesPerLine]       ; Get pixel address\r
+        add     ax, [BoxX1]\r
+        mov     di, ax\r
+        mov     ah, [WritePlane]\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax\r
+        mov     dx, [Color]\r
+        call    subFillScan\r
+@@DrawNext:\r
+        rol     [WritePlane], 1\r
+        adc     [BoxX1], 0              ; Bump pointer to video memory if needed\r
+        add     si, SIZE TSCAN\r
+        dec     [ScanCount]\r
+        jnz     @@DrawLoop\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxGouraudPoly  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxpi.asm b/16/xw/mxpi.asm
new file mode 100755 (executable)
index 0000000..9e8525f
--- /dev/null
@@ -0,0 +1,267 @@
+;-----------------------------------------------------------\r
+;\r
+; MXPI.ASM - Put image\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxPutImage\r
+\r
+EXTRN   subClipImage            : NEAR\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+mxTable LABEL   WORD                    ; Raster ops\r
+        DW      subMove\r
+        DW      subAnd\r
+        DW      subOr\r
+        DW      subXor\r
+        DW      subTrans\r
+        DW      subAdd\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Move functions.\r
+; Note: loops unrolled and optimized for CX even, no check for CX = 0.\r
+;\r
+subMove         PROC    NEAR\r
+        shr     cx, 1                   ; Make CX even\r
+        jc      @@Odd                   ; Special case if odd byte\r
+@@Loop: movsb\r
+        add     si, 3\r
+        movsb\r
+        add     si, 3\r
+        dec     cx\r
+        jnz     @@Loop\r
+@@Exit: ret\r
+@@Odd:  movsb\r
+        add     si, 3\r
+        jcxz    @@Exit\r
+        jmp     @@Loop\r
+subMove         ENDP\r
+;\r
+subAnd          PROC     NEAR\r
+        shr     cx, 1\r
+        jc      @@Odd\r
+@@Loop: mov     al, ds:[si]\r
+        mov     ah, ds:[si+4]\r
+        and     es:[di], ax\r
+        inc     di\r
+        inc     di\r
+        add     si, 8\r
+        dec     cx\r
+        jnz     @@Loop\r
+@@Exit: ret\r
+@@Odd:  lodsb\r
+        and     es:[di], al\r
+        inc     di\r
+        add     si, 3\r
+        jcxz    @@Exit\r
+        jmp     @@Loop\r
+subAnd          ENDP\r
+;\r
+subOr           PROC     NEAR\r
+        shr     cx, 1\r
+        jc      @@Odd\r
+@@Loop: mov     al, ds:[si]\r
+        mov     ah, ds:[si+4]\r
+        or      es:[di], ax\r
+        inc     di\r
+        inc     di\r
+        add     si, 8\r
+        dec     cx\r
+        jnz     @@Loop\r
+@@Exit: ret\r
+@@Odd:  lodsb\r
+        or      es:[di], al\r
+        inc     di\r
+        add     si, 3\r
+        jcxz    @@Exit\r
+        jmp     @@Loop\r
+subOr           ENDP\r
+;\r
+subXor          PROC     NEAR\r
+        shr     cx, 1\r
+        jc      @@Odd\r
+@@Loop: mov     al, ds:[si]\r
+        mov     ah, ds:[si+4]\r
+        xor     es:[di], ax\r
+        inc     di\r
+        inc     di\r
+        add     si, 8\r
+        dec     cx\r
+        jnz     @@Loop\r
+@@Exit: ret\r
+@@Odd:  lodsb\r
+        xor     es:[di], al\r
+        inc     di\r
+        add     si, 3\r
+        jcxz    @@Exit\r
+        jmp     @@Loop\r
+subXor          ENDP\r
+;\r
+subTrans        PROC     NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        cmp     al, ah\r
+        je      @@Skip\r
+        mov     es:[di], al\r
+@@Skip: inc     di\r
+        add     si, 4\r
+        dec     cx\r
+        jnz     @@Loop\r
+@@Exit: ret\r
+subTrans        ENDP\r
+;\r
+subAdd          PROC     NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        add     es:[di], al\r
+        inc     di\r
+        add     si, 4\r
+        dec     cx\r
+        jnz     @@Loop\r
+        ret\r
+subAdd          ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies a "raw" image from memory to screen.\r
+;\r
+; Input:\r
+;       Image   = pointer to image\r
+;       X, Y    = coordinates of destination\r
+;       Width   = width of image in pixels\r
+;       Height  = height of image in pixels\r
+;       Op      = raster op (OP_xxx)\r
+; Output:\r
+;       none\r
+;\r
+mxPutImage      PROC    FAR\r
+        ARG     Op:WORD,                \\r
+                Height:WORD,            \\r
+                Width:WORD,             \\r
+                Y:WORD,                 \\r
+                X:WORD,                 \\r
+                Image:DWORD             = ARG_SIZE\r
+        LOCAL   PlaneWidth:WORD:4,      \\r
+                PixelOffset:WORD,       \\r
+                MoveFunction:WORD,      \\r
+                Count:BYTE,             \\r
+                ReadPlane:BYTE,         \\r
+                OpInfo:BYTE,            \\r
+                WritePlane:BYTE         = AUTO_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+\r
+; Clip image\r
+        mov     bx, [X]\r
+        mov     ax, [Y]\r
+        mov     cx, [Width]\r
+        mov     dx, [Height]\r
+        call    subClipImage\r
+        jc      @@Exit                  ; Full clipped\r
+        mov     [Height], dx\r
+        add     WORD PTR Image[0], si   ; Skip clipped pixels\r
+\r
+; Get pixel address\r
+        mul     [mx_BytesPerLine]\r
+        mov     di, bx\r
+        shr     di, 1\r
+        shr     di, 1\r
+        add     di, ax\r
+        mov     [PixelOffset], di\r
+        mov     es, [mx_VideoSegment]   ; ES:DI points to pixel\r
+        and     bl, 03h\r
+        mov     [ReadPlane], bl\r
+\r
+; Compute extra bytes and width count for each plane\r
+        mov     bx, cx\r
+        shr     bx, 1\r
+        shr     bx, 1                   ; Width for each plane\r
+        and     cl, 03h\r
+        mov     al, 00001000b\r
+        shr     al, cl\r
+        mov     si, 3 SHL 1\r
+@@PatchLoop:\r
+        mov     PlaneWidth[si], bx\r
+        shr     al, 1\r
+        adc     bx, 0\r
+        dec     si\r
+        dec     si\r
+        jge     @@PatchLoop\r
+\r
+; Setup planes for output to VGA registers\r
+        mov     cl, [ReadPlane]\r
+        mov     al, 00010001b\r
+        shl     al, cl\r
+        mov     [WritePlane], al\r
+\r
+; Install move function\r
+        mov     bx, [Op]\r
+        mov     [OpInfo], bh            ; Remember additional info if needed\r
+        xor     bh, bh\r
+        cmp     bl, OP_ADD\r
+        jbe     @@SetMoveFunction\r
+        xor     bl, bl\r
+@@SetMoveFunction:\r
+        shl     bx, 1\r
+        mov     ax, mxTable[bx]\r
+        mov     [MoveFunction], ax\r
+\r
+; Put image\r
+        cld\r
+        mov     [Count], 4              ; Four planes\r
+        lea     bx, PlaneWidth          ; SS:[BX] = width in bytes for plane\r
+        mov     ds, WORD PTR Image[2]\r
+@@PlaneLoop:\r
+        cmp     WORD PTR ss:[bx], 0     ; Exit if nothing more to do\r
+        je      @@Exit                  ; (also, never try to move zero bytes!)\r
+        mov     si, WORD PTR Image[0]\r
+        mov     ah, [WritePlane]\r
+        and     ah, 0Fh\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax                  ; Select write plane\r
+        mov     ah, [ReadPlane]\r
+        and     ah, 03h\r
+        mov     al, 04h\r
+        mov     dx, GDC\r
+        out     dx, ax                  ; Select read plane\r
+        mov     dx, [Height]\r
+        mov     di, [PixelOffset]\r
+@@Loop:\r
+        push    si\r
+        push    di\r
+        mov     cx, WORD PTR ss:[bx]    ; Number of bytes to move\r
+        mov     ah, [OpInfo]            ; Transparent color for subTrans\r
+        call    [MoveFunction]\r
+        pop     di\r
+        pop     si\r
+        add     si, [Width]             ; Go to next image line\r
+        add     di, [mx_BytesPerLine]   ; Go to next screen row\r
+        dec     dx\r
+        jnz     @@Loop                  ; Repeat for all lines\r
+        inc     bx\r
+        inc     bx                      ; Select width for next plane\r
+        inc     [ReadPlane]\r
+        rol     [WritePlane], 1\r
+        adc     [PixelOffset], 0\r
+        inc     WORD PTR Image[0]\r
+        dec     [Count]\r
+        jnz     @@PlaneLoop             ; Repeat for all planes\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxPutImage      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxpn.asm b/16/xw/mxpn.asm
new file mode 100755 (executable)
index 0000000..eaaf61b
--- /dev/null
@@ -0,0 +1,60 @@
+;-----------------------------------------------------------\r
+;\r
+; MXPN.ASM - Panning function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxPan\r
+\r
+EXTRN   mxWaitDisplay   : FAR\r
+EXTRN   mxStartAddress  : FAR\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Moves the screen.\r
+;\r
+; Input:\r
+;       X, Y    = new X, Y coordinates of view screen\r
+; Output:\r
+;       none\r
+;\r
+mxPan           PROC    FAR\r
+        ARG     Y:WORD,                 \\r
+                X:WORD                  = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+\r
+        mov     ax, [Y]\r
+        mul     [mx_BytesPerLine]\r
+        mov     dx, [X]\r
+        shr     dx, 1\r
+        shr     dx, 1\r
+        add     ax, dx\r
+        push    ax                      ; Push the start address\r
+        call    mxWaitDisplay\r
+        call    mxStartAddress\r
+\r
+        mov     dx, 03DAh               ; Set the pixel pan register\r
+        in      al, dx\r
+        mov     dx, 03C0h\r
+        mov     al, 33h\r
+        out     dx, al\r
+        mov     al, BYTE PTR [X]\r
+        and     al, 3\r
+        shl     al, 1\r
+        out     dx, al\r
+\r
+        xor     ax, ax\r
+        .leave  ARG_SIZE\r
+mxPan           ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxpp.asm b/16/xw/mxpp.asm
new file mode 100755 (executable)
index 0000000..fc1755a
--- /dev/null
@@ -0,0 +1,121 @@
+;-----------------------------------------------------------\r
+;\r
+; MXPP.ASM - Get/put pixel functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxGetPixel\r
+PUBLIC  mxPutPixel\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_ClipX1       : WORD\r
+EXTRN   mx_ClipY1       : WORD\r
+EXTRN   mx_ClipX2       : WORD\r
+EXTRN   mx_ClipY2       : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Gets a pixel.\r
+;\r
+; Input:\r
+;       X, Y    = pixel coordinates\r
+; Output:\r
+;       pixel color\r
+;\r
+mxGetPixel      PROC    FAR\r
+        ARG     Y:WORD,                 \\r
+                X:WORD                  = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si\r
+\r
+        xor     ax, ax\r
+        mov     si, [X]\r
+        cmp     si, [mx_ClipX1]\r
+        jl      @@Exit\r
+        cmp     si, [mx_ClipX2]\r
+        jg      @@Exit\r
+        mov     bx, [Y]\r
+        cmp     bx, [mx_ClipY1]\r
+        jl      @@Exit\r
+        cmp     bx, [mx_ClipY2]\r
+        jg      @@Exit\r
+\r
+        mov     al, 04h                 ; Set read plane\r
+        mov     ah, BYTE PTR [X]\r
+        and     ah, 3\r
+        mov     dx, GDC\r
+        out     dx, ax\r
+\r
+        mov     ds, [mx_VideoSegment]\r
+        mov     ax, bx\r
+        mul     [mx_BytesPerLine]\r
+        .shr    si, 2\r
+        add     si, ax\r
+\r
+        mov     al, ds:[si]             ; Get pixel value\r
+        xor     ah, ah\r
+\r
+@@Exit:\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetPixel      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Puts a pixel of the specified color.\r
+;\r
+; Input:\r
+;       X, Y    = pixel coordinates\r
+;       Color   = pixel color\r
+; Output:\r
+;       none\r
+;\r
+mxPutPixel      PROC    FAR\r
+        ARG     Color:BYTE:2,           \\r
+                Y:WORD,                 \\r
+                X:WORD                  = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+\r
+        mov     si, [X]\r
+        cmp     si, [mx_ClipX1]\r
+        jl      @@Exit\r
+        cmp     si, [mx_ClipX2]\r
+        jg      @@Exit\r
+        mov     ax, [Y]\r
+        cmp     ax, [mx_ClipY1]\r
+        jl      @@Exit\r
+        cmp     ax, [mx_ClipY2]\r
+        jg      @@Exit\r
+\r
+        mov     ds, [mx_VideoSegment]\r
+        mul     [mx_BytesPerLine]\r
+        .shr    si, 2\r
+        add     si, ax\r
+\r
+        mov     cl, BYTE PTR [X]        ; Set write plane\r
+        and     cl, 3\r
+        mov     ax, 0102h\r
+        shl     ah, cl\r
+        mov     dx, TS\r
+        out     dx, ax\r
+\r
+        mov     al, [Color]             ; Write pixel\r
+        mov     ds:[si], al\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxPutPixel      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxra.asm b/16/xw/mxra.asm
new file mode 100755 (executable)
index 0000000..dd8e683
--- /dev/null
@@ -0,0 +1,37 @@
+;-----------------------------------------------------------\r
+;\r
+; MXRA.ASM - Row address\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxRowAddress\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the row address register.\r
+;\r
+; Input:\r
+;       RowAddress      = row size in words\r
+; Output:\r
+;       none\r
+;\r
+mxRowAddress    PROC    FAR\r
+        ARG     RowAddress:BYTE:2       = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        mov     dx, CRTC\r
+        mov     al, 13h\r
+        mov     ah, [RowAddress]\r
+        out     dx, ax\r
+        xor     ax, ax\r
+        .leave  ARG_SIZE\r
+mxRowAddress    ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxrp.asm b/16/xw/mxrp.asm
new file mode 100755 (executable)
index 0000000..de820c1
--- /dev/null
@@ -0,0 +1,101 @@
+;-----------------------------------------------------------\r
+;\r
+; MXRP.ASM - Rotate palette function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxRotatePalette\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Rotates the palette of the specified number of colors.\r
+;\r
+; Input:\r
+;       Palette = pointer to palette\r
+;       Count   = number of colors to rotate\r
+;       Step    = step size\r
+; Output:\r
+;       none\r
+;\r
+; Note: if Step is positive palette is rotated left to right, otherwise\r
+;       right to left.\r
+;\r
+mxRotatePalette PROC    FAR\r
+        ARG     Step:WORD,      \\r
+                Count:WORD,     \\r
+                Palette:DWORD   = ARG_SIZE\r
+        LOCAL   Holder:BYTE:768 = AUTO_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+\r
+        mov     bx, [Count]\r
+        add     bx, bx\r
+        add     bx, [Count]             ; BX = Count*3\r
+\r
+        lds     si, [Palette]           ; DS:SI -> palette\r
+        push    ss\r
+        pop     es\r
+        lea     di, Holder              ; ES:DI -> local space\r
+        cld\r
+\r
+        mov     ax, [Step]\r
+        mov     dx, ax\r
+        test    ax, ax\r
+        jz      @@Exit                  ; Nothing to do, exit\r
+        jl      @@RightToLeft\r
+\r
+@@LeftToRight:\r
+        add     ax, ax\r
+        add     dx, ax                  ; DX = Step*3\r
+        sub     bx, dx                  ; BX = (Count-Step)*3\r
+        add     si, bx\r
+        push    si\r
+        mov     cx, dx\r
+        rep     movsb\r
+        mov     es, WORD PTR Palette[2]\r
+        mov     di, si\r
+        dec     di                      ; ES:DI -> last byte of palette\r
+        pop     si\r
+        dec     si\r
+        mov     cx, bx\r
+        std\r
+        rep     movsb\r
+        push    ss\r
+        pop     ds\r
+        lea     si, Holder\r
+        les     di, [Palette]\r
+        mov     cx, dx\r
+        cld\r
+        rep     movsb\r
+        jmp     @@Exit\r
+\r
+@@RightToLeft:\r
+        add     ax, ax\r
+        add     dx, ax\r
+        neg     dx                      ; DX = Step*3\r
+        sub     bx, dx                  ; BX = (Count-Step)*3\r
+        mov     cx, dx\r
+        rep     movsb\r
+        les     di, [Palette]\r
+        mov     cx, bx\r
+        rep     movsb\r
+        push    ss\r
+        pop     ds\r
+        lea     si, Holder\r
+        mov     cx, dx\r
+        rep     movsb\r
+\r
+@@Exit:\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxRotatePalette ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxsa.asm b/16/xw/mxsa.asm
new file mode 100755 (executable)
index 0000000..3ebae67
--- /dev/null
@@ -0,0 +1,44 @@
+;-----------------------------------------------------------\r
+;\r
+; MXSA.ASM - Start address function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxStartAddress\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Modifies the starting address of video memory.\r
+;\r
+; Input:\r
+;       StartAddr       = new start address of video memory\r
+; Output:\r
+;       none\r
+;\r
+mxStartAddress  PROC    FAR\r
+        ARG     StartAddr:WORD  = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+\r
+        mov     bx, [StartAddr]\r
+        mov     dx, CRTC\r
+        mov     al, 0Ch                 ; Linear Starting Address high\r
+        mov     ah, bh\r
+        cli\r
+        out     dx, ax\r
+        mov     al, 0Dh                 ; Linear Starting Address low\r
+        mov     ah, bl\r
+        out     dx, ax\r
+        sti\r
+\r
+        .leave  ARG_SIZE\r
+mxStartAddress  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxsc.asm b/16/xw/mxsc.asm
new file mode 100755 (executable)
index 0000000..bcae45e
--- /dev/null
@@ -0,0 +1,50 @@
+;-----------------------------------------------------------\r
+;\r
+; MXSC.ASM - Set color function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxSetColor\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Updates the selected DAC register.\r
+;\r
+; Input:\r
+;       Index   = index of color to set\r
+;       R, G, B = color components\r
+; Output:\r
+;       none\r
+;\r
+mxSetColor      PROC FAR\r
+        ARG     B:BYTE:2,       \\r
+                G:BYTE:2,       \\r
+                R:BYTE:2,       \\r
+                Index:WORD      = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+\r
+        mov     ax, [Index]\r
+        mov     dx, 3C8h                ; PEL write address register\r
+        out     dx, al\r
+        inc     dx\r
+\r
+        mov     al, [R]\r
+        out     dx, al\r
+        mov     al, [G]\r
+        out     dx, al\r
+        mov     al, [B]\r
+        out     dx, al\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxSetColor      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxsi.asm b/16/xw/mxsi.asm
new file mode 100755 (executable)
index 0000000..b88d3b1
--- /dev/null
@@ -0,0 +1,317 @@
+;-----------------------------------------------------------\r
+;\r
+; MXPI.ASM - Stretch image\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxStretchImage\r
+\r
+EXTRN   subClipBox              : NEAR\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+mxTable LABEL   WORD                    ; Raster ops\r
+        DW      subMove\r
+        DW      subAnd\r
+        DW      subOr\r
+        DW      subXor\r
+        DW      subTrans\r
+        DW      subAdd\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Stretches and copies a "raw" image from memory to screen.\r
+;\r
+; Input:\r
+;       Image     = pointer to image\r
+;       X, Y      = coordinates of destination\r
+;       Width     = width of image in pixels\r
+;       Height    = height of image in pixels\r
+;       NewWidth  = new width of image in pixels\r
+;       NewHeight = new height of image in pixels\r
+;       Op        = raster op (OP_xxx)\r
+; Output:\r
+;       none\r
+;\r
+mxStretchImage  PROC    FAR\r
+        ARG     Op:WORD,                \\r
+                NewHeight:WORD,         \\r
+                NewWidth:WORD,          \\r
+                Height:WORD,            \\r
+                Width:WORD,             \\r
+                Y:WORD,                 \\r
+                X:WORD,                 \\r
+                Image:DWORD             = ARG_SIZE\r
+        LOCAL   PixelOffset:WORD,       \\r
+                MoveFunction:WORD,      \\r
+                ReadPlane:BYTE,         \\r
+                OpInfo:BYTE,            \\r
+                WidthStep:DWORD,        \\r
+                HeightStep:DWORD,       \\r
+                ImageLo:WORD,           \\r
+                WritePlane:BYTE         = AUTO_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+\r
+; Get width stretch factor\r
+    IF USE386 EQ TRUE\r
+        movzx   edx, [Width]\r
+        xor     eax, eax\r
+        movzx   ebx, [NewWidth]\r
+        shl     ebx, 16\r
+        idiv    ebx\r
+        mov     [WidthStep], eax\r
+    ELSE\r
+        xor     dx, dx                  ; Width stretch factor\r
+        mov     ax, [Width]\r
+        mov     bx, [NewWidth]\r
+        div     bx\r
+        mov     WORD PTR WidthStep[2], ax\r
+        xor     ax, ax\r
+        div     bx\r
+        mov     WORD PTR WidthStep[0], ax\r
+    ENDIF\r
+; Get height stretch factor\r
+    IF USE386 EQ TRUE\r
+        movzx   edx, [Height]\r
+        xor     eax, eax\r
+        movzx   ebx, [NewHeight]\r
+        shl     ebx, 16\r
+        idiv    ebx\r
+        mov     [HeightStep], eax\r
+    ELSE\r
+        xor     dx, dx\r
+        mov     ax, [Height]\r
+        mov     bx, [NewHeight]\r
+        div     bx\r
+        mov     WORD PTR HeightStep[2], ax\r
+        xor     ax, ax\r
+        div     bx\r
+        mov     WORD PTR HeightStep[0], ax\r
+   ENDIF\r
+\r
+; Clip image\r
+        mov     bx, [X]\r
+        mov     ax, [Y]\r
+        mov     cx, [NewWidth]\r
+        mov     dx, [NewHeight]\r
+        call    subClipBox\r
+        jc      @@Exit                  ; Full clipped\r
+        mov     [NewWidth], cx\r
+        mov     [NewHeight], dx\r
+        sub     [X], bx\r
+        sub     [Y], ax\r
+\r
+; Get pixel address\r
+        mul     [mx_BytesPerLine]\r
+        mov     di, bx\r
+        shr     di, 1\r
+        shr     di, 1\r
+        add     di, ax\r
+        mov     [PixelOffset], di\r
+        mov     es, [mx_VideoSegment]   ; ES:DI points to pixel\r
+        and     bl, 03h\r
+        mov     [ReadPlane], bl         ; Set read plane\r
+        mov     cl, bl\r
+        mov     al, 00010001b\r
+        shl     al, cl\r
+        mov     [WritePlane], al        ; Set write plane\r
+\r
+; Relocate image origin if previously clipped\r
+        mov     ax, [Y]\r
+        test    ax, ax\r
+        jz      @@OriginYDone\r
+    IF USE386 EQ TRUE\r
+        shl     eax, 16\r
+        imul    [HeightStep]\r
+        mov     ax, [Width]\r
+        mul     dx\r
+    ELSE\r
+        mov     bx, ax\r
+        mul     WORD PTR HeightStep[0]\r
+        mov     cx, dx\r
+        mov     ax, bx\r
+        mul     WORD PTR HeightStep[2]\r
+        add     ax, cx\r
+        mul     [Width]\r
+    ENDIF\r
+        add     WORD PTR [Image], ax\r
+@@OriginYDone:\r
+        mov     ax, [X]\r
+        test    ax, ax\r
+        jz      @@OriginXDone\r
+    IF USE386 EQ TRUE\r
+        shl     eax, 16\r
+        imul    [WidthStep]\r
+        add     WORD PTR [Image], dx\r
+    ELSE\r
+        mov     bx, ax\r
+        mul     WORD PTR WidthStep[0]\r
+        mov     cx, dx\r
+        mov     ax, bx\r
+        mul     WORD PTR WidthStep[2]\r
+        add     ax, cx\r
+        add     WORD PTR [Image], ax\r
+    ENDIF\r
+@@OriginXDone:\r
+        mov     ax, WORD PTR HeightStep[2]\r
+        mul     [Width]\r
+        mov     WORD PTR HeightStep[2], ax\r
+\r
+; Install move function\r
+        mov     bx, [Op]\r
+        mov     [OpInfo], bh            ; Remember additional info if needed\r
+        xor     bh, bh\r
+        cmp     bl, OP_ADD\r
+        jbe     @@SetMoveFunction\r
+        xor     bl, bl\r
+@@SetMoveFunction:\r
+        shl     bx, 1\r
+        mov     ax, mxTable[bx]\r
+        mov     [MoveFunction], ax\r
+\r
+; Put image\r
+        mov     ds, WORD PTR Image[2]\r
+        xor     ax, ax\r
+        mov     [ImageLo], ax\r
+@@Loop:\r
+        mov     si, WORD PTR Image[0]   ; Get pointer to image\r
+        mov     ah, [WritePlane]\r
+        and     ah, 0Fh\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax                  ; Select write plane\r
+        mov     ah, [ReadPlane]\r
+        and     ah, 03h\r
+        mov     al, 04h\r
+        mov     dx, GDC\r
+        out     dx, ax                  ; Select read plane\r
+        mov     cx, [NewHeight]\r
+        mov     di, [PixelOffset]       ; ES:DI points to video memory\r
+        mov     ah, [OpInfo]            ; Additional raster op info\r
+        xor     bx, bx\r
+        mov     dx, [mx_BytesPerLine]\r
+        call    [MoveFunction]          ; Draw column\r
+        inc     [ReadPlane]             ; Next read plane\r
+        rol     [WritePlane], 1         ; Next write plane\r
+        adc     [PixelOffset], 0        ; Update video offset if needed\r
+        mov     dx, WORD PTR WidthStep[0]\r
+        mov     ax, WORD PTR WidthStep[2]\r
+        add     [ImageLo], dx\r
+        adc     WORD PTR Image[0], ax   ; Next image column\r
+        dec     [NewWidth]\r
+        jnz     @@Loop                  ; Repeat for all columns\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Move functions, on entry:\r
+;       AH = additional raster op info (e.g. transparent color)\r
+;       BX = 0,\r
+;       CX = pixel count,\r
+;       DX = mx_BytesPerLine.\r
+;\r
+subMove         PROC    NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        mov     es:[di], al\r
+        add     di, dx\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, WORD PTR HeightStep[2]\r
+        add     bx, WORD PTR HeightStep[0]\r
+        jnc     @@Loop\r
+        add     si, [Width]\r
+        jmp     @@Loop\r
+@@Exit: ret\r
+subMove         ENDP\r
+;\r
+subAnd          PROC     NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        and     es:[di], al\r
+        add     di, dx\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, WORD PTR HeightStep[2]\r
+        add     bx, WORD PTR HeightStep[0]\r
+        jnc     @@Loop\r
+        add     si, [Width]\r
+        jmp     @@Loop\r
+@@Exit: ret\r
+subAnd          ENDP\r
+;\r
+subOr           PROC     NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        or      es:[di], al\r
+        add     di, dx\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, WORD PTR HeightStep[2]\r
+        add     bx, WORD PTR HeightStep[0]\r
+        jnc     @@Loop\r
+        add     si, [Width]\r
+        jmp     @@Loop\r
+@@Exit: ret\r
+subOr           ENDP\r
+;\r
+subXor          PROC     NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        xor     es:[di], al\r
+        add     di, dx\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, WORD PTR HeightStep[2]\r
+        add     bx, WORD PTR HeightStep[0]\r
+        jnc     @@Loop\r
+        add     si, [Width]\r
+        jmp     @@Loop\r
+@@Exit: ret\r
+subXor          ENDP\r
+;\r
+subTrans        PROC     NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        cmp     al, ah\r
+        je      @@Skip\r
+        mov     es:[di], al\r
+@@Skip:\r
+        add     di, dx\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, WORD PTR HeightStep[2]\r
+        add     bx, WORD PTR HeightStep[0]\r
+        jnc     @@Loop\r
+        add     si, [Width]\r
+        jmp     @@Loop\r
+@@Exit: ret\r
+subTrans        ENDP\r
+;\r
+subAdd          PROC     NEAR\r
+@@Loop: mov     al, ds:[si]\r
+        add     es:[di], al\r
+        add     di, dx\r
+        dec     cx\r
+        jz      @@Exit\r
+        add     si, WORD PTR HeightStep[2]\r
+        add     bx, WORD PTR HeightStep[0]\r
+        jnc     @@Loop\r
+        add     si, [Width]\r
+        jmp     @@Loop\r
+@@Exit: ret\r
+subAdd          ENDP\r
+\r
+mxStretchImage  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxsl.asm b/16/xw/mxsl.asm
new file mode 100755 (executable)
index 0000000..d790885
--- /dev/null
@@ -0,0 +1,62 @@
+;-----------------------------------------------------------\r
+;\r
+; MXLN.ASM - Start line function\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxStartLine\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+        ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Changes the video start address to the specified line.\r
+;\r
+; Input:\r
+;       Line    = new start line\r
+; Output:\r
+;       none\r
+;\r
+mxStartLine     PROC FAR\r
+        ARG     Line:WORD       = ARG_SIZE\r
+        .enter  0\r
+        ASSUME  ds:NOTHING\r
+\r
+        mov     ax, [Line]              ; Get video offset\r
+        mul     [mx_BytesPerLine]\r
+        xchg    ax, bx                  ; Copy it into BX\r
+\r
+; Wait display\r
+        mov     dx, STATUS\r
+@@1:    in      al, dx\r
+        test    al, 08h\r
+        jnz     @@1\r
+\r
+; Set starting address\r
+        mov     dx, CRTC\r
+        mov     al, 0Ch                 ; Linear Starting Address high\r
+        mov     ah, bh\r
+        cli\r
+        out     dx, ax\r
+        mov     al, 0Dh                 ; Linear Starting Address low\r
+        mov     ah, bl\r
+        out     dx, ax\r
+        sti\r
+\r
+; Wait retrace\r
+        mov     dx, STATUS\r
+@@2:    in      al,dx\r
+        test    al, 08h\r
+        jz      @@2\r
+\r
+        xor     ax, ax\r
+        .leave  ARG_SIZE\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxsm.asm b/16/xw/mxsm.asm
new file mode 100755 (executable)
index 0000000..183fba1
--- /dev/null
@@ -0,0 +1,508 @@
+;-----------------------------------------------------------\r
+;\r
+; MXSM.ASM - Set/change mode functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxChangeMode\r
+PUBLIC  mxGetAspect\r
+PUBLIC  mxGetScreenSize\r
+PUBLIC  mxSetMode\r
+\r
+PUBLIC  mx_ScreenWidth\r
+PUBLIC  mx_ScreenHeight\r
+PUBLIC  mx_BytesPerLine\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mxSetSysClipRegion      : FAR\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_CodeSegment  : WORD\r
+\r
+mx_ScreenWidth  DW      ?               ; Current screen width\r
+mx_ScreenHeight DW      ?\r
+mx_AspectX      DW      ?               ; Aspect ratio for current mode\r
+mx_AspectY      DW      ?\r
+mx_BytesPerLine DW      0               ; Bytes per line\r
+\r
+;\r
+; Tables for setting video modes, sources:\r
+; - MODEX.ASM, Matt Pritchard\r
+; - Dr. Dobb's Journal, Michael Abrash\r
+; - Fractint VIDEO.ASM module\r
+;\r
+TBL_SingleLine  LABEL   WORD            ; CRTC\r
+        DW      04009h                  ; Cell height: 1 scan line\r
+        DW      00014h                  ; Double word mode off\r
+        DW      0E317h                  ; Byte mode on\r
+        DW      0\r
+TBL_DoubleLine  LABEL   WORD            ; CRTC\r
+        DW      04109h                  ; Cell height: 2 scan lines\r
+        DW      00014h\r
+        DW      0E317h\r
+        DW      0\r
+TBL_Width320    LABEL   WORD            ; CRTC\r
+        DW      05F00h                  ; Horizontal total\r
+        DW      04F01h                  ; Horizontal displayed\r
+        DW      05002h                  ; Start horizontal blanking\r
+        DW      08203h                  ; End horizontal blanking\r
+        DW      05404h                  ; Start horizontal sync\r
+        DW      08005h                  ; End horizontal sync\r
+        DW      02813h                  ; Row address\r
+        DW      0\r
+TBL_Width360    LABEL   WORD            ; CRTC\r
+        DW      06B00h                  ; Horizontal total\r
+        DW      05901h                  ; Horizontal displayed\r
+        DW      05A02h                  ; Start horizontal blanking\r
+        DW      08E03h                  ; End horizontal blanking\r
+        DW      05E04h                  ; Start horizontal sync\r
+        DW      08A05h                  ; End horizontal sync\r
+        DW      02D13h                  ; Row address\r
+        DW      0\r
+TBL_Height175   LABEL   WORD            ; CRTC\r
+        DW      0BF06h                  ; Vertical total\r
+        DW      01F07h                  ; Overflow\r
+        DW      08310h                  ; Start vertical sync\r
+        DW      08511h                  ; End vertical sync\r
+        DW      05D12h                  ; Vertical displayed\r
+        DW      06315h                  ; Start vertical blanking\r
+        DW      0BA16h                  ; End vertical blanking\r
+        DW      0\r
+TBL_Height200   LABEL   WORD            ; CRTC\r
+        DW      0BF06h                  ; Vertical total\r
+        DW      01F07h                  ; Overflow\r
+        DW      09C10h                  ; Start vertical sync\r
+        DW      08E11h                  ; End vertical sync\r
+        DW      08F12h                  ; Vertical displayed\r
+        DW      09615h                  ; Start vertical blanking\r
+        DW      0B916h                  ; End vertical blanking\r
+        DW      0\r
+TBL_Height240   LABEL   WORD            ; CRTC\r
+        DW      00D06h                  ; Vertical total\r
+        DW      03E07h                  ; Overflow\r
+        DW      0EA10h                  ; Start vertical sync\r
+        DW      08C11h                  ; End vertical sync\r
+        DW      0DF12h                  ; Vertical displayed\r
+        DW      0E715h                  ; Start vertical blanking\r
+        DW      00616h                  ; End vertical blanking\r
+        DW      0\r
+TBL_Tweak400x600:\r
+        DW      07400h\r
+        DW      06301h\r
+        DW      06402h\r
+        DW      09703h\r
+        DW      06804h\r
+        DW      09505h\r
+        DW      08606h\r
+        DW      0F007h\r
+        DW      06009h\r
+        DW      0310Fh\r
+        DW      05B10h\r
+        DW      08D11h\r
+        DW      05712h\r
+        DW      03213h\r
+        DW      00014h\r
+        DW      06015h\r
+        DW      08016h\r
+        DW      0E317h\r
+        DW      0\r
+\r
+TBL_320x200:\r
+        DB      63h                     ; 400 scan lines, 25 MHz clock\r
+        DW      6, 5                    ; Aspect: 6/5 = 1.2:1\r
+        DW      320, 200                ; Size\r
+        DW      TBL_Width320, TBL_Height200, TBL_DoubleLine, 0\r
+        DW      819                     ; Max height\r
+TBL_320x240:\r
+        DB      0E3h                    ; 400 scan lines, 25 MHz clock\r
+        DW      1, 1                    ; Aspect: 1/1 = 1:1\r
+        DW      320, 240                ; Size\r
+        DW      TBL_Width320, TBL_Height240, TBL_DoubleLine, 0\r
+        DW      819                     ; Max height\r
+TBL_320x400:\r
+        DB      63h                     ; 480 scan lines, 25 MHz clock\r
+        DW      6, 10                   ; Aspect: 6/10 = 0.6:1\r
+        DW      320, 400                ; Size\r
+        DW      TBL_Width320, TBL_Height200, TBL_SingleLine, 0\r
+        DW      819                     ; Max height\r
+TBL_320x480:\r
+        DB      0E3h                    ; 480 scan lines, 25 MHz clock\r
+        DW      1, 2                    ; Aspect: 1/2 = 0.5:1\r
+        DW      320, 480                ; Size\r
+        DW      TBL_Width320, TBL_Height240, TBL_SingleLine, 0\r
+        DW      819                     ; Max height\r
+TBL_360x200:\r
+        DB      067h                    ; 400 scan lines, 28 MHz clock\r
+        DW      27, 20                  ; Aspect: 27/20 = 1.35:1\r
+        DW      360, 200                ; Size\r
+        DW      TBL_Width360, TBL_Height200, TBL_DoubleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_360x240:\r
+        DB      0E7h                    ; 480 scan lines, 28 MHz clock\r
+        DW      9, 8                    ; Aspect: 9/8 = 1.125:1\r
+        DW      360, 240                ; Size\r
+        DW      TBL_Width360, TBL_Height240, TBL_DoubleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_360x400:\r
+        DB      067h                    ; 400 scan lines, 28 MHz clock\r
+        DW      27, 40                  ; Aspect: 27/40 = 0.675:1\r
+        DW      360, 400                ; Size\r
+        DW      TBL_Width360, TBL_Height200, TBL_SingleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_360x480:\r
+        DB      0E7h                    ; 480 scan lines, 28 MHz clock\r
+        DW      9, 16                   ; Aspect: 9/16 = 0.5625:1\r
+        DW      360, 480                ; Size\r
+        DW      TBL_Width360, TBL_Height240, TBL_SingleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_320x175:\r
+        DB      0A3h\r
+        DW      0, 0                    ; Aspect:\r
+        DW      320, 175\r
+        DW      TBL_Width320, TBL_Height175, TBL_DoubleLine, 0\r
+        DW      819\r
+TBL_320x350:\r
+        DB      0A3h\r
+        DW      0, 0                    ; Aspect:\r
+        DW      320, 175\r
+        DW      TBL_Width320, TBL_Height175, TBL_SingleLine, 0\r
+        DW      819\r
+TBL_360x175:\r
+        DB      0A7h\r
+        DW      0, 0                    ; Aspect:\r
+        DW      360, 480                ; Size\r
+        DW      TBL_Width360, TBL_Height175, TBL_DoubleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_360x350:\r
+        DB      0A7h\r
+        DW      0, 0                    ; Aspect:\r
+        DW      360, 480                ; Size\r
+        DW      TBL_Width360, TBL_Height175, TBL_SingleLine, 0\r
+        DW      728                     ; Max height\r
+TBL_400x600:\r
+        DB      0E7h                    ; 28 MHz clock\r
+        DW      1, 2                    ; Aspect: 1/2 = 0.5:1\r
+        DW      400, 600                ; Size\r
+        DW      TBL_Tweak400x600, 0\r
+        DW      655                     ; Max height\r
+\r
+TBL_Mode        LABEL   WORD\r
+        DW      TBL_320x175\r
+        DW      TBL_320x200\r
+        DW      TBL_320x240\r
+        DW      TBL_320x350\r
+        DW      TBL_320x400\r
+        DW      TBL_320x480\r
+        DW      TBL_360x175\r
+        DW      TBL_360x200\r
+        DW      TBL_360x240\r
+        DW      TBL_360x350\r
+        DW      TBL_360x400\r
+        DW      TBL_360x480\r
+        DW      TBL_400x600\r
+\r
+MAXVMODE        EQU     ($-OFFSET TBL_Mode) / 2\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Enables 80x25 color text mode\r
+;\r
+subText         PROC    NEAR\r
+        ASSUME  ds:MX_TEXT\r
+        mov     ax, 0003h\r
+        int     10h                     ; Call BIOS set mode\r
+\r
+        mov     [mx_ScreenHeight], 0\r
+        mov     [mx_BytesPerLine], 0\r
+        ret\r
+subText         ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Enables the selected graphics mode.\r
+;\r
+; Input:\r
+;       Mode    = mode to select (MX_???x???)\r
+; Output:\r
+;       none\r
+;\r
+mxSetMode       PROC    FAR\r
+        ARG     Mode:WORD       = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si, es, di\r
+\r
+; Set DS to code segment alias\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     si, [Mode]\r
+        cmp     si, MAXVMODE            ; Is it a valid mode?\r
+        ja      @@Exit                  ; No, exit\r
+        test    si, si                  ; Text mode?\r
+        jnz     @@Set                   ; No, handle it\r
+\r
+        call    subText                 ; Back to text mode\r
+        jmp     @@Exit                  ; Exit now\r
+\r
+; Set video mode\r
+@@Set:\r
+        dec     si                      ; Skip text mode\r
+        shl     si, 1\r
+        mov     si, TBL_Mode[si]\r
+        cld\r
+\r
+; Use BIOS to set 320x200x256 linear mode\r
+        push    si                      ; Save SI\r
+        mov     ax, 0013h\r
+        int     10h                     ; Use BIOS to set 320x200 linear mode\r
+        pop     si                      ; Restore SI\r
+\r
+        mov     dx, TS\r
+        mov     ax, 0604h\r
+        out     dx, ax                  ; Disable chain-4 mode\r
+        mov     ax, 0100h\r
+        out     dx, ax                  ; Reset\r
+        mov     dx, MISC\r
+        lodsb\r
+        out     dx, al                  ; New timing/size\r
+        mov     dx, TS\r
+        mov     ax, 0300h\r
+        out     dx, ax                  ; Restart sequencer\r
+\r
+; Unlock CRTC registers 0-7\r
+        mov     dx, CRTC\r
+        mov     al, 11h\r
+        out     dx, al                  ; Vertical sync end register\r
+        inc     dx\r
+        in      al, dx\r
+        and     al, 7Fh                 ; Clear write protect bit\r
+        out     dx, al\r
+\r
+        lodsw                           ; Get X aspect\r
+        mov     [mx_AspectX], ax\r
+        lodsw                           ; Get Y aspect\r
+        mov     [mx_AspectY], ax\r
+        lodsw                           ; Get screen width\r
+        mov     [mx_ScreenWidth], ax\r
+        shr     ax, 1\r
+        shr     ax, 1                   ; Divide by four to get bytes per line\r
+        mov     [mx_BytesPerLine], ax\r
+        lodsw                           ; Get screen height\r
+        mov     [mx_ScreenHeight], ax\r
+\r
+; Set CRTC registers\r
+        mov     bx, si\r
+        mov     dx, CRTC\r
+@@TableLoop:\r
+        mov     si, ds:[bx]             ; DS:SI -> table of CRTC registers\r
+        inc     bx\r
+        inc     bx                      ; DS:BX -> offset of next table\r
+        test    si, si                  ; Last table?\r
+        jz      @@EndLoop               ; Yes, exit loop\r
+@@Loop:\r
+        lodsw                           ; Get CRTC register index and value\r
+        test    ax, ax                  ; End of table?\r
+        jz      @@TableLoop             ; Yes, go to next table\r
+        out     dx, ax                  ; Set register AL to value AH\r
+        jmp     @@Loop                  ; Get next register/value\r
+@@EndLoop:\r
+\r
+; Set virtual screen and system clip region\r
+        push    [mx_ScreenWidth]\r
+        push    WORD PTR ds:[bx]\r
+        call    mxSetSysClipRegion\r
+\r
+; Clear video memory\r
+        mov     dx, TS\r
+        mov     ax, 0F02h\r
+        out     dx, ax                  ; Enable all planes\r
+        mov     es, [mx_VideoSegment]\r
+        xor     di, di\r
+        mov     cx, 8000h\r
+        xor     ax, ax\r
+        rep     stosw\r
+\r
+@@Done:\r
+; Lock CRTC registers 0-7 (some cards need this)\r
+        mov     dx, CRTC\r
+        mov     al, 11h\r
+        out     dx, al                  ; Vertical sync end register\r
+        inc     dx\r
+        in      al, dx\r
+        or      al, 80h                 ; Set write protect bit\r
+        out     dx, al\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        mov     ax, [mx_ScreenWidth]\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxSetMode       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Changes from the current mode the selected graphics mode.\r
+;\r
+; Input:\r
+;       Mode    = mode to select (MX_???x???)\r
+; Output:\r
+;       none\r
+; Notes:\r
+;       this function assumes that mxSetMode and mxSetVirtualScreen\r
+;       have been called first. View size is rearranged to match the\r
+;       specified mode, but video memory is not cleared.\r
+;       Differences from mxSetMode:\r
+;       - video BIOS is not called to initialize graphics;\r
+;       - row address register is not modified;\r
+;       - video memory is not cleared;\r
+;       - mx_BytesPerLine is not modified;\r
+;       - system clip region is not modified.\r
+;\r
+mxChangeMode    PROC    FAR\r
+        ARG     Mode:WORD       = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si, es, di\r
+\r
+; Set DS to code segment alias\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     si, [Mode]\r
+        cmp     si, MAXVMODE            ; Is it a valid mode?\r
+        ja      @@Exit                  ; No, exit\r
+        test    si, si                  ; Text mode?\r
+        jz      @@Exit                  ; Yes, exit\r
+\r
+        dec     si                      ; Skip text mode\r
+        shl     si, 1\r
+        mov     si, TBL_Mode[si]\r
+        cld\r
+\r
+        mov     dx, TS\r
+        mov     ax, 0604h\r
+        out     dx, ax                  ; Disable chain-4 mode\r
+        mov     ax, 0100h\r
+        out     dx, ax                  ; Reset\r
+        mov     dx, MISC\r
+        lodsb\r
+        out     dx, al                  ; New timing/size\r
+        mov     dx, TS\r
+        mov     ax, 0300h\r
+        out     dx, ax                  ; Restart sequencer\r
+\r
+; Unlock CRTC registers 0-7\r
+        mov     dx, CRTC\r
+        mov     al, 11h\r
+        out     dx, al                  ; Vertical sync end register\r
+        inc     dx\r
+        in      al, dx\r
+        and     al, 7Fh                 ; Clear write protect bit\r
+        out     dx, al\r
+\r
+        lodsw                           ; Get X aspect\r
+        mov     [mx_AspectX], ax\r
+        lodsw                           ; Get Y aspect\r
+        mov     [mx_AspectY], ax\r
+        lodsw                           ; Get screen width\r
+        mov     [mx_ScreenWidth], ax\r
+        lodsw                           ; Get screen height\r
+        mov     [mx_ScreenHeight], ax\r
+\r
+; Set CRTC registers\r
+        mov     bx, si\r
+        mov     dx, CRTC\r
+@@TableLoop:\r
+        mov     si, ds:[bx]             ; DS:SI -> table of CRTC registers\r
+        inc     bx\r
+        inc     bx                      ; DS:BX -> offset of next table\r
+        test    si, si                  ; Last table?\r
+        jz      @@EndLoop               ; Yes, exit loop\r
+@@Loop:\r
+        lodsw                           ; Get CRTC register index and value\r
+        test    ax, ax                  ; End of table?\r
+        jz      @@TableLoop             ; Yes, go to next table\r
+        cmp     al, 13h                 ; Row address register?\r
+        je      @@Loop                  ; Yes, ignore it\r
+        out     dx, ax                  ; Set register AL to value AH\r
+        jmp     @@Loop                  ; Get next register/value\r
+@@EndLoop:\r
+\r
+; Lock CRTC registers 0-7 (some cards need this)\r
+        mov     dx, CRTC\r
+        mov     al, 11h\r
+        out     dx, al                  ; Vertical sync end register\r
+        inc     dx\r
+        in      al, dx\r
+        or      al, 80h                 ; Set write protect bit\r
+        out     dx, al\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        mov     ax, [mx_ScreenWidth]\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxChangeMode    ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the aspect ratio for the current mode.\r
+;\r
+; Input:\r
+;       AspectX = pointer to aspect X\r
+;       AspectY = pointer to aspect Y\r
+;\r
+; A rectangle of width AspectX and height AspectY looks like a square.\r
+;\r
+mxGetAspect     PROC FAR\r
+        ARG     AspectY:DWORD,  \\r
+                AspectX:DWORD   = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+        ASSUME  ds:NOTHING\r
+\r
+        lds     si, [AspectX]\r
+        mov     ax, [mx_AspectX]\r
+        mov     ds:[si], ax\r
+        lds     si, [AspectY]\r
+        mov     ax, [mx_AspectY]\r
+        mov     ds:[si], ax\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetAspect     ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current screen size.\r
+;\r
+; Input:\r
+;       Width   = pointer to screen width\r
+;       Height  = pointer to screen height\r
+;\r
+mxGetScreenSize PROC FAR\r
+        ARG     SizeY:DWORD,    \\r
+                SizeX:DWORD     = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+        ASSUME  ds:NOTHING\r
+\r
+        lds     si, [SizeX]\r
+        mov     ax, [mx_ScreenWidth]\r
+        mov     ds:[si], ax\r
+        lds     si, [SizeY]\r
+        mov     ax, [mx_ScreenHeight]\r
+        mov     ds:[si], ax\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetScreenSize ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxsp.asm b/16/xw/mxsp.asm
new file mode 100755 (executable)
index 0000000..1d08e71
--- /dev/null
@@ -0,0 +1,57 @@
+;-----------------------------------------------------------\r
+;\r
+; MXSP.ASM - Set palette function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxSetPalette\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Updates the VGA palette.\r
+;\r
+; Input:\r
+;       Buffer          = pointer to palette data (R,G,B)\r
+;       Start           = index of first color to set\r
+;       Count           = number of color to set\r
+; Output:\r
+;       none\r
+;\r
+mxSetPalette    PROC    FAR\r
+        ARG     Count:WORD,             \\r
+                Start:WORD,             \\r
+                Buffer:DWORD            = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si\r
+\r
+        lds     si, [Buffer]\r
+        mov     cx, [Count]\r
+        mov     ax, [Start]\r
+        mov     dx, 3C8h                ; PEL write address register\r
+        out     dx, al\r
+        inc     dx\r
+        cld\r
+        cli                             ; Disable interrupts\r
+@@Loop:\r
+        lodsb\r
+        out     dx, al                  ; Red\r
+        lodsb\r
+        out     dx, al                  ; Green\r
+        lodsb\r
+        out     dx, al                  ; Blue\r
+        loop    @@Loop                  ; Loop until done\r
+        sti                             ; Enable interrupts\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxSetPalette    ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxss.asm b/16/xw/mxss.asm
new file mode 100755 (executable)
index 0000000..97df736
--- /dev/null
@@ -0,0 +1,72 @@
+;-----------------------------------------------------------\r
+;\r
+; MXSS.ASM - Split screen function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxSplitScreen\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Splits the screen.\r
+;\r
+; Input:\r
+;       Line    = scan line at which screen has to be splitted\r
+; Output:\r
+;       none\r
+;\r
+mxSplitScreen   PROC    FAR\r
+        ARG     Line:WORD       = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+\r
+; Modify the line compare value: bits 0-7 are in the Line Compare\r
+; register (CRTC #18), bit 8 is in the Overflow Low register (CRTC #7)\r
+; and bit 9 is in the Maximum Row Address register (CRTC #9)\r
+        mov     ax, [Line]\r
+        shl     ax, 1                   ; Adjust line for mode "X"\r
+        mov     bh, ah\r
+        mov     bl, ah\r
+        and     bx, 0201h\r
+        mov     cl, 4\r
+        shl     bx, cl\r
+        shl     bh, 1\r
+        mov     dx, CRTC\r
+; Write bits 0-7 to line compare register\r
+        mov     ah, al\r
+        mov     al, 18h\r
+        out     dx, ax\r
+; Write bit 8 to overflow register\r
+        mov     al, 07h\r
+        out     dx, al\r
+        inc     dx\r
+        in      al, dx\r
+        dec     dx\r
+        mov     ah, al\r
+        and     ah, 11101111b\r
+        or      ah, bl\r
+        mov     al, 07h\r
+        out     dx, ax\r
+; Write bit 9 to maximum row address register\r
+        mov     al, 09h\r
+        out     dx, al\r
+        inc     dx\r
+        in      al, dx\r
+        dec     dx\r
+        mov     ah, al\r
+        and     ah, 10111111b\r
+        or      ah, bh\r
+        mov     al, 09h\r
+        out     dx, ax\r
+\r
+        .leave  ARG_SIZE\r
+mxSplitScreen   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxtl.asm b/16/xw/mxtl.asm
new file mode 100755 (executable)
index 0000000..69900c8
--- /dev/null
@@ -0,0 +1,169 @@
+;-----------------------------------------------------------\r
+;\r
+; MXTL.ASM - Put tile\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxPutTile\r
+PUBLIC  mxTransPutTile\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies a "mode-x" tile from memory to screen.\r
+;\r
+; Input:\r
+;       Image   = pointer to tile\r
+;       X, Y    = coordinates of destination\r
+;       Width   = width of image in pixels (Width and 3 = 0)\r
+;       Height  = height of image in pixels\r
+; Output:\r
+;       none\r
+; Note:\r
+;       no clipping is performed on tiles!\r
+;\r
+mxPutTile       PROC    FAR\r
+        ARG     Height:WORD,            \\r
+                Width:WORD,             \\r
+                Y:WORD,                 \\r
+                X:WORD,                 \\r
+                Image:DWORD             = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si, es, di\r
+\r
+        mov     ax, [Y]                 ; Get pixel address\r
+        mul     [mx_BytesPerLine]\r
+        mov     di, [X]\r
+        .shr    di, 2\r
+        add     di, ax\r
+        mov     es, [mx_VideoSegment]\r
+\r
+        lds     si, [Image]             ; Get tile address\r
+        .shr    [Width], 2              ; Number of bytes per plane\r
+        mov     cl, BYTE PTR [X]\r
+        and     cl, 3\r
+        mov     ah, 11h                 ; AH = plane mask\r
+        shl     ah, cl                  ; Align mask to first plane\r
+\r
+        mov     [Y], 4                  ; Number of planes\r
+        mov     bx, [mx_BytesPerLine]\r
+        sub     bx, [Width]             ; Extra bytes per line\r
+@@Loop:\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax                  ; Set write plane\r
+        mov     [X], di                 ; Save video offset\r
+        mov     dx, [Height]\r
+@@Loop2:\r
+        mov     cx, [Width]             ; Number of bytes to move\r
+\r
+        shr     cx, 1                   ; Move line\r
+        rep     movsw\r
+        rcl     cx, 1\r
+        rep     movsb\r
+\r
+        add     di, bx                  ; Move video offset to next line\r
+        dec     dx                      ; Done all lines?\r
+        jnz     @@Loop2                 ; No, continue\r
+        mov     di, [X]                 ; Restore video offset\r
+        rol     ah, 1                   ; Next plane\r
+        adc     di, 0                   ; Bump video offset if needed\r
+        dec     [Y]                     ; Any plane left?\r
+        jnz     @@Loop                  ; Yes, keep looping\r
+\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxPutTile       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies a "mode-x" tile from memory to screen.\r
+; Skips over color 0.\r
+;\r
+; Input:\r
+;       Image   = pointer to tile\r
+;       X, Y    = coordinates of destination\r
+;       Width   = width of image in pixels (Width and 3 = 0)\r
+;       Height  = height of image in pixels\r
+; Output:\r
+;       none\r
+; Note:\r
+;       no clipping is performed on tiles!\r
+;\r
+mxTransPutTile  PROC    FAR\r
+        ARG     Height:WORD,            \\r
+                Width:WORD,             \\r
+                Y:WORD,                 \\r
+                X:WORD,                 \\r
+                Image:DWORD             = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si, es, di\r
+\r
+        mov     ax, [Y]                 ; Get pixel address\r
+        mul     [mx_BytesPerLine]\r
+        mov     di, [X]\r
+        .shr    di, 2\r
+        add     di, ax\r
+        mov     es, [mx_VideoSegment]\r
+\r
+        lds     si, [Image]             ; Get tile address\r
+        .shr    [Width], 2              ; Number of bytes per plane\r
+        mov     cl, BYTE PTR [X]\r
+        and     cl, 3\r
+        mov     ah, 11h                 ; AH = plane mask\r
+        shl     ah, cl                  ; Align mask to first plane\r
+\r
+        mov     [Y], 4                  ; Number of planes\r
+        mov     bx, [mx_BytesPerLine]\r
+        sub     bx, [Width]             ; Extra bytes per line\r
+@@Loop:\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax                  ; Set write plane\r
+        mov     [X], di                 ; Save video offset\r
+        mov     dx, [Height]\r
+@@Loop2:\r
+        mov     cx, [Width]             ; Number of bytes to move\r
+\r
+; Move one line\r
+        jcxz    @@MoveLineDone\r
+@@MoveLineLoop:\r
+        mov     al, ds:[si]\r
+        test    al, al\r
+        jz      @@MoveLineNext\r
+        mov     es:[di], al\r
+@@MoveLineNext:\r
+        inc     si\r
+        inc     di\r
+        dec     cx\r
+        jnz     @@MoveLineLoop\r
+@@MoveLineDone:\r
+\r
+        add     di, bx                  ; Move video offset to next line\r
+        dec     dx                      ; Done all lines?\r
+        jnz     @@Loop2                 ; No, continue\r
+        mov     di, [X]                 ; Restore video offset\r
+        rol     ah, 1                   ; Next plane\r
+        adc     di, 0                   ; Bump video offset if needed\r
+        dec     [Y]                     ; Any plane left?\r
+        jnz     @@Loop                  ; Yes, keep looping\r
+\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxTransPutTile  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxvs.asm b/16/xw/mxvs.asm
new file mode 100755 (executable)
index 0000000..992eaba
--- /dev/null
@@ -0,0 +1,110 @@
+;-----------------------------------------------------------\r
+;\r
+; MXVS.ASM - Set/get virtual screen\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxSetVirtualScreen\r
+PUBLIC  mxGetVirtualScreen\r
+\r
+EXTRN   mxRowAddress            : FAR\r
+EXTRN   mxSetSysClipRegion      : FAR\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_BytesPerLine : WORD\r
+EXTRN   mx_CodeSegment  : WORD\r
+\r
+mx_VirtualWidth         DW      ?       ; Virtual screen size\r
+mx_VirtualHeight        DW      ?\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the virtual screen.\r
+;\r
+; Input:\r
+;       Width   = virtual screen width\r
+;       Height  = virtual screen height\r
+; Output:\r
+;       0 on success, else invalid parameters\r
+;\r
+mxSetVirtualScreen      PROC    FAR\r
+        ARG     Height:WORD,            \\r
+                Width:WORD              = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds\r
+\r
+; Set DS to code segment\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, 1                   ; Assume an error\r
+        cmp     [Width], 320            ; Check width\r
+        jb      @@Exit\r
+        push    ax                      ; Save return code\r
+        mov     dx, 0004h\r
+        xor     ax, ax                  ; DX:AX = 256K\r
+        div     [Width]                 ; Max height in AX\r
+        cmp     [Height], ax\r
+        pop     ax                      ; Restore return code\r
+        ja      @@Exit                  ; Exit if bad heigth\r
+\r
+        mov     ax, [Width]\r
+        and     ax, 0FFF8h              ; Align to byte\r
+        mov     [mx_VirtualWidth], ax\r
+        shr     ax, 1\r
+        shr     ax, 1\r
+        mov     [mx_BytesPerLine], ax\r
+        shr     ax, 1\r
+        push    ax\r
+        call    mxRowAddress            ; Set row address\r
+        mov     ax, [Height]\r
+        mov     [mx_VirtualHeight], ax\r
+\r
+        push    [Width]\r
+        push    [Height]\r
+        call    mxSetSysClipRegion\r
+        xor     ax, ax\r
+\r
+@@Exit:\r
+        .pop    ds\r
+        .leave  ARG_SIZE\r
+mxSetVirtualScreen      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the current virtual screen size.\r
+;\r
+; Input:\r
+;       Width   = pointer to virtual screen width\r
+;       Height  = pointer to virtual screen height\r
+; Output:\r
+;       none\r
+;\r
+mxGetVirtualScreen      PROC    FAR\r
+        ARG     Height:DWORD,           \\r
+                Width:DWORD             = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        .push   ds, si\r
+\r
+        mov     ax, [mx_VirtualWidth]\r
+        lds     si, [Width]\r
+        mov     ds:[si], ax\r
+        mov     ax, [mx_VirtualHeight]\r
+        lds     si, [Height]\r
+        mov     ds:[si], ax\r
+\r
+        xor     ax, ax\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetVirtualScreen      ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxwd.asm b/16/xw/mxwd.asm
new file mode 100755 (executable)
index 0000000..de55208
--- /dev/null
@@ -0,0 +1,28 @@
+;-----------------------------------------------------------\r
+;\r
+; MXWD.ASM - Wait display function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxWaitDisplay\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Waits for display start.\r
+;\r
+mxWaitDisplay   PROC    FAR\r
+        mov     dx, STATUS\r
+@@1:    in      al, dx\r
+        test    al, 08h\r
+        jnz     @@1\r
+        ret\r
+mxWaitDisplay   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxwm.asm b/16/xw/mxwm.asm
new file mode 100755 (executable)
index 0000000..0615885
--- /dev/null
@@ -0,0 +1,39 @@
+;-----------------------------------------------------------\r
+;\r
+; MXWM.ASM - Set write mode function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxWriteMode\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the write mode.\r
+;\r
+; Input:\r
+;       Mode    = write mode (0,1,2,3)\r
+; Output:\r
+;       none\r
+;\r
+mxWriteMode     PROC    FAR\r
+        ARG     Mode:BYTE:2     = ARG_SIZE\r
+        .enter  0\r
+\r
+        mov     dx, GDC\r
+        mov     ah, [Mode]\r
+        and     ah, 00000011b\r
+        or      ah, 01000000b\r
+        mov     al, 05h\r
+        out     dx, ax\r
+\r
+        .leave  ARG_SIZE\r
+mxWriteMode     ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxwp.asm b/16/xw/mxwp.asm
new file mode 100755 (executable)
index 0000000..19ca99d
--- /dev/null
@@ -0,0 +1,62 @@
+;-----------------------------------------------------------\r
+;\r
+; MXWP.ASM - Set write/read plane functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxWritePlane\r
+PUBLIC  mxReadPlane\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the write plane(s).\r
+;\r
+; Input:\r
+;       Plane   = write plane(s) to set (bit 0 enables plane 0,\r
+;                 bit 1 enables plane 1 and so on, different planes\r
+;                 may be selected at the same time)\r
+; Output:\r
+;       none\r
+;\r
+mxWritePlane    PROC    FAR\r
+        ARG     Plane:BYTE:2    = ARG_SIZE\r
+        .enter  0\r
+\r
+        mov     ah, [Plane]\r
+        and     ah, 00001111b           ; Mask off unused bits\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax\r
+\r
+        .leave  ARG_SIZE\r
+mxWritePlane    ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the read plane.\r
+;\r
+; Input:\r
+;       Plane   = read plane to set (0,1,2,3)\r
+; Output:\r
+;       none\r
+;\r
+mxReadPlane     PROC    FAR\r
+        ARG     Plane:BYTE:2    = ARG_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  0\r
+        mov     al, 04h\r
+        mov     ah, [Plane]\r
+        and     ah, 0000011b            ; Mask off unused bits\r
+        mov     dx, GDC\r
+        out     dx, ax\r
+        .leave  ARG_SIZE\r
+mxReadPlane     ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/mxwr.asm b/16/xw/mxwr.asm
new file mode 100755 (executable)
index 0000000..bd29fe5
--- /dev/null
@@ -0,0 +1,28 @@
+;-----------------------------------------------------------\r
+;\r
+; MXWR.ASM - Wait vertical retrace function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxWaitRetrace\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Waits for vertical retrace start.\r
+;\r
+mxWaitRetrace   PROC    FAR\r
+        mov     dx, STATUS\r
+@@1:    in      al,dx\r
+        test    al, 08h\r
+        jz      @@1\r
+        ret\r
+mxWaitRetrace   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw/readme.txt b/16/xw/readme.txt
new file mode 100755 (executable)
index 0000000..306e8b9
--- /dev/null
@@ -0,0 +1,8 @@
+ModeX - A graphical library for DOS programs\r
+Copyright (c) 1993-1994 Alessandro Scotti\r
+http://www.ascotti.org/\r
+\r
+Please look at the above site in the "Art of..." and\r
+then in the "Old programs" section for more information.\r
+\r
+\r
diff --git a/16/xw_/default.fnt b/16/xw_/default.fnt
new file mode 100755 (executable)
index 0000000..12eb22c
--- /dev/null
@@ -0,0 +1,260 @@
+;\r
+; MODEX library default font\r
+; Copyright (c) 1993-1994 by Alessandro Scotti\r
+;\r
+  DB    000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h  ; #0\r
+  DB   07Eh, 081h, 0A5h, 081h, 0A5h, 099h, 081h, 07Eh  ; #1\r
+  DB   07Eh, 0FFh, 0DBh, 0FFh, 0DBh, 0E7h, 0FFh, 07Eh  ; #2\r
+  DB   06Ch, 0FEh, 0FEh, 0FEh, 07Ch, 038h, 010h, 000h  ; #3\r
+  DB   010h, 038h, 07Ch, 0FEh, 07Ch, 038h, 010h, 000h  ; #4\r
+  DB   010h, 038h, 010h, 054h, 0FEh, 054h, 010h, 0FEh  ; #5\r
+  DB   010h, 038h, 07Ch, 0FEh, 0FEh, 07Ch, 010h, 0FEh  ; #6\r
+  DB   000h, 018h, 03Ch, 07Eh, 07Eh, 03Ch, 018h, 000h  ; #7\r
+  DB   0FFh, 0E7h, 0C3h, 081h, 081h, 0C3h, 0E7h, 0FFh  ; #8\r
+  DB   000h, 03Ch, 066h, 042h, 042h, 066h, 03Ch, 000h  ; #9\r
+  DB   0FFh, 0C3h, 099h, 0BDh, 0BDh, 099h, 0C3h, 0FFh  ; #10\r
+  DB   007h, 003h, 005h, 078h, 084h, 084h, 084h, 078h  ; #11\r
+  DB   07Ch, 082h, 082h, 082h, 07Ch, 010h, 038h, 010h  ; #12\r
+  DB   01Ch, 010h, 01Ch, 010h, 010h, 010h, 030h, 030h  ; #13\r
+  DB   03Eh, 022h, 03Eh, 022h, 022h, 026h, 066h, 060h  ; #14\r
+  DB   099h, 05Ah, 03Ch, 0E7h, 0E7h, 03Ch, 05Ah, 099h  ; #15\r
+  DB   000h, 010h, 030h, 070h, 0F0h, 070h, 030h, 010h  ; #16\r
+  DB   000h, 080h, 0C0h, 0E0h, 0F0h, 0E0h, 0C0h, 080h  ; #17\r
+  DB   010h, 038h, 054h, 010h, 010h, 054h, 038h, 010h  ; #18\r
+  DB   048h, 048h, 048h, 048h, 048h, 000h, 048h, 000h  ; #19\r
+  DB   07Eh, 092h, 092h, 072h, 012h, 012h, 012h, 000h  ; #20\r
+  DB   03Ch, 022h, 018h, 024h, 024h, 018h, 044h, 03Ch  ; #21\r
+  DB   000h, 000h, 000h, 000h, 000h, 03Eh, 03Eh, 000h  ; #22\r
+  DB   038h, 054h, 010h, 010h, 010h, 054h, 038h, 0FEh  ; #23\r
+  DB   000h, 010h, 038h, 054h, 010h, 010h, 010h, 000h  ; #24\r
+  DB   000h, 010h, 010h, 010h, 054h, 038h, 010h, 000h  ; #25\r
+  DB   000h, 008h, 004h, 0FEh, 004h, 008h, 000h, 000h  ; #26\r
+  DB   000h, 020h, 040h, 0FEh, 040h, 020h, 000h, 000h  ; #27\r
+  DB   000h, 000h, 080h, 080h, 080h, 0FCh, 000h, 000h  ; #28\r
+  DB   000h, 024h, 042h, 0FFh, 042h, 024h, 000h, 000h  ; #29\r
+  DB   000h, 000h, 010h, 038h, 07Ch, 0FEh, 000h, 000h  ; #30\r
+  DB   000h, 000h, 0FEh, 07Ch, 038h, 010h, 000h, 000h  ; #31\r
+  DB   000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h  ;  \r
+  DB   010h, 010h, 010h, 010h, 010h, 000h, 010h, 000h  ; !\r
+  DB   000h, 024h, 024h, 000h, 000h, 000h, 000h, 000h  ; "\r
+  DB   024h, 024h, 07Eh, 024h, 07Eh, 024h, 024h, 000h  ; #\r
+  DB   038h, 054h, 050h, 038h, 014h, 054h, 038h, 010h  ; $\r
+  DB   000h, 002h, 044h, 008h, 010h, 020h, 042h, 000h  ; %\r
+  DB   038h, 044h, 038h, 060h, 094h, 088h, 074h, 000h  ; &\r
+  DB   020h, 020h, 040h, 000h, 000h, 000h, 000h, 000h  ; '\r
+  DB   010h, 020h, 040h, 040h, 040h, 020h, 010h, 000h  ; (\r
+  DB   040h, 020h, 010h, 010h, 010h, 020h, 040h, 000h  ; )\r
+  DB   000h, 024h, 018h, 07Eh, 018h, 024h, 000h, 000h  ; *\r
+  DB   000h, 010h, 010h, 07Ch, 010h, 010h, 000h, 000h  ; +\r
+  DB   000h, 000h, 000h, 000h, 000h, 010h, 010h, 020h  ; ,\r
+  DB   000h, 000h, 000h, 0FCh, 000h, 000h, 000h, 000h  ; -\r
+  DB   000h, 000h, 000h, 000h, 000h, 000h, 010h, 000h  ; .\r
+  DB   000h, 004h, 008h, 010h, 020h, 040h, 080h, 000h  ; /\r
+  DB   07Ch, 0C6h, 08Ah, 092h, 0A2h, 0C6h, 07Ch, 000h  ; 0\r
+  DB   010h, 030h, 010h, 010h, 010h, 010h, 038h, 000h  ; 1\r
+  DB   078h, 084h, 004h, 018h, 060h, 080h, 0FCh, 000h  ; 2\r
+  DB   078h, 084h, 004h, 038h, 004h, 084h, 078h, 000h  ; 3\r
+  DB   01Ch, 024h, 044h, 084h, 0FEh, 004h, 00Eh, 000h  ; 4\r
+  DB   0FCh, 080h, 0F8h, 004h, 004h, 084h, 078h, 000h  ; 5\r
+  DB   078h, 084h, 080h, 0F8h, 084h, 084h, 078h, 000h  ; 6\r
+  DB   0FCh, 004h, 004h, 008h, 010h, 020h, 020h, 000h  ; 7\r
+  DB   078h, 084h, 084h, 078h, 084h, 084h, 078h, 000h  ; 8\r
+  DB   078h, 084h, 084h, 07Ch, 004h, 084h, 078h, 000h  ; 9\r
+  DB   000h, 000h, 010h, 000h, 000h, 000h, 010h, 000h  ; :\r
+  DB   000h, 000h, 010h, 000h, 000h, 010h, 010h, 020h  ; ;\r
+  DB   008h, 010h, 020h, 040h, 020h, 010h, 008h, 000h  ; <\r
+  DB   000h, 000h, 0FCh, 000h, 000h, 0FCh, 000h, 000h  ; =\r
+  DB   040h, 020h, 010h, 008h, 010h, 020h, 040h, 000h  ; >\r
+  DB   078h, 084h, 004h, 008h, 010h, 000h, 010h, 000h  ; ?\r
+  DB   07Ch, 082h, 0BAh, 0A6h, 0BEh, 080h, 07Ch, 000h  ; @\r
+  DB   078h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h  ; A\r
+  DB   0F8h, 084h, 084h, 0F8h, 084h, 084h, 0F8h, 000h  ; B\r
+  DB   078h, 084h, 080h, 080h, 080h, 084h, 078h, 000h  ; C\r
+  DB   0F0h, 088h, 084h, 084h, 084h, 088h, 0F0h, 000h  ; D\r
+  DB   0FCh, 080h, 080h, 0F0h, 080h, 080h, 0FCh, 000h  ; E\r
+  DB   0FCh, 080h, 080h, 0F0h, 080h, 080h, 080h, 000h  ; F\r
+  DB   078h, 084h, 080h, 09Ch, 084h, 084h, 078h, 000h  ; G\r
+  DB   084h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h  ; H\r
+  DB   038h, 010h, 010h, 010h, 010h, 010h, 038h, 000h  ; I\r
+  DB   01Ch, 008h, 008h, 008h, 088h, 088h, 070h, 000h  ; J\r
+  DB   084h, 088h, 090h, 0E0h, 090h, 088h, 084h, 000h  ; K\r
+  DB   080h, 080h, 080h, 080h, 080h, 080h, 0FCh, 000h  ; L\r
+  DB   0C6h, 0AAh, 092h, 082h, 082h, 082h, 082h, 000h  ; M\r
+  DB   082h, 0C2h, 0A2h, 092h, 08Ah, 086h, 082h, 000h  ; N\r
+  DB   078h, 084h, 084h, 084h, 084h, 084h, 078h, 000h  ; O\r
+  DB   0F8h, 084h, 084h, 0F8h, 080h, 080h, 080h, 000h  ; P\r
+  DB   078h, 084h, 084h, 084h, 094h, 088h, 076h, 000h  ; Q\r
+  DB   0F8h, 084h, 084h, 0F8h, 090h, 088h, 084h, 000h  ; R\r
+  DB   078h, 084h, 080h, 078h, 004h, 084h, 078h, 000h  ; S\r
+  DB   0FEh, 010h, 010h, 010h, 010h, 010h, 010h, 000h  ; T\r
+  DB   084h, 084h, 084h, 084h, 084h, 084h, 078h, 000h  ; U\r
+  DB   084h, 084h, 084h, 084h, 084h, 048h, 030h, 000h  ; V\r
+  DB   082h, 082h, 082h, 082h, 092h, 0AAh, 0C6h, 000h  ; W\r
+  DB   082h, 044h, 028h, 010h, 028h, 044h, 082h, 000h  ; X\r
+  DB   044h, 044h, 044h, 038h, 010h, 010h, 010h, 000h  ; Y\r
+  DB   0FEh, 004h, 008h, 010h, 020h, 040h, 0FEh, 000h  ; Z\r
+  DB   078h, 040h, 040h, 040h, 040h, 040h, 078h, 000h  ; [\r
+  DB   000h, 080h, 040h, 020h, 010h, 008h, 004h, 000h  ; \\r
+  DB   078h, 008h, 008h, 008h, 008h, 008h, 078h, 000h  ; ]\r
+  DB   010h, 028h, 044h, 082h, 000h, 000h, 000h, 000h  ; ^\r
+  DB   000h, 000h, 000h, 000h, 000h, 000h, 000h, 0FFh  ; _\r
+  DB   020h, 020h, 010h, 000h, 000h, 000h, 000h, 000h  ; `\r
+  DB   000h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; a\r
+  DB   000h, 040h, 040h, 078h, 044h, 044h, 078h, 000h  ; b\r
+  DB   000h, 000h, 03Ch, 040h, 040h, 040h, 03Ch, 000h  ; c\r
+  DB   000h, 004h, 004h, 03Ch, 044h, 044h, 03Ch, 000h  ; d\r
+  DB   000h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h  ; e\r
+  DB   000h, 00Ch, 010h, 03Ch, 010h, 010h, 010h, 000h  ; f\r
+  DB   000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 038h  ; g\r
+  DB   000h, 040h, 040h, 078h, 044h, 044h, 044h, 000h  ; h\r
+  DB   000h, 010h, 000h, 010h, 010h, 010h, 010h, 000h  ; i\r
+  DB   000h, 004h, 000h, 004h, 004h, 004h, 044h, 038h  ; j\r
+  DB   000h, 040h, 040h, 050h, 060h, 050h, 048h, 000h  ; k\r
+  DB   000h, 030h, 010h, 010h, 010h, 010h, 010h, 000h  ; l\r
+  DB   000h, 000h, 068h, 054h, 054h, 044h, 044h, 000h  ; m\r
+  DB   000h, 000h, 078h, 044h, 044h, 044h, 044h, 000h  ; n\r
+  DB   000h, 000h, 038h, 044h, 044h, 044h, 038h, 000h  ; o\r
+  DB   000h, 000h, 078h, 044h, 044h, 078h, 040h, 040h  ; p\r
+  DB   000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 004h  ; q\r
+  DB   000h, 000h, 05Ch, 060h, 040h, 040h, 040h, 000h  ; r\r
+  DB   000h, 000h, 038h, 040h, 07Ch, 004h, 07Ch, 000h  ; s\r
+  DB   000h, 010h, 038h, 010h, 010h, 010h, 018h, 000h  ; t\r
+  DB   000h, 000h, 044h, 044h, 044h, 044h, 038h, 000h  ; u\r
+  DB   000h, 000h, 044h, 044h, 044h, 028h, 010h, 000h  ; v\r
+  DB   000h, 000h, 044h, 044h, 054h, 054h, 06Ch, 000h  ; w\r
+  DB   000h, 000h, 044h, 028h, 010h, 028h, 044h, 000h  ; x\r
+  DB   000h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch  ; y\r
+  DB   000h, 000h, 07Ch, 004h, 038h, 040h, 07Ch, 000h  ; z\r
+  DB   000h, 008h, 010h, 010h, 030h, 010h, 010h, 008h  ; {\r
+  DB   000h, 010h, 010h, 010h, 000h, 010h, 010h, 010h  ; |\r
+  DB   000h, 020h, 010h, 010h, 018h, 010h, 010h, 020h  ; }\r
+  DB   064h, 098h, 000h, 000h, 000h, 000h, 000h, 000h  ; ~\r
+  DB   000h, 010h, 028h, 044h, 082h, 082h, 0FEh, 000h  ; \7f\r
+  DB   07Ch, 080h, 080h, 080h, 080h, 07Ch, 004h, 07Ch  ; #128\r
+  DB   000h, 028h, 000h, 044h, 044h, 044h, 038h, 000h  ; #129\r
+  DB   03Ch, 000h, 07Ch, 044h, 07Ch, 040h, 07Ch, 000h  ; #130\r
+  DB   07Eh, 081h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #131\r
+  DB   024h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #132\r
+  DB   078h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #133\r
+  DB   018h, 018h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #134\r
+  DB   000h, 000h, 078h, 080h, 080h, 078h, 008h, 038h  ; #135\r
+  DB   07Ch, 082h, 038h, 044h, 07Ch, 040h, 03Ch, 000h  ; #136\r
+  DB   048h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h  ; #137\r
+  DB   078h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h  ; #138\r
+  DB   000h, 028h, 000h, 010h, 010h, 010h, 010h, 000h  ; #139\r
+  DB   010h, 028h, 000h, 010h, 010h, 010h, 010h, 000h  ; #140\r
+  DB   000h, 030h, 000h, 010h, 010h, 010h, 010h, 000h  ; #141\r
+  DB   048h, 000h, 078h, 084h, 0FCh, 084h, 084h, 000h  ; #142\r
+  DB   030h, 030h, 078h, 084h, 0FCh, 084h, 084h, 000h  ; #143\r
+  DB   038h, 000h, 0FCh, 080h, 0F0h, 080h, 0FCh, 000h  ; #144\r
+  DB   000h, 000h, 07Eh, 008h, 07Eh, 048h, 07Eh, 000h  ; #145\r
+  DB   07Eh, 090h, 090h, 0FCh, 090h, 090h, 09Eh, 000h  ; #146\r
+  DB   07Ch, 082h, 038h, 044h, 044h, 044h, 038h, 000h  ; #147\r
+  DB   028h, 000h, 038h, 044h, 044h, 044h, 038h, 000h  ; #148\r
+  DB   070h, 000h, 038h, 044h, 044h, 044h, 038h, 000h  ; #149\r
+  DB   038h, 044h, 000h, 044h, 044h, 044h, 038h, 000h  ; #150\r
+  DB   070h, 000h, 044h, 044h, 044h, 044h, 038h, 000h  ; #151\r
+  DB   028h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch  ; #152\r
+  DB   048h, 000h, 078h, 084h, 084h, 084h, 078h, 000h  ; #153\r
+  DB   048h, 000h, 084h, 084h, 084h, 084h, 078h, 000h  ; #154\r
+  DB   000h, 010h, 038h, 040h, 040h, 040h, 038h, 010h  ; #155\r
+  DB   038h, 044h, 040h, 0E0h, 040h, 040h, 082h, 0FCh  ; #156\r
+  DB   044h, 07Ch, 010h, 07Ch, 010h, 07Ch, 010h, 000h  ; #157\r
+  DB   0F0h, 088h, 08Ah, 0F7h, 082h, 082h, 082h, 000h  ; #158\r
+  DB   00Ch, 012h, 010h, 018h, 030h, 010h, 090h, 060h  ; #159\r
+  DB   03Ch, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #160\r
+  DB   000h, 018h, 000h, 010h, 010h, 010h, 010h, 000h  ; #161\r
+  DB   01Ch, 000h, 038h, 044h, 044h, 044h, 038h, 000h  ; #162\r
+  DB   01Ch, 000h, 044h, 044h, 044h, 044h, 038h, 000h  ; #163\r
+  DB   07Ch, 000h, 078h, 044h, 044h, 044h, 044h, 000h  ; #164\r
+  DB   07Ch, 000h, 044h, 064h, 054h, 04Ch, 044h, 000h  ; #165\r
+  DB   018h, 024h, 024h, 01Eh, 000h, 03Eh, 000h, 000h  ; #166\r
+  DB   01Ch, 022h, 022h, 01Ch, 000h, 03Eh, 000h, 000h  ; #167\r
+  DB   010h, 000h, 010h, 020h, 040h, 042h, 03Ch, 000h  ; #168\r
+  DB   000h, 000h, 000h, 0FCh, 080h, 080h, 000h, 000h  ; #169\r
+  DB   000h, 000h, 000h, 0FCh, 004h, 004h, 000h, 000h  ; #170\r
+  DB   040h, 044h, 048h, 057h, 021h, 047h, 004h, 007h  ; #171\r
+  DB   040h, 044h, 048h, 052h, 026h, 04Ah, 01Fh, 002h  ; #172\r
+  DB   010h, 000h, 010h, 010h, 010h, 010h, 010h, 000h  ; #173\r
+  DB   000h, 024h, 048h, 090h, 048h, 024h, 000h, 000h  ; #174\r
+  DB   000h, 048h, 024h, 012h, 024h, 048h, 000h, 000h  ; #175\r
+  DB   022h, 088h, 022h, 088h, 022h, 088h, 022h, 088h  ; #176\r
+  DB   055h, 0AAh, 055h, 0AAh, 055h, 0AAh, 055h, 0AAh  ; #177\r
+  DB   0DBh, 077h, 0DBh, 0EEh, 0DBh, 077h, 0DBh, 0EEh  ; #178\r
+  DB   018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h  ; #179\r
+  DB   018h, 018h, 018h, 018h, 0F8h, 018h, 018h, 018h  ; #180\r
+  DB   018h, 018h, 0F8h, 018h, 0F8h, 018h, 018h, 018h  ; #181\r
+  DB   036h, 036h, 036h, 036h, 0F6h, 036h, 036h, 036h  ; #182\r
+  DB   000h, 000h, 000h, 000h, 0FEh, 036h, 036h, 036h  ; #183\r
+  DB   000h, 000h, 0F8h, 018h, 0F8h, 018h, 018h, 018h  ; #184\r
+  DB   036h, 036h, 0F6h, 006h, 0F6h, 036h, 036h, 036h  ; #185\r
+  DB   036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h  ; #186\r
+  DB   000h, 000h, 0FEh, 006h, 0F6h, 036h, 036h, 036h  ; #187\r
+  DB   036h, 036h, 0F6h, 006h, 0FEh, 000h, 000h, 000h  ; #188\r
+  DB   036h, 036h, 036h, 036h, 0FEh, 000h, 000h, 000h  ; #189\r
+  DB   018h, 018h, 0F8h, 018h, 0F8h, 000h, 000h, 000h  ; #190\r
+  DB   000h, 000h, 000h, 000h, 0F8h, 018h, 018h, 018h  ; #191\r
+  DB   018h, 018h, 018h, 018h, 01Fh, 000h, 000h, 000h  ; #192\r
+  DB   018h, 018h, 018h, 018h, 0FFh, 000h, 000h, 000h  ; #193\r
+  DB   000h, 000h, 000h, 000h, 0FFh, 018h, 018h, 018h  ; #194\r
+  DB   018h, 018h, 018h, 018h, 01Fh, 018h, 018h, 018h  ; #195\r
+  DB   000h, 000h, 000h, 000h, 0FFh, 000h, 000h, 000h  ; #196\r
+  DB   018h, 018h, 018h, 018h, 0FFh, 018h, 018h, 018h  ; #197\r
+  DB   018h, 018h, 01Fh, 018h, 01Fh, 018h, 018h, 018h  ; #198\r
+  DB   036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h  ; #199\r
+  DB   036h, 036h, 037h, 030h, 03Fh, 000h, 000h, 000h  ; #200\r
+  DB   000h, 000h, 03Fh, 030h, 037h, 036h, 036h, 036h  ; #201\r
+  DB   036h, 036h, 0F7h, 000h, 0FFh, 000h, 000h, 000h  ; #202\r
+  DB   000h, 000h, 0FFh, 000h, 0F7h, 036h, 036h, 036h  ; #203\r
+  DB   036h, 036h, 037h, 030h, 037h, 036h, 036h, 036h  ; #204\r
+  DB   000h, 000h, 0FFh, 000h, 0FFh, 000h, 000h, 000h  ; #205\r
+  DB   036h, 036h, 0F7h, 000h, 0F7h, 036h, 036h, 036h  ; #206\r
+  DB   018h, 018h, 0FFh, 000h, 0FFh, 000h, 000h, 000h  ; #207\r
+  DB   036h, 036h, 036h, 036h, 0FFh, 000h, 000h, 000h  ; #208\r
+  DB   000h, 000h, 0FFh, 000h, 0FFh, 018h, 018h, 018h  ; #209\r
+  DB   000h, 000h, 000h, 000h, 0FFh, 036h, 036h, 036h  ; #210\r
+  DB   036h, 036h, 036h, 036h, 03Fh, 000h, 000h, 000h  ; #211\r
+  DB   018h, 018h, 01Fh, 018h, 01Fh, 000h, 000h, 000h  ; #212\r
+  DB   000h, 000h, 01Fh, 018h, 01Fh, 018h, 018h, 018h  ; #213\r
+  DB   000h, 000h, 000h, 000h, 03Fh, 036h, 036h, 036h  ; #214\r
+  DB   036h, 036h, 036h, 036h, 0FFh, 036h, 036h, 036h  ; #215\r
+  DB   018h, 018h, 0FFh, 018h, 0FFh, 018h, 018h, 018h  ; #216\r
+  DB   018h, 018h, 018h, 018h, 0F8h, 000h, 000h, 000h  ; #217\r
+  DB   000h, 000h, 000h, 000h, 01Fh, 018h, 018h, 018h  ; #218\r
+  DB   0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh  ; #219\r
+  DB   000h, 000h, 000h, 000h, 0FFh, 0FFh, 0FFh, 0FFh  ; #220\r
+  DB   0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h  ; #221\r
+  DB   00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh  ; #222\r
+  DB   0FFh, 0FFh, 0FFh, 0FFh, 000h, 000h, 000h, 000h  ; #223\r
+  DB   000h, 000h, 062h, 094h, 088h, 094h, 062h, 000h  ; #224\r
+  DB   000h, 0F0h, 088h, 0F0h, 088h, 088h, 0F0h, 080h  ; #225\r
+  DB   000h, 0F8h, 088h, 080h, 080h, 080h, 080h, 000h  ; #226\r
+  DB   000h, 0FCh, 048h, 048h, 048h, 048h, 048h, 000h  ; #227\r
+  DB   0FCh, 084h, 040h, 020h, 040h, 084h, 0FCh, 000h  ; #228\r
+  DB   03Ch, 040h, 038h, 044h, 044h, 044h, 038h, 000h  ; #229\r
+  DB   000h, 000h, 044h, 044h, 044h, 078h, 040h, 040h  ; #230\r
+  DB   000h, 036h, 048h, 008h, 008h, 008h, 008h, 000h  ; #231\r
+  DB   038h, 010h, 038h, 044h, 044h, 038h, 010h, 038h  ; #232\r
+  DB   078h, 084h, 084h, 0FCh, 084h, 084h, 078h, 000h  ; #233\r
+  DB   078h, 084h, 084h, 084h, 048h, 048h, 0CCh, 000h  ; #234\r
+  DB   078h, 004h, 038h, 044h, 044h, 044h, 038h, 000h  ; #235\r
+  DB   000h, 000h, 06Ch, 092h, 092h, 06Ch, 000h, 000h  ; #236\r
+  DB   000h, 000h, 03Ah, 044h, 05Ah, 022h, 05Ch, 000h  ; #237\r
+  DB   018h, 020h, 040h, 078h, 040h, 020h, 018h, 000h  ; #238\r
+  DB   078h, 084h, 084h, 084h, 084h, 084h, 084h, 000h  ; #239\r
+  DB   000h, 0FCh, 000h, 0FCh, 000h, 0FCh, 000h, 000h  ; #240\r
+  DB   020h, 020h, 0F8h, 020h, 020h, 000h, 0F8h, 000h  ; #241\r
+  DB   020h, 010h, 008h, 010h, 020h, 000h, 07Ch, 000h  ; #242\r
+  DB   008h, 010h, 020h, 010h, 008h, 000h, 07Ch, 000h  ; #243\r
+  DB   00Ch, 012h, 010h, 010h, 010h, 010h, 010h, 010h  ; #244\r
+  DB   010h, 010h, 010h, 010h, 010h, 010h, 090h, 060h  ; #245\r
+  DB   000h, 010h, 000h, 07Ch, 000h, 010h, 000h, 000h  ; #246\r
+  DB   000h, 032h, 04Ch, 000h, 032h, 04Ch, 000h, 000h  ; #247\r
+  DB   038h, 044h, 044h, 038h, 000h, 000h, 000h, 000h  ; #248\r
+  DB   000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h  ; #249\r
+  DB   000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h  ; #250\r
+  DB   00Eh, 008h, 008h, 008h, 048h, 028h, 018h, 008h  ; #251\r
+  DB   038h, 024h, 024h, 024h, 024h, 000h, 000h, 000h  ; #252\r
+  DB   03Ch, 004h, 03Ch, 020h, 03Ch, 000h, 000h, 000h  ; #253\r
+  DB   000h, 000h, 03Ch, 03Ch, 03Ch, 03Ch, 000h, 000h  ; #254\r
+  DB   000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h  ; #255\r
diff --git a/16/xw_/makefile b/16/xw_/makefile
new file mode 100755 (executable)
index 0000000..cfe1523
--- /dev/null
@@ -0,0 +1,132 @@
+#\r
+# MODEX library makefile (for Borland MAKE)\r
+# Copyright (c) 1993,1994 by Alessandro Scotti\r
+#\r
+!ifdef __LINUX__\r
+REMOVECOMMAND=rm -f\r
+COPYCOMMAND=cp -f\r
+DIRSEP=/\r
+OBJ=o\r
+!else\r
+REMOVECOMMAND=del\r
+COPYCOMMAND=copy /y\r
+DIRSEP=\\r
+OBJ=obj\r
+!endif\r
+LIBINCS = modex.def\r
+\r
+LIBOBJS = mxbb.$(OBJ) mxcc.$(OBJ) mxcg.$(OBJ) mxcl.$(OBJ) mxcr.$(OBJ) mxfb.$(OBJ) mxgc.$(OBJ) mxgi.$(OBJ) mxgm.$(OBJ) mxgp.$(OBJ) mxgv.$(OBJ) mxhl.$(OBJ) mxit.$(OBJ) mxll.$(OBJ) mxln.$(OBJ) mxot.$(OBJ) mxpb.$(OBJ) mxpf.$(OBJ) mxpg.$(OBJ) mxpi.$(OBJ) mxpn.$(OBJ) mxpp.$(OBJ) mxra.$(OBJ) mxrp.$(OBJ) mxsa.$(OBJ) mxsc.$(OBJ) mxsi.$(OBJ) mxsl.$(OBJ) mxsm.$(OBJ) mxsp.$(OBJ) mxss.$(OBJ) mxtl.$(OBJ) mxvs.$(OBJ) mxwd.$(OBJ) mxwm.$(OBJ) mxwp.$(OBJ) mxwr.$(OBJ)\r
+#mxfp.$(OBJ) \r
+#\r
+# ASM compiler\r
+#\r
+ASMC =wasm\r
+ASMO =-mh -0\r
+\r
+#\r
+# PAS compiler\r
+#\r
+#PASC = tpc\r
+#PASO = /m -$D- -$L- -$S-\r
+\r
+#\r
+# LIB maker, uses response file\r
+#\r
+LIBC = wlib\r
+\r
+# .asm.obj:\r
+#              $(ASMC) $(ASMO) $<\r
+\r
+mxbb.$(OBJ): mxbb.asm\r
+       $(ASMC) $(ASMO) mxbb.asm\r
+mxcc.$(OBJ): mxcc.asm\r
+       $(ASMC) $(ASMO) mxcc.asm\r
+mxcg.$(OBJ): mxcg.asm\r
+       $(ASMC) $(ASMO) mxcg.asm\r
+mxcl.$(OBJ): mxcl.asm\r
+       $(ASMC) $(ASMO) mxcl.asm\r
+mxcr.$(OBJ): mxcr.asm\r
+       $(ASMC) $(ASMO) mxcr.asm\r
+mxfb.$(OBJ): mxfb.asm\r
+       $(ASMC) $(ASMO) mxfb.asm\r
+mxfp.$(OBJ): mxfp.asm\r
+       $(ASMC) $(ASMO) mxfp.asm\r
+mxgc.$(OBJ): mxgc.asm\r
+       $(ASMC) $(ASMO) mxgc.asm\r
+mxgi.$(OBJ): mxgi.asm\r
+       $(ASMC) $(ASMO) mxgi.asm\r
+mxgm.$(OBJ): mxgm.asm\r
+       $(ASMC) $(ASMO) mxgm.asm\r
+mxgp.$(OBJ): mxgp.asm\r
+       $(ASMC) $(ASMO) mxgp.asm\r
+mxgv.$(OBJ): mxgv.asm\r
+       $(ASMC) $(ASMO) mxgv.asm\r
+mxhl.$(OBJ): mxhl.asm\r
+       $(ASMC) $(ASMO) mxhl.asm\r
+mxit.$(OBJ): mxit.asm\r
+       $(ASMC) $(ASMO) mxit.asm\r
+mxll.$(OBJ): mxll.asm\r
+       $(ASMC) $(ASMO) mxll.asm\r
+mxln.$(OBJ): mxln.asm\r
+       $(ASMC) $(ASMO) mxln.asm\r
+mxot.$(OBJ): mxot.asm\r
+       $(ASMC) $(ASMO) mxot.asm\r
+mxpb.$(OBJ): mxpb.asm\r
+       $(ASMC) $(ASMO) mxpb.asm\r
+mxpf.$(OBJ): mxpf.asm\r
+       $(ASMC) $(ASMO) mxpf.asm\r
+mxpg.$(OBJ): mxpg.asm\r
+       $(ASMC) $(ASMO) mxpg.asm\r
+mxpi.$(OBJ): mxpi.asm\r
+       $(ASMC) $(ASMO) mxpi.asm\r
+mxpn.$(OBJ): mxpn.asm\r
+       $(ASMC) $(ASMO) mxpn.asm\r
+mxpp.$(OBJ): mxpp.asm\r
+       $(ASMC) $(ASMO) mxpp.asm\r
+mxra.$(OBJ): mxra.asm\r
+       $(ASMC) $(ASMO) mxra.asm\r
+mxrp.$(OBJ): mxrp.asm\r
+       $(ASMC) $(ASMO) mxrp.asm\r
+mxsa.$(OBJ): mxsa.asm\r
+       $(ASMC) $(ASMO) mxsa.asm\r
+mxsc.$(OBJ): mxsc.asm\r
+       $(ASMC) $(ASMO) mxsc.asm\r
+mxsi.$(OBJ): mxsi.asm\r
+       $(ASMC) $(ASMO) mxsi.asm\r
+mxsl.$(OBJ): mxsl.asm\r
+       $(ASMC) $(ASMO) mxsl.asm\r
+mxsm.$(OBJ): mxsm.asm\r
+       $(ASMC) $(ASMO) mxsm.asm\r
+mxsp.$(OBJ): mxsp.asm\r
+       $(ASMC) $(ASMO) mxsp.asm\r
+mxss.$(OBJ): mxss.asm\r
+       $(ASMC) $(ASMO) mxss.asm\r
+mxtl.$(OBJ): mxtl.asm\r
+       $(ASMC) $(ASMO) mxtl.asm\r
+mxvs.$(OBJ): mxvs.asm\r
+       $(ASMC) $(ASMO) mxvs.asm\r
+mxwd.$(OBJ): mxwd.asm\r
+       $(ASMC) $(ASMO) mxwd.asm\r
+mxwm.$(OBJ): mxwm.asm\r
+       $(ASMC) $(ASMO) mxwm.asm\r
+mxwp.$(OBJ): mxwp.asm\r
+       $(ASMC) $(ASMO) mxwp.asm\r
+mxwr.$(OBJ): mxwr.asm\r
+       $(ASMC) $(ASMO) mxwr.asm\r
+\r
+all: $(LIBOBJS) modex.lib\r
+# modex.tpu modex.tpp\r
+\r
+#modex.tpu: $(LIBOBJS) modex.pas\r
+#        $(PASC) $(PASO) modex\r
+#        copy modex.tpu ..\r
+#        copy modex.pas ..\r
+\r
+#modex.tpp: $(LIBOBJS) modex.pas\r
+#        $(PASC) /cp $(PASO) modex\r
+#        copy modex.tpp ..\r
+\r
+modex.lib: modex.lbr $(LIBOBJS)\r
+       $(LIBC) modex.lib @modex.lbr\r
+\r
+$(LIBOBJS):   modex.def\r
diff --git a/16/xw_/makefile.bcc b/16/xw_/makefile.bcc
new file mode 100755 (executable)
index 0000000..d3ad8b7
--- /dev/null
@@ -0,0 +1,81 @@
+#\r
+# MODEX library makefile (for Borland MAKE)\r
+# Copyright (c) 1993,1994 by Alessandro Scotti\r
+#\r
+LIBINCS = MODEX.DEF\r
+\r
+LIBOBJS = MXBB.OBJ \\r
+          MXCC.OBJ \\r
+          MXCG.OBJ \\r
+          MXCL.OBJ \\r
+          MXCR.OBJ \\r
+          MXFB.OBJ \\r
+          MXFP.OBJ \\r
+          MXGC.OBJ \\r
+          MXGI.OBJ \\r
+          MXGM.OBJ \\r
+          MXGP.OBJ \\r
+          MXGV.OBJ \\r
+          MXHL.OBJ \\r
+          MXIT.OBJ \\r
+          MXLL.OBJ \\r
+          MXLN.OBJ \\r
+          MXOT.OBJ \\r
+          MXPB.OBJ \\r
+          MXPF.OBJ \\r
+          MXPG.OBJ \\r
+          MXPI.OBJ \\r
+          MXPN.OBJ \\r
+          MXPP.OBJ \\r
+          MXRA.OBJ \\r
+          MXRP.OBJ \\r
+          MXSA.OBJ \\r
+          MXSC.OBJ \\r
+          MXSI.OBJ \\r
+          MXSL.OBJ \\r
+          MXSM.OBJ \\r
+          MXSP.OBJ \\r
+          MXSS.OBJ \\r
+          MXTL.OBJ \\r
+          MXVS.OBJ \\r
+          MXWD.OBJ \\r
+          MXWM.OBJ \\r
+          MXWP.OBJ \\r
+          MXWR.OBJ\r
+\r
+#\r
+# ASM compiler\r
+#\r
+ASMC = tasm\r
+ASMO = /m5 /p\r
+\r
+#\r
+# PAS compiler\r
+#\r
+PASC = tpc\r
+PASO = /m -$D- -$L- -$S-\r
+\r
+#\r
+# LIB maker, uses response file\r
+#\r
+LIBC = tlib\r
+\r
+.asm.obj:\r
+        $(ASMC) $(ASMO) $<\r
+\r
+target: modex.lib
+# modex.tpu modex.tpp\r
+\r
+#modex.tpu: $(LIBOBJS) modex.pas\r
+#        $(PASC) $(PASO) modex\r
+#        copy modex.tpu ..\r
+#        copy modex.pas ..\r
+\r
+#modex.tpp: $(LIBOBJS) modex.pas\r
+#        $(PASC) /cp $(PASO) modex\r
+#        copy modex.tpp ..\r
+\r
+modex.lib: modex.lbr $(LIBOBJS)\r
+        $(LIBC) modex.lib @modex.lbr\r
+\r
+$(LIBOBJS):   modex.def\r
diff --git a/16/xw_/modex.bak b/16/xw_/modex.bak
new file mode 100755 (executable)
index 0000000..560a1c6
Binary files /dev/null and b/16/xw_/modex.bak differ
diff --git a/16/xw_/modex.def b/16/xw_/modex.def
new file mode 100755 (executable)
index 0000000..7977a4a
--- /dev/null
@@ -0,0 +1,163 @@
+;------------------------------------------------------------\r
+;\r
+; MODEX.DEF - Include file\r
+; Copyright (c) 1993-1994 by Alessandro Scotti\r
+;\r
+;JUMPS\r
+;LOCALS\r
+\r
+TRUE            EQU     1       ; Boolean constants\r
+FALSE           EQU     0\r
+\r
+USE286  = FALSE                  ; TRUE enables 80286 instructions\r
+USE386  = FALSE                  ; TRUE enables 80386 (and 80286) instructions\r
+\r
+IF USE286 EQ TRUE\r
+        P286\r
+ENDIF\r
+\r
+IF USE386 EQ TRUE\r
+        P386\r
+        USE286  = TRUE\r
+ENDIF\r
+\r
+MXVERSION       EQU     0128h   ; Library version (1.40)\r
+\r
+;------------------------------------------------------------\r
+;\r
+; VGA definitions\r
+;\r
+MISC    EQU     3C2h            ; Miscellaneous output\r
+TS      EQU     3C4h            ; Timing Sequencer index register\r
+GDC     EQU     3CEh            ; Graphics Data Controller index register\r
+CRTC    EQU     3D4h            ; CRTC index register\r
+STATUS  EQU     3DAh            ; Input Status register one\r
+\r
+;------------------------------------------------------------\r
+;\r
+; Raster operators\r
+;\r
+OP_SET          EQU     0\r
+OP_MOVE         EQU     0       ; Same as OP_SET\r
+OP_AND          EQU     1\r
+OP_OR           EQU     2\r
+OP_XOR          EQU     3\r
+OP_TRANS        EQU     4\r
+OP_ADD          EQU     5       ; Must be last op\r
+\r
+;------------------------------------------------------------\r
+;\r
+; Polygon fill functions\r
+;\r
+POLYSCANBUFSIZE EQU     4*1024\r
+\r
+;------------------------------------------------------------\r
+; Macro to push registers, variables or flags onto the stack\r
+; Usage: .push "loc16"[,"loc16"...]\r
+; where "loc16" is a 16-bit register, a word-sized variable or the\r
+; keyword "FLAGS".\r
+; Exmpl: .push ax, flags, var1\r
+;        .pop  ax, flags, var1\r
+;\r
+.push   MACRO   r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10\r
+    IFNB <r10>\r
+        .ERROR <.PUSH has more than 10 arguments>\r
+    ENDIF\r
+    IRP $reg, <r0, r1, r2, r3, r4, r5, r6, r7, r8, r9>\r
+        IFB <$reg>                      ;; Is argument blank?\r
+            EXITM                       ;; Yes, exit\r
+        ELSEIFIDNI <$reg>, <FLAGS>      ;; Is argument the keyword "FLAGS"?\r
+            pushf                       ;; Yes, push flags\r
+        ELSE\r
+            push    $reg                ;; Push argument\r
+        ENDIF\r
+    ENDM\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+; Macro to pop registers, variables or flags from the stack\r
+; Usage: .pop "loc16"[,"loc16"...]\r
+; where "loc16" is a 16-bit register, a word-sized variable or the\r
+; keyword "FLAGS".\r
+; Exmpl: .push ax, flags, var1\r
+;        .pop  ax, flags, var1\r
+;\r
+.pop    MACRO   r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10\r
+    IFNB <r10>\r
+        .ERROR <.POP has more than 10 arguments>\r
+    ENDIF\r
+    IRP $reg, <r9, r8, r7, r6, r5, r4, r3, r2, r1, r0>\r
+        IFNB <$reg>                     ;; Is argument non-blank?\r
+            IFIDNI <$reg>, <FLAGS>      ;; Yes, is it the keyword "FLAGS"?\r
+                popf                    ;; Yes, pop flags\r
+            ELSE\r
+                pop     $reg            ;; Pop argument\r
+            ENDIF\r
+        ENDIF\r
+    ENDM\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.enter  MACRO   localsize\r
+    IF USE286 EQ TRUE\r
+        enter   localsize, 0\r
+    ELSE\r
+        push    bp\r
+        mov     bp, sp\r
+        sub     sp, localsize\r
+    ENDIF\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.leave  MACRO   argsize\r
+;    IF USE286 EQ TRUE\r
+;        leave\r
+;    ELSE\r
+;        mov     sp, bp\r
+;        pop     bp\r
+;    ENDIF\r
+;    IFNB <argspace>\r
+;        ret     argsize\r
+;    ELSE\r
+;        ret\r
+;    ENDIF\r
+;ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.shr    MACRO   arg, count\r
+;    IF USE286 EQ TRUE\r
+;        shr     arg, count\r
+;    ELSE\r
+;        $temp = count\r
+;        WHILE $temp GT 0\r
+;            shr arg, 1\r
+;            $temp = $temp-1\r
+;        ENDM\r
+;    ENDIF\r
+;ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.shl    MACRO   arg, count\r
+;    IF USE286 EQ TRUE\r
+;        shl     arg, count\r
+;    ELSE\r
+;        $temp = count\r
+;        WHILE $temp GT 0\r
+;            shl arg, 1\r
+;            $temp = $temp-1\r
+;        ENDM\r
+;    ENDIF\r
+;ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.chk386 MACRO   name, jump\r
+;    IF USE386 EQ FALSE\r
+;        .OUT    "Warning: ", <name>, " needs a 386 or better to run!"\r
+;        jmp     @@jump\r
+;    ENDIF\r
+;ENDM\r
diff --git a/16/xw_/modex.h b/16/xw_/modex.h
new file mode 100755 (executable)
index 0000000..2c1f1eb
--- /dev/null
@@ -0,0 +1,153 @@
+/*\r
+    MODEX.H - C/C++ include file for the MODEX library\r
+    Copyright (c) 1994 Alessandro Scotti\r
+*/\r
+\r
+#ifndef _MODEX_H_               // Avoid nested inclusions\r
+#define _MODEX_H_\r
+\r
+//\r
+// Video modes\r
+//\r
+#define MX_TEXT     0           // 80x25 text\r
+#define MX_320x175  1           // 320x175x256\r
+#define MX_320x200  2           // 320x200x256, 4 pages, aspect 6:5\r
+#define MX_320x240  3           // 320x240x256, 3 pages, aspect 1:1\r
+#define MX_320x350  4           // 320x350x256\r
+#define MX_320x400  5           // 320x400x256, 2 pages\r
+#define MX_320x480  6           // 320x480x256, 1 page\r
+#define MX_360x175  7           // 360x175x256\r
+#define MX_360x200  8           // 360x200x256, 3 pages\r
+#define MX_360x240  9           // 360x240x256, 2 pages\r
+#define MX_360x350  10          // 360x350x256\r
+#define MX_360x400  11          // 360x400x256, 1 page\r
+#define MX_360x480  12          // 360x480x256, 1 page\r
+#define MX_400x600  13          // 400x600x256, 1 page\r
+\r
+//\r
+// Fade effects\r
+//\r
+#define MX_FADEIN   0\r
+#define MX_FADEOUT  1\r
+\r
+//\r
+// Raster ops\r
+//\r
+#define OP_SET      0           // No operator\r
+#define OP_AND      1           // And\r
+#define OP_OR       2           // Or\r
+#define OP_XOR      3           // Xor\r
+#define OP_TRANS    4           // Transparent\r
+#define OP_ADD      5           // Additive\r
+#define OP_MOVE     0           // Alias for OP_SET\r
+\r
+//\r
+// Temporary definitions\r
+//\r
+#define MXBYTE      unsigned char\r
+#define MXBOOL      short int\r
+#define MXSINT      short int\r
+#define MXUINT      unsigned short int\r
+#define MXAPI       far pascal\r
+#define MXPTR       void far *\r
+\r
+// Functions\r
+\r
+#ifdef __cplusplus                      // Avoid C++ name mangling\r
+extern "C" {\r
+#endif\r
+\r
+//\r
+// Initialization\r
+//\r
+MXSINT  MXAPI mxInit( void );             // Returns 0 if successful\r
+void    MXAPI mxTerm( void );\r
+MXUINT  MXAPI mxGetVersion( void );\r
+//\r
+// Mode setting\r
+//\r
+void    MXAPI mxChangeMode( MXUINT mode );\r
+void    MXAPI mxSetMode( MXUINT mode );\r
+void    MXAPI mxGetAspect( MXUINT far *aspectx, MXUINT far *aspecty );\r
+void    MXAPI mxGetScreenSize( MXUINT far *width, MXUINT far *height );\r
+//\r
+// Hardware support\r
+//\r
+void    MXAPI mxWriteMode( MXBYTE wm );\r
+void    MXAPI mxSplitScreen( MXUINT line );\r
+void    MXAPI mxStartAddress( MXUINT sa );\r
+void    MXAPI mxStartLine( MXUINT sl );\r
+void    MXAPI mxWaitDisplay( void );\r
+void    MXAPI mxWaitRetrace( void );\r
+void    MXAPI mxWritePlane( MXBYTE wp );\r
+void    MXAPI mxReadPlane( MXBYTE rp );\r
+void    MXAPI mxRowAddress( MXBYTE ra );\r
+//\r
+// Virtual screen\r
+//\r
+void    MXAPI mxGetVirtualScreen( MXUINT far *width, MXUINT far *height );\r
+void    MXAPI mxSetVirtualScreen( MXUINT width, MXUINT height );\r
+void    MXAPI mxPan( MXUINT x, MXUINT y );\r
+//\r
+// Clipping\r
+//\r
+MXBOOL  MXAPI mxGetClip( void );\r
+MXBOOL  MXAPI mxGetClipRegion( MXSINT far *x, MXSINT far *y, MXSINT far *w, MXSINT far *h );\r
+MXBOOL  MXAPI mxSetClip( MXBOOL );\r
+void    MXAPI mxSetClipRegion( MXUINT x, MXUINT y, MXUINT width, MXUINT height );\r
+//\r
+// Graphics\r
+//\r
+void    MXAPI mxBitBlt( MXSINT sx, MXSINT sy, MXUINT width, MXUINT height, MXSINT dx, MXSINT dy );\r
+void    MXAPI mxFillBox( MXSINT x, MXSINT y, MXUINT width, MXUINT height, MXUINT color, MXUINT op );\r
+MXBYTE  MXAPI mxGetPixel( MXSINT x, MXSINT y );\r
+void    MXAPI mxPutPixel( MXSINT x, MXSINT y, MXBYTE color );\r
+void    MXAPI mxLine( MXSINT x1, MXSINT y1, MXSINT x2, MXSINT y2, MXUINT color, MXUINT op );\r
+void    MXAPI mxGetImage( MXPTR img, MXSINT x, MXSINT y, MXUINT width, MXUINT height );\r
+void    MXAPI mxPutImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT op );\r
+void    MXAPI mxPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT width, MXUINT height );\r
+void    MXAPI mxTransPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT w, MXUINT h );\r
+void    MXAPI mxCircle( MXSINT x, MXSINT y, MXUINT radius, MXBYTE color );\r
+void    MXAPI mxStretchImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT neww, MXUINT newh, MXUINT op );\r
+//\r
+// Palette\r
+//\r
+void    MXAPI mxColorToGray( MXPTR source, MXPTR dest, MXUINT count );\r
+void    MXAPI mxGammaCorrect( MXPTR source, MXPTR dest, MXUINT count );\r
+void    MXAPI mxGetColor( MXUINT index, MXSINT far *r, MXSINT far *g, MXSINT far *b );\r
+void    MXAPI mxSetColor( MXUINT index, MXSINT red, MXSINT green, MXSINT blue );\r
+void    MXAPI mxGetPalette( MXPTR palette, MXUINT index, MXUINT count );\r
+void    MXAPI mxSetPalette( MXPTR palette, MXUINT index, MXUINT count );\r
+void    MXAPI mxFadePalette( MXPTR, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT );\r
+void    MXAPI mxRotatePalette( MXPTR palette, MXUINT count, MXSINT step );\r
+//\r
+// Text\r
+//\r
+MXSINT  MXAPI mxSetFont( MXPTR font, MXUINT charwidth, MXUINT charheight );\r
+void    MXAPI mxSetTextColor( MXUINT color, MXUINT op );\r
+void    MXAPI mxGetTextStep( MXSINT far *deltax, MXSINT far *deltay );\r
+void    MXAPI mxSetTextStep( MXSINT deltax, MXSINT deltay );\r
+void    MXAPI mxOutChar( MXSINT x, MXSINT y, char c );\r
+void    MXAPI mxOutText( MXSINT x, MXSINT y, char far *sz );\r
+//\r
+// Convex polygons\r
+//\r
+void    MXAPI mxFillPoly( MXUINT, MXPTR, MXPTR, MXUINT, MXUINT );\r
+void    MXAPI mxGouraudPoly( MXUINT, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT );\r
+void    MXAPI mxTexturePoly( MXUINT, MXPTR, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+//\r
+// Remove temporary defines\r
+//\r
+#undef  MXBYTE\r
+#undef  MXBOOL\r
+#undef  MXSINT\r
+#undef  MXUINT\r
+#undef  MXPTR\r
+#undef  MXAPI\r
+\r
+#endif  // _MODEX_H_\r
diff --git a/16/xw_/modex.lbr b/16/xw_/modex.lbr
new file mode 100755 (executable)
index 0000000..93fc780
--- /dev/null
@@ -0,0 +1,39 @@
++-MXBB.OBJ &\r
++-MXCC.OBJ &\r
++-MXCG.OBJ &\r
++-MXCL.OBJ &\r
++-MXCR.OBJ &\r
++-MXFB.OBJ &\r
++-MXFP.OBJ &\r
++-MXGC.OBJ &\r
++-MXGI.OBJ &\r
++-MXGM.OBJ &\r
++-MXGP.OBJ &\r
++-MXGV.OBJ &\r
++-MXHL.OBJ &\r
++-MXIT.OBJ &\r
++-MXLL.OBJ &\r
++-MXLN.OBJ &\r
++-MXOT.OBJ &\r
++-MXPB.OBJ &\r
++-MXPF.OBJ &\r
++-MXPG.OBJ &\r
++-MXPI.OBJ &\r
++-MXPN.OBJ &\r
++-MXPP.OBJ &\r
++-MXPT.OBJ &\r
++-MXRA.OBJ &\r
++-MXRP.OBJ &\r
++-MXSA.OBJ &\r
++-MXSC.OBJ &\r
++-MXSI.OBJ &\r
++-MXSL.OBJ &\r
++-MXSM.OBJ &\r
++-MXSP.OBJ &\r
++-MXSS.OBJ &\r
++-MXTL.OBJ &\r
++-MXVS.OBJ &\r
++-MXWD.OBJ &\r
++-MXWM.OBJ &\r
++-MXWP.OBJ &\r
++-MXWR.OBJ\r
diff --git a/16/xw_/modex.pas b/16/xw_/modex.pas
new file mode 100755 (executable)
index 0000000..7d9d26e
--- /dev/null
@@ -0,0 +1,194 @@
+(*\r
+   Turbo Pascal interface to the MODEX library\r
+   Copyright (c) 1993,1994 by Alessandro Scotti\r
+*)\r
+unit ModeX;\r
+interface\r
+\r
+const\r
+  (* Video modes *)\r
+  MX_TEXT       = 0;\r
+  MX_320x175    = 1;\r
+  MX_320x200    = 2;\r
+  MX_320x240    = 3;\r
+  MX_320x350    = 4;\r
+  MX_320x400    = 5;\r
+  MX_320x480    = 6;\r
+  MX_360x175    = 7;\r
+  MX_360x200    = 8;\r
+  MX_360x240    = 9;\r
+  MX_360x350    = 10;\r
+  MX_360x400    = 11;\r
+  MX_360x480    = 12;\r
+  MX_400x600    = 13;\r
+\r
+  (* Fade effects *)\r
+  MX_FADEIN     = 0;\r
+  MX_FADEOUT    = 1;\r
+\r
+  (* Raster ops *)\r
+  OP_SET        = 0;\r
+  OP_AND        = 1;\r
+  OP_OR         = 2;\r
+  OP_XOR        = 3;\r
+  OP_TRANS      = 4;\r
+  OP_ADD        = 5;\r
+  OP_MOVE       = 0;                    (* Alias for OP_SET *)\r
+\r
+procedure mxBitBlt( SX, SY: integer; Width, Height: word; DX, DY: integer );\r
+procedure mxCircle( CX, CY: integer; Radius: word; Color: byte );\r
+procedure mxChangeMode( Mode: word );\r
+procedure mxColorToGray( ColorPalette, GrayPalette: pointer; Count: word );\r
+procedure mxFadePalette( Palette: pointer; Cmd, Start, Count, R, G, B: word );\r
+procedure mxFillBox( X, Y: integer; Width, Height: word; Color: byte; Op: word );\r
+procedure mxGammaCorrect( ColorPalette, GammaPalette: pointer; Count: word );\r
+procedure mxGetAspect( var AspectX, AspectY: word );\r
+function  mxGetClipRegion( var X1, Y1, Width, Height: word ): boolean;\r
+function  mxGetClip: boolean;\r
+procedure mxGetImage( Image: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxGetPalette( Palette: pointer; Start, Count: word );\r
+function  mxGetPixel( X, Y: word ): byte;\r
+procedure mxGetScreenSize( var Width, Height: word );\r
+procedure mxGetTextStep( var DeltaX, DeltaY: integer );\r
+function  mxGetVersion: word;\r
+procedure mxGetVirtualScreen( var Width, Height: word );\r
+procedure mxInit;\r
+procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word );\r
+procedure mxOutChar( X, Y: integer; C: char );\r
+procedure mxOutText( X, Y: integer; S: pointer );\r
+procedure mxPan( X, Y: word );\r
+procedure mxPutImage( Image: pointer; X, Y: integer; Width, Height, Op: word );\r
+procedure mxPutPixel( X, Y: word; C: byte );\r
+procedure mxPutTile( Tile: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxReadPlane( Plane: byte );\r
+procedure mxRotatePalette( Palette: pointer; Count: word; Step: integer );\r
+procedure mxRowAddress( RowAddress: byte );\r
+function  mxSetClip( Clip: boolean ): boolean;\r
+procedure mxSetClipRegion( X1, Y1, Width, Height: word );\r
+procedure mxSetColor( Index, R, G, B: word );\r
+procedure mxSetFont( Font: pointer; Width, Height: word );\r
+procedure mxSetMode( Mode: word );\r
+procedure mxSetPalette( Palette: pointer; Start, Count: word );\r
+procedure mxSetTextColor( Color, Op: word );\r
+procedure mxSetTextStep( DeltaX, DeltaY: integer );\r
+procedure mxSetVirtualScreen( Width, Height: word );\r
+procedure mxStretchImage( Image: pointer; X, Y: integer; Width, Height, NewWidth, NewHeight, Op: word );\r
+procedure mxSplitScreen( Line: word );\r
+procedure mxStartAddress( StartAddress: word );\r
+procedure mxStartLine( Line: word );\r
+procedure mxTerm;\r
+procedure mxTransPutTile( Tile: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxWaitDisplay;\r
+procedure mxWaitRetrace;\r
+procedure mxWriteMode( Mode: byte );\r
+procedure mxWritePlane( Plane: byte );\r
+\r
+procedure mxFillPoly( Count: word; var Map, Points; Color: word );\r
+procedure mxGouraudPoly( Count: word; var Map, Points, Colors; BaseColor: word );\r
+procedure mxTexturePoly( Count: word; var Map, Points, ImgPoints, Texture; Width: word );\r
+\r
+procedure mxOutStr( X, Y: integer; S: string );\r
+\r
+implementation\r
+\r
+procedure mxBitBlt;                                             external;\r
+procedure mxChangeMode( Mode: word );                           external;\r
+procedure mxCircle;                                             external;\r
+procedure mxColorToGray;                                        external;\r
+procedure mxFadePalette;                                        external;\r
+procedure mxFillBox;                                            external;\r
+procedure mxGammaCorrect;                                       external;\r
+procedure mxGetAspect( var AspectX, AspectY: word );            external;\r
+function  mxGetClipRegion;                                      external;\r
+function  mxGetClip: boolean;                                   external;\r
+procedure mxGetImage;                                           external;\r
+procedure mxGetPalette( Palette: pointer; Start, Count: word ); external;\r
+function  mxGetPixel( X, Y: word ): byte;                       external;\r
+procedure mxGetScreenSize( var Width, Height: word );           external;\r
+procedure mxGetTextStep( var DeltaX, DeltaY: integer );         external;\r
+function  mxGetVersion: word;                                   external;\r
+procedure mxGetVirtualScreen( var Width, Height: word );        external;\r
+procedure mxInit;                                               external;\r
+procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word );   external;\r
+procedure mxOutChar( X, Y: integer; C: char );                  external;\r
+procedure mxOutText( X, Y: integer; S: pointer );               external;\r
+procedure mxPan( X, Y: word );                                  external;\r
+procedure mxPutImage;                                           external;\r
+procedure mxPutPixel( X, Y: word; C: byte );                    external;\r
+procedure mxPutTile;                                            external;\r
+procedure mxReadPlane( Plane: byte );                           external;\r
+procedure mxRotatePalette;                                      external;\r
+procedure mxRowAddress( RowAddress: byte );                     external;\r
+function  mxSetClip( Clip: boolean ): boolean;                  external;\r
+procedure mxSetClipRegion( X1, Y1, Width, Height: word );       external;\r
+procedure mxSetColor( Index, R, G, B: word );                   external;\r
+procedure mxSetFont( Font: pointer; Width, Height: word );      external;\r
+procedure mxSetMode( Mode: word );                              external;\r
+procedure mxSetPalette( Palette: pointer; Start, Count: word ); external;\r
+procedure mxSetTextColor( Color, Op: word );                    external;\r
+procedure mxSetTextStep( DeltaX, DeltaY: integer );             external;\r
+procedure mxSetVirtualScreen( Width, Height: word );            external;\r
+procedure mxSplitScreen( Line: word );                          external;\r
+procedure mxStartAddress( StartAddress: word );                 external;\r
+procedure mxStartLine;                                          external;\r
+procedure mxStretchImage;                                       external;\r
+procedure mxTerm;                                               external;\r
+procedure mxTransPutTile;                                       external;\r
+procedure mxWaitDisplay;                                        external;\r
+procedure mxWaitRetrace;                                        external;\r
+procedure mxWriteMode( Mode: byte );                            external;\r
+procedure mxWritePlane( Plane: byte );                          external;\r
+\r
+procedure mxFillPoly;                                           external;\r
+procedure mxGouraudPoly;                                        external;\r
+procedure mxTexturePoly;                                        external;\r
+{$L MXPB}\r
+{$L MXPF}\r
+{$L MXPG}\r
+{$L MXPT}\r
+\r
+{$L MXBB}\r
+{$L MXCC}\r
+{$L MXCG}\r
+{$L MXCL}\r
+{$L MXCR}\r
+{$L MXFB}\r
+{$L MXFP}\r
+{$L MXGI}\r
+{$L MXGM}\r
+{$L MXGP}\r
+{$L MXGV}\r
+{$L MXHL}\r
+{$L MXIT}\r
+{$L MXLN}\r
+{$L MXOT}\r
+{$L MXPI}\r
+{$L MXPN}\r
+{$L MXPP}\r
+{$L MXRA}\r
+{$L MXRP}\r
+{$L MXSA}\r
+{$L MXSC}\r
+{$L MXSI}\r
+{$L MXSL}\r
+{$L MXSM}\r
+{$L MXSP}\r
+{$L MXSS}\r
+{$L MXTL}\r
+{$L MXVS}\r
+{$L MXWD}\r
+{$L MXWM}\r
+{$L MXWP}\r
+{$L MXWR}\r
+\r
+(*\r
+   Prints a Turbo Pascal string.\r
+   Note: BP 7.0 supports ASCIIZ strings (PChar type).\r
+*)\r
+procedure mxOutStr;\r
+begin\r
+  S := S + #0;\r
+  mxOutText( X, Y, @S[1] );\r
+end;\r
+\r
+end.\r
diff --git a/16/xw_/modex/DEMO01.EXE b/16/xw_/modex/DEMO01.EXE
new file mode 100755 (executable)
index 0000000..28caff8
Binary files /dev/null and b/16/xw_/modex/DEMO01.EXE differ
diff --git a/16/xw_/modex/DEMO01.PAS b/16/xw_/modex/DEMO01.PAS
new file mode 100755 (executable)
index 0000000..c684acd
--- /dev/null
@@ -0,0 +1,126 @@
+(*\r
+    DEMO01 - Sprites, page flipping and palette rotation\r
+    Copyright (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+  MAX_SPRITE = 100;\r
+type\r
+  (* Sprite structure *)\r
+  TSprite = record\r
+    X, Y : integer;                        (* Sprite coordinates *)\r
+    DX,DY: integer;                        (* Deltas for sprite movement *)\r
+    W, H : integer;                        (* Sprite width and height *)\r
+    Image: array[ 1..16, 1..16 ] of byte;  (* Sprite image data *)\r
+  end;\r
+  (* RGB color structure *)\r
+  TRgb    = record\r
+    R, G, B: byte;\r
+  end;\r
+var\r
+  S      : array[ 1..MAX_SPRITE ] of TSprite;   (* An array of sprites *)\r
+  Palette: array[ byte ] of TRgb;               (* Palette *)\r
+  Page   : word;                                (* Page offset *)\r
+  I      : word;\r
+\r
+(* Initializes a sprite structure *)\r
+procedure sxInit( var S: TSprite );\r
+var\r
+  I: word;\r
+begin\r
+  S.X := Random( 320 );  (* Initialize position with random values *)\r
+  S.Y := Random( 240 );\r
+  S.DX := Random( 7 )-3; (* Initialize speed with random values *)\r
+  S.DY := Random( 7 )-3;\r
+  S.W := 16;             (* Size is fixed in this program *)\r
+  S.H := 16;\r
+  (* The image is a square with a hole inside *)\r
+  FillChar( S.Image, SizeOf(S.Image), Random(15)+1 );\r
+  for I:=5 to 12 do FillChar( S.Image[ I, 5 ], 8, 0 );\r
+end;\r
+\r
+(* Moves a sprite *)\r
+procedure sxMove( var S: TSprite );\r
+begin\r
+  Inc( S.X, S.DX );     (* Get new position *)\r
+  Inc( S.Y, S.DY );\r
+  (* Check sprite position, change delta if needed *)\r
+  if( S.X > 320 ) then begin\r
+    S.X := 320;\r
+    S.DX := -S.DX;\r
+  end;\r
+  if( S.X < -16 ) then begin\r
+    S.X := -16;\r
+    S.DX := -S.DX;\r
+  end;\r
+  if( S.Y > 240 ) then begin\r
+    S.Y := 240;\r
+    S.DY := -S.DY;\r
+  end;\r
+  if( S.Y < -16 ) then begin\r
+    S.Y := -16;\r
+    S.DY := -S.DY;\r
+  end;\r
+  (* Draw the sprite, note the Page offset added to the *)\r
+  (* Y coordinate of the image *)\r
+  mxPutImage( @S.Image, S.X, Page+S.Y, S.W, S.H, OP_TRANS );\r
+end;\r
+\r
+begin\r
+  (* Initialize library *)\r
+  mxInit;\r
+\r
+  (* Enter graphics mode *)\r
+  mxSetMode( MX_320x240 );\r
+\r
+  (* Print initialization message *)\r
+  mxSetTextColor( 15, OP_TRANS );\r
+  mxOutStr( 4, 4, 'Initializing...' );\r
+\r
+  (* Initialize sprites *)\r
+  for I:=1 to MAX_SPRITE do sxInit( S[I] );\r
+\r
+  (* Draw background *)\r
+  for I:=1 to 192 do begin\r
+    mxCircle( 160, 480+120, I, I+63 );\r
+    mxCircle( 161, 480+120, I, I+63 );\r
+  end;\r
+\r
+  (* Compute and set palette *)\r
+  for I:=1 to 192 do with Palette[I+63] do begin\r
+    R := 0;\r
+    G := 0;\r
+    B := 0;\r
+    if( I < 64 ) then\r
+      R := I shr 1+31\r
+    else if( I < 128 ) then\r
+      G := (I-64) shr 1+31\r
+    else\r
+      B := (I-128) shr 1+31;\r
+  end;\r
+  mxSetPalette( @Palette[64], 64, 192 );\r
+\r
+  (* Main loop *)\r
+  Page := 240;\r
+  while( not KeyPressed ) do begin\r
+    (* Set clip region to current page *)\r
+    mxSetClipRegion( 0, Page, 320, 240 );\r
+    mxSetClip( TRUE );\r
+    (* Restore background *)\r
+    mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+    (* Draw sprites *)\r
+    for I:=1 to MAX_SPRITE do sxMove( S[I] );\r
+    (* Print message *)\r
+    mxOutStr( 4, Page+4, 'Some sprites moving...' );\r
+    (* Flip page *)\r
+    mxStartLine( Page );\r
+    Page := 240-Page;\r
+    (* Animate palette *)\r
+    mxSetPalette( @Palette[64], 64, 192 );\r
+    mxRotatePalette( @Palette[64], 192, 3 );\r
+  end;\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw_/modex/DEMO02.EXE b/16/xw_/modex/DEMO02.EXE
new file mode 100755 (executable)
index 0000000..14e7dc7
Binary files /dev/null and b/16/xw_/modex/DEMO02.EXE differ
diff --git a/16/xw_/modex/DEMO02.PAS b/16/xw_/modex/DEMO02.PAS
new file mode 100755 (executable)
index 0000000..6b4fb6f
--- /dev/null
@@ -0,0 +1,125 @@
+(*\r
+    DEMO02 - Texture mapping and palette rotation\r
+    (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Plasma, Threed;\r
+\r
+const\r
+  LSIZE = 85;\r
+  Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+type\r
+  T2DPoint = record\r
+    X, Y: integer;\r
+  end;\r
+  TTexture = record\r
+    Desc   : array[ 0..3 ] of T2DPoint;\r
+    Width  : word;\r
+    Data   : array[ 1..64*64 ] of byte;\r
+  end;\r
+  TQuad = record\r
+    VtxCnt : word;\r
+    Vtx    : array[ 0..3 ] of word;\r
+    Texture: word;\r
+  end;\r
+var\r
+  Vtx   : array[ 0..7 ] of TPoint;\r
+  XVtx  : array[ 0..7 ] of TPoint;\r
+  VVtx  : array[ 0..7 ] of T2DPoint;\r
+  Face  : array[ 0..5 ] of TQuad;\r
+  Txts  : array[ 0..5 ] of TTexture;\r
+  Nrm   : array[ 0..5 ] of TPoint;\r
+  XNrm  : array[ 0..5 ] of TPoint;\r
+  Page  : word;\r
+  Palette: array[ byte ] of record R, G, B: byte; end;\r
+\r
+(* Make a 64x64 plasma to be used as texture *)\r
+procedure MakeTexture( Idx: word );\r
+var\r
+  I: word;\r
+begin\r
+  mxFillBox( 0, 0, 64, 64, 0, OP_SET );\r
+  MakePlasma( 0, 0, 64, 64, 96, Random(192)+1, Random(192)+1, Random(192)+1 );\r
+  mxGetImage( @Txts[Idx].Data, 0, 0, 64, 64 );\r
+  (* Texture vertexes are 8:8 fixed, add $80 (0.5) for best results *)\r
+  with Txts[Idx] do begin\r
+    Desc[0].X := $80; Desc[0].Y := $80;\r
+    Desc[1].X := $80; Desc[1].Y := $3F80;\r
+    Desc[2].X := $3F80; Desc[2].Y := $3F80;\r
+    Desc[3].X := $3F80; Desc[3].Y := $80;\r
+    Width := 64;\r
+  end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+  I: integer;\r
+begin\r
+  (* Build vertexes for a cube *)\r
+  with Vtx[0] do begin X:=-LSIZE; Y:=-LSIZE; Z:=-LSIZE; end;\r
+  with Vtx[1] do begin X:=+LSIZE; Y:=-LSIZE; Z:=-LSIZE; end;\r
+  with Vtx[2] do begin X:=-LSIZE; Y:=+LSIZE; Z:=-LSIZE; end;\r
+  with Vtx[3] do begin X:=+LSIZE; Y:=+LSIZE; Z:=-LSIZE; end;\r
+  with Vtx[4] do begin X:=-LSIZE; Y:=-LSIZE; Z:=+LSIZE; end;\r
+  with Vtx[5] do begin X:=+LSIZE; Y:=-LSIZE; Z:=+LSIZE; end;\r
+  with Vtx[6] do begin X:=-LSIZE; Y:=+LSIZE; Z:=+LSIZE; end;\r
+  with Vtx[7] do begin X:=+LSIZE; Y:=+LSIZE; Z:=+LSIZE; end;\r
+  for I:=0 to 7 do begin          (* Make points 16:16 fixed *)\r
+    Vtx[I].X := Vtx[I].X*$10000;\r
+    Vtx[I].Y := Vtx[I].Y*$10000;\r
+    Vtx[I].Z := Vtx[I].Z*$10000;\r
+  end;\r
+  (* Build faces *)\r
+  with Face[0] do begin Vtx[0]:=0; Vtx[1]:=2; Vtx[2]:=3; Vtx[3]:=1; end;\r
+  with Face[1] do begin Vtx[0]:=4; Vtx[1]:=5; Vtx[2]:=7; Vtx[3]:=6; end;\r
+  with Face[2] do begin Vtx[0]:=0; Vtx[1]:=1; Vtx[2]:=5; Vtx[3]:=4; end;\r
+  with Face[3] do begin Vtx[0]:=1; Vtx[1]:=3; Vtx[2]:=7; Vtx[3]:=5; end;\r
+  with Face[4] do begin Vtx[0]:=2; Vtx[1]:=0; Vtx[2]:=4; Vtx[3]:=6; end;\r
+  with Face[5] do begin Vtx[0]:=7; Vtx[1]:=3; Vtx[2]:=2; Vtx[3]:=6; end;\r
+  for I:=0 to 5 do Face[I].Texture := I;\r
+  (* Build textures and palette *)\r
+  Randomize;\r
+  FillChar( Palette, SizeOf(Palette), 0 );\r
+  MakePlasmaPalette( Palette, PAL_RGB );\r
+  mxSetPalette( @Palette, 0, 193 );\r
+  for I:=0 to 5 do MakeTexture( I );\r
+end;\r
+\r
+var\r
+  AX, AY, AZ: byte;\r
+  I: word;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;          (* Start with hidden page *)\r
+\r
+  AX := 0;\r
+  AY := 0;\r
+  AZ := 0;\r
+  (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+  tdSetTranslation( Trans );\r
+  tdSetPerspective( 400*$10000, $10000, $10000 );\r
+  (* Main loop, all magic here! *)\r
+  while( not KeyPressed ) do begin\r
+    tdSetRotation( AX, AY, AZ );                (* Set new angles *)\r
+    tdTransform( Vtx, XVtx, 8 );                (* 3D transform points *)\r
+    tdTransformToImage( XVtx, VVtx, 8, 160, 120+Page );\r
+    Inc( AX, 1 );                               (* Bump angles *)\r
+    Inc( AY, 1 );\r
+    Inc( AZ, 2 );\r
+    mxSetClipRegion( 0, Page, 320, 240 );       (* Set clip to new page *)\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+    mxRotatePalette( @Palette[1], 192, 3 );     (* Rotate palette *)\r
+    (* Draw cube: backface culling is straighforward in this case, so *)\r
+    (* it can be handled by the polygon filling procedure *)\r
+    for I:=0 to 5 do\r
+      mxTexturePoly( 4, Face[I].Vtx, VVtx, Txts[I].Desc, Txts[I].Data, Txts[I].Width );\r
+    mxStartLine( Page );                        (* Flip pages *)\r
+    mxSetPalette( @Palette[1], 1, 192 );        (* Set new palette *)\r
+    Page := 240-Page;\r
+  end;\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw_/modex/DEMO03.EXE b/16/xw_/modex/DEMO03.EXE
new file mode 100755 (executable)
index 0000000..c646c4b
Binary files /dev/null and b/16/xw_/modex/DEMO03.EXE differ
diff --git a/16/xw_/modex/DEMO03.PAS b/16/xw_/modex/DEMO03.PAS
new file mode 100755 (executable)
index 0000000..01d10f4
--- /dev/null
@@ -0,0 +1,152 @@
+(*\r
+    DEMO03 - Simple star animation, morphs between a cube and a sphere\r
+    (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+const\r
+  MAXVTX = 1000;        (* Number of points *)\r
+  EDGE = 70;            (* Length of cube edge *)\r
+  RADIUS = 90;          (* Radius of sphere *)\r
+  WAITCOUNT = 192;      (* Frames to wait for non-morphing shapes *)\r
+  MS = 32;              (* Number of steps for morphing *)\r
+  Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+  InitMorph1: array[ 0..3 ] of integer = ( 0, MS, 0, 0 );\r
+  InitMorph2: array[ 0..3 ] of integer = ( 0, 0, 0, MS );\r
+  InitDelta1: array[ 0..3 ] of integer = ( 0, -1, 0, +1 );\r
+  InitDelta2: array[ 0..3 ] of integer = ( 0, +1, 0, -1 );\r
+type\r
+  T2DPoint = record\r
+    X, Y: integer;\r
+  end;\r
+  T3DPointArray = array[ 0..MAXVTX-1 ] of TPoint;\r
+  P3DPointArray = ^T3DPointArray;\r
+var\r
+  CubeVtx, SphereVtx, Vtx, XVtx: P3DPointArray;\r
+  VVtx  : array[ 0..MAXVTX-1 ] of T2DPoint;\r
+  Page  : word;\r
+  Status, Count, Delta1, Delta2, Morph1, Morph2: integer;\r
+\r
+procedure Swap( var A, B: longint );\r
+var\r
+  L: longint;\r
+begin\r
+  L := A; A := B; B := L;\r
+end;\r
+\r
+function Toggle( A: longint ): longint;\r
+begin\r
+  Toggle := A;\r
+  if( Random(2) = 0 ) then Toggle := -A;\r
+end;\r
+\r
+procedure Init;\r
+label Retry;\r
+var\r
+  I: integer;\r
+begin\r
+  New( CubeVtx );\r
+  New( SphereVtx );\r
+  New( Vtx );\r
+  New( XVtx );\r
+  (* Build vertexes (yes, I know this piece of code is terrible) *)\r
+  Randomize;\r
+  for I:=0 to MAXVTX-1 do begin\r
+    with CubeVtx^[I] do begin\r
+      (* Build cube *)\r
+      X := (longint(Random(2*EDGE))-EDGE)*$10000;\r
+      Y := (longint(Random(2*EDGE))-EDGE)*$10000;\r
+      Z := Toggle( EDGE*$10000 );\r
+      case Random(3) of\r
+        0: Swap( X, Z );\r
+        1: Swap( Y, Z );\r
+      end;\r
+    end;\r
+    with SphereVtx^[I] do begin\r
+      (* Build sphere *)\r
+Retry:\r
+      X := (longint(Random(2*RADIUS))-RADIUS);\r
+      Y := (longint(Random(2*RADIUS))-RADIUS);\r
+      if( X*X+Y*Y > RADIUS*RADIUS ) then goto Retry;\r
+      Z := Toggle( Round( Sqrt( Abs( RADIUS*RADIUS-X*X-Y*Y ) ) ) );\r
+      case Random(3) of\r
+        0: Swap( X, Z );\r
+        1: Swap( Y, Z );\r
+      end;\r
+      X := X * $10000; Y := Y * $10000; Z := Z * $10000;\r
+    end;\r
+  end;\r
+  (* Initialize morphing *)\r
+  Move( CubeVtx^, Vtx^, SizeOf(Vtx^) );\r
+  Status := 0;\r
+  Count := WAITCOUNT;\r
+end;\r
+\r
+procedure Morph;\r
+var\r
+  I: integer;\r
+begin\r
+  (* Fully unoptimized, slowest loop I could think of! *)\r
+  for I:=0 to MAXVTX-1 do begin\r
+    Vtx^[I].X := ((CubeVtx^[I].X * Morph1)+(SphereVtx^[I].X * Morph2)) div MS;\r
+    Vtx^[I].Y := ((CubeVtx^[I].Y * Morph1)+(SphereVtx^[I].Y * Morph2)) div MS;\r
+    Vtx^[I].Z := ((CubeVtx^[I].Z * Morph1)+(SphereVtx^[I].Z * Morph2)) div MS;\r
+  end;\r
+end;\r
+\r
+var\r
+  AX, AY, AZ: byte;\r
+  I: word;\r
+  C: char;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;          (* Start with hidden page *)\r
+\r
+  AX := 0;\r
+  AY := 0;\r
+  AZ := 0;\r
+  (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+  tdSetTranslation( Trans );\r
+  tdSetPerspective( 400*$10000, $10000, $10000 );\r
+  C := #0;\r
+  repeat\r
+    tdSetRotation( AX, AY, AZ );                (* Set new angles *)\r
+    tdTransform( Vtx^, XVtx^, MAXVTX );         (* 3D transform points *)\r
+    tdTransformToImage( XVtx^, VVtx, MAXVTX, 160, 120+Page );\r
+    Inc( AX, 1 );                               (* Bump angles *)\r
+    Inc( AY, 1 );\r
+    Inc( AZ, 2 );\r
+    mxSetClipRegion( 0, Page, 320, 240 );       (* Set clip to new page *)\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+    (* Draw points *)\r
+    for I:=0 to MAXVTX-1 do\r
+      mxPutPixel( VVtx[I].X, VVtx[I].Y, 128 + XVtx^[I].Z shr 18 );\r
+    mxStartLine( Page );                        (* Flip pages *)\r
+    Page := 240-Page;\r
+    (* Morph *)\r
+    if( Odd(Status) ) then begin\r
+      Morph;\r
+      Inc( Morph1, Delta1 );\r
+      Inc( Morph2, Delta2 );\r
+      if( Morph1 < 0 )or( Morph2 < 0 ) then Inc( Status );\r
+      if( Status = 4 ) then Status := 0;\r
+    end\r
+    else begin\r
+      Dec( Count );\r
+      if( Count < 0 ) then begin\r
+        Inc( Status );\r
+        Count :=  WAITCOUNT;\r
+        Morph1 := InitMorph1[Status];\r
+        Morph2 := InitMorph2[Status];\r
+        Delta1 := InitDelta1[Status];\r
+        Delta2 := InitDelta2[Status];\r
+      end;\r
+    end;\r
+  until( KeyPressed );\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw_/modex/DEMO04.DAT b/16/xw_/modex/DEMO04.DAT
new file mode 100755 (executable)
index 0000000..72aaad0
Binary files /dev/null and b/16/xw_/modex/DEMO04.DAT differ
diff --git a/16/xw_/modex/DEMO04.EXE b/16/xw_/modex/DEMO04.EXE
new file mode 100755 (executable)
index 0000000..1fec5e8
Binary files /dev/null and b/16/xw_/modex/DEMO04.EXE differ
diff --git a/16/xw_/modex/DEMO04.PAS b/16/xw_/modex/DEMO04.PAS
new file mode 100755 (executable)
index 0000000..1a94631
--- /dev/null
@@ -0,0 +1,198 @@
+(*\r
+    DEMO04 - Multiple textures and triple buffering (3 pages)\r
+    (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+const\r
+  MAXVTX = 256;\r
+  MAXCUB = 2;\r
+  MAXTXT = 2;\r
+  Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+  TxtSunDial: array[ 0..7 ] of word = (\r
+    $7F80,$0080, $0080,$0080, $0080,$7E80, $7F80,$7E80 );\r
+  TxtSapphire : array[ 0..7 ] of word = (\r
+    $0080,$0080, $0080,$1F80, $1F80,$1F80, $1F80,$0080 );\r
+  TxtMarble: array[ 0..7 ] of word = (\r
+    $0080,$8080, $0080,$FD80, $7F80,$FD80, $7F80,$8080 );\r
+type\r
+  T2DPoint = record\r
+    X, Y: integer;\r
+  end;\r
+  TTexture = record\r
+    Desc   : array[ 0..3 ] of record X, Y: word end;\r
+    Width  : word;\r
+    Data   : pointer;\r
+  end;\r
+  TQuad = record\r
+    Vtx    : array[ 0..3 ] of word;\r
+    Texture: word;\r
+  end;\r
+  TCube    = record\r
+    Face   : array[ 0..5 ] of TQuad;\r
+    Base   : integer;\r
+  end;\r
+var\r
+  Vtx, XVtx: array[ 0..MAXVTX ] of TPoint;\r
+  VVtx     : array[ 0..MAXVTX ] of T2DPoint;\r
+  Cube     : array[ 0..MAXCUB ] of TCube;\r
+  ZList    : array[ 0..MAXCUB ] of integer;\r
+  VtxCnt   : word;\r
+  Txts     : array[ 0..MAXTXT ] of TTexture;\r
+  Page     : word;\r
+  Palette  : array[ byte ] of record R, G, B: byte; end;\r
+  TxtDat1, TxtDat2: pointer;\r
+\r
+(* Add a new entry to the vertex array *)\r
+procedure AddVtx( PX, PY, PZ: longint );\r
+begin\r
+  with Vtx[VtxCnt] do begin X:=PX*$10000; Y:=PY*$10000; Z:=PZ*$10000; end;\r
+  Inc( VtxCnt );\r
+end;\r
+\r
+procedure MakeCube( var C: TCube; X1,Y1,Z1, X2,Y2,Z2, TX,TY,TZ, Texture: integer );\r
+const\r
+  FaceIdx: array[ 0..23 ] of integer = (\r
+    0,1,2,3, 0,4,5,1, 1,5,6,2, 2,6,7,3, 3,7,4,0, 6,5,4,7 );\r
+var\r
+  I, VC: integer;\r
+begin\r
+  VC := VtxCnt;\r
+  C.Base := VC;\r
+  AddVtx( X1+TX, Y1+TY, Z1+TZ );\r
+  AddVtx( X2+TX, Y1+TY, Z1+TZ );\r
+  AddVtx( X2+TX, Y2+TY, Z1+TZ );\r
+  AddVtx( X1+TX, Y2+TY, Z1+TZ );\r
+  AddVtx( X1+TX, Y1+TY, Z2+TZ );\r
+  AddVtx( X2+TX, Y1+TY, Z2+TZ );\r
+  AddVtx( X2+TX, Y2+TY, Z2+TZ );\r
+  AddVtx( X1+TX, Y2+TY, Z2+TZ );\r
+  for I:=0 to 23 do C.Face[I shr 2].Vtx[I and 3] := VC+FaceIdx[I];\r
+  for I:=0 to 5 do C.Face[I].Texture := Texture;\r
+end;\r
+\r
+procedure MakeTexture( Idx: integer; var VtxData );\r
+var\r
+  P: ^word;\r
+  I: integer;\r
+begin\r
+  P := @VtxData;\r
+  with Txts[Idx] do begin\r
+    for I:=0 to 3 do begin\r
+      Desc[I].X := P^; Inc( P );\r
+      Desc[I].Y := P^; Inc( P );\r
+    end;\r
+    Width := 129;\r
+    Data := TxtDat1;\r
+  end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+  I: integer;\r
+  V: integer;\r
+  F: file;\r
+  P: array[ 1..768 ] of byte;\r
+begin\r
+  (* Initialize objects *)\r
+  VtxCnt := 0;\r
+  MakeCube( Cube[0], -64,-64,8, 64,64,-8, 0,0,0, 1 );   (* Sundial *)\r
+  Cube[0].Face[0].Texture := 0;\r
+  V := VtxCnt;\r
+  MakeCube( Cube[1], -16,-16,16, 16,16,-16, 0,0,0, 2 ); (* Sapphire *)\r
+  tdSetTranslation( Trans );\r
+  tdSetRotation( 32, 32, 00 );\r
+  tdRotate( Vtx[V], XVtx[V], 8 );       (* Got to rotate this cube *)\r
+  for I:=V to V+7 do begin\r
+    Vtx[I].X := XVtx[I].X;\r
+    Vtx[I].Y := XVtx[I].Y;\r
+    Vtx[I].Z := XVtx[I].Z + 100*$10000;\r
+  end;\r
+  MakeCube( Cube[2], -64,-4,48, 64,4,-48, 0,68,56, 1 ); (* Marble *)\r
+  (* Load texture and palette *)\r
+  Assign( F, 'DEMO04.DAT' );\r
+  Reset( F, 1 );\r
+  BlockRead( F, P, SizeOf(P) );\r
+  mxSetPalette( @P, 0, 256 );\r
+  GetMem( TxtDat1, 63*1024 );\r
+  BlockRead( F, TxtDat1^, 129*286 );\r
+  Close( F );\r
+  TxtDat2 := Ptr( Seg(TxtDat1^), Ofs(TxtDat1^)+129*254 );\r
+  (* Init textures *)\r
+  MakeTexture( 0, TxtSundial );\r
+  MakeTexture( 1, TxtMarble );\r
+  MakeTexture( 2, TxtSapphire );\r
+  Txts[2].Data := TxtDat2;\r
+end;\r
+\r
+(* Sort procedure, not worth optimizing with only a few objects *)\r
+procedure SortObjects;\r
+var\r
+  I, J, K: integer;\r
+  ZMax: array[ 0..MAXCUB ] of longint;\r
+  ZI: integer;\r
+  L: longint;\r
+begin\r
+  for I:=0 to MAXCUB do begin\r
+    L := XVtx[Cube[I].Base].Z;\r
+    for J:=1 to 7 do\r
+      if( L > XVtx[Cube[I].Base+J].Z ) then L := XVtx[Cube[I].Base+J].Z;\r
+    ZMax[I] := L;\r
+    ZList[I] := I;\r
+  end;\r
+  for I:=0 to MAXCUB-1 do begin\r
+    ZI := I;\r
+    for J:=I+1 to MAXCUB do\r
+      if( ZMax[ZList[J]] > ZMax[ZList[ZI]] ) then ZI := J;\r
+    if( ZI <> I ) then begin\r
+      K := ZList[I];\r
+      ZList[I] := ZList[ZI];\r
+      ZList[ZI] := K;\r
+    end;\r
+  end;\r
+end;\r
+\r
+var\r
+  AX, AY, AZ: byte;\r
+  I, J, K: word;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;          (* Start with hidden page *)\r
+\r
+  (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+  AX := 0; AY := 0; AZ := 0;\r
+  tdSetTranslation( Trans );\r
+  tdSetPerspective( 600*$10000, $10000, $10000 );\r
+  (* Main loop, all magic here! *)\r
+  while( not KeyPressed ) do begin\r
+    tdSetRotation( AX, AY, AZ );                (* Set new angles *)\r
+    tdTransform( Vtx, XVtx, VtxCnt );           (* 3D transform points *)\r
+    tdTransformToImage( XVtx, VVtx, VtxCnt, 160, 120+Page );\r
+    Inc( AX, 1 );                               (* Bump angles *)\r
+    Inc( AY, 2 );\r
+    Inc( AZ, 1 );\r
+    mxSetClipRegion( 0, Page, 320, 240 );       (* Set clip to new page *)\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+    (* Draw objects *)\r
+    SortObjects;\r
+    for I:=0 to MAXCUB do with Cube[ZList[I]] do begin\r
+      for J:=0 to 5 do begin\r
+        K := Face[J].Texture;\r
+        mxTexturePoly( 4, Face[J].Vtx, VVtx, Txts[K].Desc, Txts[K].Data^, Txts[K].Width );\r
+      end;\r
+    end;\r
+    (* Flip page: at 320x240 the Start Address Register Low is always zero *)\r
+    case Page of\r
+      0  : begin PortW[$3D4] := $000C; Page := 240; end;\r
+      240: begin PortW[$3D4] := $4B0C; Page := 480; end;\r
+      480: begin PortW[$3D4] := $960C; Page := 0; end;\r
+    end;\r
+    mxWaitRetrace; (* If the frame rate seems low, try to remove this line *)\r
+  end;\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw_/modex/DEMO05.EXE b/16/xw_/modex/DEMO05.EXE
new file mode 100755 (executable)
index 0000000..21a7c20
Binary files /dev/null and b/16/xw_/modex/DEMO05.EXE differ
diff --git a/16/xw_/modex/DEMO05.PAS b/16/xw_/modex/DEMO05.PAS
new file mode 100755 (executable)
index 0000000..819c5cf
--- /dev/null
@@ -0,0 +1,131 @@
+(*\r
+   DEMO05 - A Gouraud-shaded rotating torus\r
+   (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+(* Define ALTPAL for alternate palette *)\r
+{$define ALTPAL}\r
+\r
+const\r
+  MAXVTX1 = 15; RADIUS1 = 70;   (* MAXVTX1+1 must be multiple of 4 *)\r
+  MAXVTX2 = 15; RADIUS2 = 30;\r
+  MAXVTX  = (MAXVTX1+1)*(MAXVTX2+1)-1;\r
+  MAXFACE = MAXVTX;\r
+  Trans : TPoint = ( X:0; Y:0; Z:0 );           (* Object translation *)\r
+  Light : TPoint = ( X:0; Y:0; Z:-63*$10000 );  (* Light direction *)\r
+type\r
+  TQuad   = record\r
+    QVtx  : array[ 0..3 ] of integer;\r
+  end;\r
+var\r
+  Vtx, XVtx : array[ 0..MAXVTX ] of TPoint;     (* Points *)\r
+  VVtx      : array[ 0..MAXVTX ] of record X, Y: integer end;\r
+  Face      : array[ 0..MAXFACE ] of TQuad;     (* Polys *)\r
+  Culled    : array[ 0..MAXFACE ] of integer;\r
+  GNrm,XGNrm: array[ 0..MAXVTX ] of TVector;    (* Gouraud normals *)\r
+  VtxLight  : array[ 0..MAXVTX ] of integer;    (* Points brightness *)\r
+  Page      : word;\r
+\r
+function GetVtx( I1, I2: integer ): integer;\r
+begin\r
+  GetVtx := (I1 mod (MAXVTX1+1))*(MAXVTX2+1) + I2 mod (MAXVTX2+1);\r
+end;\r
+\r
+procedure Init;\r
+var\r
+  R, N, X, Y, Z: real;\r
+  I, J, K, V: integer;\r
+begin\r
+  (* Build vertexes *)\r
+  for I:=0 to MAXVTX1 do begin\r
+    K := (I + (MAXVTX1+1) shr 2) mod (MAXVTX1+1);\r
+    R := RADIUS1 + RADIUS2*Cos( 2*K*Pi / (MAXVTX1+1) );\r
+    for J:=0 to MAXVTX2 do begin\r
+      V := I*(MAXVTX2+1)+J;                     (* Index of current vertex *)\r
+      (* Compute coordinates of current vertex *)\r
+      X := R*Cos(2*J*Pi / (MAXVTX2+1));         (* Get coordinates *)\r
+      Y := R*Sin(2*J*Pi / (MAXVTX2+1));\r
+      Z := RADIUS2*Sin(2*K*Pi / (MAXVTX1+1));\r
+      Vtx[V].X := Round( X )*$10000;            (* Save coordinates *)\r
+      Vtx[V].Y := Round( Y )*$10000;\r
+      Vtx[V].Z := Round( Z )*$10000;\r
+      (* Compute direction of Gouraud normal thru current vertex *)\r
+      X := X - RADIUS1*Cos(2*J*Pi / (MAXVTX2+1));\r
+      Y := Y - RADIUS1*Sin(2*J*Pi / (MAXVTX2+1));\r
+      N := Sqrt( X*X + Y*Y + Z*Z );             (* Get vector length *)\r
+      GNrm[V].X := Trunc( X*$10000/N );         (* Save normal vector *)\r
+      GNrm[V].Y := Trunc( Y*$10000/N );\r
+      GNrm[V].Z := Trunc( Z*$10000/N );\r
+    end;\r
+  end;\r
+  (* Generate faces so that depth-sorting is not needed: there are still *)\r
+  (* some *very* little errors, but this is the best I could devise *)\r
+  J := 0;\r
+  K := 0;\r
+  for I:=0 to MAXFACE do with Face[I] do begin\r
+    QVtx[0] := GetVtx( J, K );\r
+    QVtx[1] := GetVtx( J, K+1 );\r
+    QVtx[2] := GetVtx( J+1, K+1 );\r
+    QVtx[3] := GetVtx( J+1, K );\r
+    Inc( K );\r
+    if( K > MAXVTX2 ) then begin\r
+      K := 0;\r
+      Inc( J );\r
+    end;\r
+  end;\r
+{$ifndef ALTPAL}\r
+  for I:=0 to 63 do mxSetColor( I+64, 0, 0, I );     (* Blue palette *)\r
+{$else}\r
+  for I:=0 to 31 do mxSetColor(I+64, 0, I shl 1, 0); (* Green neon palette *)\r
+  for I:=32 to 63 do mxSetColor ( I+64, (I-32) shl 1, 63, (I-32) shl 1 );\r
+{$endif}\r
+end;\r
+\r
+var\r
+  AX, AY, AZ: byte;\r
+  I: word;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;          (* Start with hidden page *)\r
+\r
+  AX := 0;\r
+  AY := 0;\r
+  AZ := 0;\r
+  (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+  tdSetTranslation( Trans );\r
+  tdSetLight( Light );\r
+  tdSetPerspective( 400*$10000, $10000, $10000 );\r
+  (* Main loop, all magic here! *)\r
+  while( not KeyPressed ) do begin\r
+    tdSetRotation( AX, AY, AZ );                (* Set new angles *)\r
+    tdTransform( Vtx, XVtx, MAXVTX+1 );         (* 3D transform points *)\r
+    tdTransformToImage( XVtx, VVtx, MAXVTX+1, 160, 120+Page );\r
+    tdRotate( GNrm, XGNrm, MAXVTX+1 );          (* Rotate Gouraud normals *)\r
+    tdTransformLight( XGNrm, VtxLight, MAXVTX+1 );\r
+    (* Backplane culling is not really needed here! *)\r
+    FillChar( Culled, SizeOf(Culled), 0 );\r
+    tdBackPlaneCull( Face, XVtx, Culled, MAXFACE+1, SizeOf(TQuad) );\r
+    Inc( AX, 1 );                               (* Bump angles *)\r
+    Inc( AY, 2 );\r
+    Inc( AZ, 3 );\r
+    mxSetClipRegion( 0, Page, 320, 240 );       (* Set clip to new page *)\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+    (* Draw polygons *)\r
+    for I:=0 to MAXFACE do with Face[I] do\r
+      if( Culled[I] >= 0 ) then mxGouraudPoly( 4, QVtx, VVtx, VtxLight, 64 );\r
+    (* Flip page: at 320x240 the Start Address Register Low is always zero *)\r
+    case Page of\r
+      0  : begin PortW[$3D4] := $000C; Page := 240; end;\r
+      240: begin PortW[$3D4] := $4B0C; Page := 480; end;\r
+      480: begin PortW[$3D4] := $960C; Page := 0; end;\r
+    end;\r
+    mxWaitRetrace; (* Uncomment this instruction if screen flickers *)\r
+  end;\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw_/modex/DEMO06.DAT b/16/xw_/modex/DEMO06.DAT
new file mode 100755 (executable)
index 0000000..1ac2c2b
Binary files /dev/null and b/16/xw_/modex/DEMO06.DAT differ
diff --git a/16/xw_/modex/DEMO06.EXE b/16/xw_/modex/DEMO06.EXE
new file mode 100755 (executable)
index 0000000..f1308e8
Binary files /dev/null and b/16/xw_/modex/DEMO06.EXE differ
diff --git a/16/xw_/modex/DEMO06.PAS b/16/xw_/modex/DEMO06.PAS
new file mode 100755 (executable)
index 0000000..f26af06
--- /dev/null
@@ -0,0 +1,135 @@
+(*\r
+    DEMO06 - Magnifying glass\r
+    (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+  R = 40;               (* Lens radius *)\r
+  K : real = 1.8;       (* Magnifying factor, less makes a stronger lens *)\r
+type\r
+  TLine   = array[ 0..319 ] of byte;\r
+  PLine   = ^TLine;\r
+  TScreen = array[ 0..239 ] of PLine;\r
+var\r
+  VScreen: TScreen;                             (* Virtual screen *)\r
+  BallX  : array[ 0..R, 0..R ] of integer;\r
+  BallY  : array[ 0..R, 0..R ] of integer;\r
+  Sprite : array[ -R..R, -R..R ] of byte;\r
+  Page   : word;\r
+\r
+(* Returns "lens-view" coordinates of X,Y *)\r
+procedure GetCoords( var X, Y: integer );\r
+var\r
+  LR, Z, SinA, SinB, TgB, Q: real;\r
+begin\r
+  LR := Sqrt( X*X + Y*Y );\r
+  if( LR = 0 ) then Exit;\r
+  if( LR < R ) then begin\r
+    Z := Sqrt( R*R - LR*LR );\r
+    SinA := LR / R;\r
+    SinB := SinA / K;\r
+    TgB := SinB / Sqrt( 1-SinB*SinB );\r
+    Q := LR - TgB*Z;\r
+    X := Round( X * ( Q/LR ) );\r
+    Y := Round( Y * ( Q/LR ) );\r
+  end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+  F      : file;\r
+  Palette: array[ 0..767 ] of record R, G, B: byte; end;\r
+  X, Y,\r
+  X2, Y2 : integer;\r
+begin\r
+  (* Load background image *)\r
+  Assign( F, 'demo06.dat' );\r
+  Reset( F, 1 );\r
+  BlockRead( F, Palette, 768 );\r
+  mxSetPalette( @Palette, 0, 256 );\r
+  for Y:=0 to 239 do begin\r
+    New( VScreen[Y] );\r
+    BlockRead( F, VScreen[Y]^, 320 );\r
+    mxPutImage( VScreen[Y], 0, 480+Y, 320, 1, OP_MOVE );\r
+  end;\r
+  Close( F );\r
+  (* Build lens *)\r
+  for X:=0 to R do begin\r
+    for Y:=0 to R do begin\r
+      X2 := X;\r
+      Y2 := Y;\r
+      GetCoords( X2, Y2 );\r
+      BallX[X, Y] := X2;\r
+      BallY[X, Y] := Y2;\r
+    end;\r
+  end;\r
+end;\r
+\r
+procedure PutLens( OX, OY: integer );\r
+var\r
+  X, Y: integer;\r
+begin\r
+  for X:=0 to R do begin\r
+    for Y:=0 to R do begin\r
+      Sprite[Y][X] := VScreen[ OY+BallY[X,Y] ]^[ OX+BallX[X,Y] ];\r
+      Sprite[Y][-X] := VScreen[ OY+BallY[X,Y] ]^[ OX-BallX[X,Y] ];\r
+      Sprite[-Y][X] := VScreen[ OY-BallY[X,Y] ]^[ OX+BallX[X,Y] ];\r
+      Sprite[-Y][-X] := VScreen[ OY-BallY[X,Y] ]^[ OX-BallX[X,Y] ];\r
+    end;\r
+  end;\r
+  (* Draw the sprite *)\r
+  mxPutImage( @Sprite, OX-R, OY-R+Page, 2*R+1, 2*R+1, OP_MOVE );\r
+end;\r
+\r
+function Delta: integer;\r
+begin\r
+  Delta := Random(3)+2;\r
+end;\r
+\r
+procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer );\r
+begin\r
+  if( Cond ) then begin\r
+    Coord := NewCoord;\r
+    DeltaC := Sign*Delta;\r
+  end;\r
+end;\r
+\r
+var\r
+  X, Y, DX, DY: integer;\r
+  C: char;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;\r
+  X := R;\r
+  Y := R;\r
+  Randomize;\r
+  DX := Delta;\r
+  DY := Delta;\r
+\r
+  (* Main loop *)\r
+  repeat\r
+    (* Update video *)\r
+    mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+    PutLens( X, Y );\r
+    mxCircle( X, Page+Y, R, 0 );\r
+    (* Update lens coordinates *)\r
+    Inc( X, DX );\r
+    Check( X+R >= 319, X, DX, 319-R, -1 );\r
+    Check( X <= R, X, DX, R, +1 );\r
+    Inc( Y, DY );\r
+    Check( Y+R >= 239, Y, DY, 239-R, -1 );\r
+    Check( Y <= R, Y, DY, R, +1 );\r
+    (* Flip pages: double buffering, avoid wait for display *)\r
+    case Page of\r
+      0  : begin PortW[$3D4] := $000C; Page := 240; end;\r
+      240: begin PortW[$3D4] := $4B0C; Page := 0; end;\r
+    end;\r
+    mxWaitRetrace; (* Wait for hidden page to show *)\r
+  until( KeyPressed );\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw_/modex/DEMO07.EXE b/16/xw_/modex/DEMO07.EXE
new file mode 100755 (executable)
index 0000000..8a40116
Binary files /dev/null and b/16/xw_/modex/DEMO07.EXE differ
diff --git a/16/xw_/modex/DEMO07.PAS b/16/xw_/modex/DEMO07.PAS
new file mode 100755 (executable)
index 0000000..04fff79
--- /dev/null
@@ -0,0 +1,68 @@
+(*\r
+    DEMO07 - Hardware scrolling\r
+    Copyright (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+  (* Change this if scrolling seems jerky (this simple program does *)\r
+  (* not handle vertical retrace/display very well) *)\r
+  STEPS = 5;\r
+\r
+procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer );\r
+begin\r
+  if( Cond ) then begin\r
+    Coord := NewCoord;\r
+    DeltaC := Sign*(Random(3)+2);\r
+  end;\r
+end;\r
+\r
+var\r
+  I, X, Y, DX, DY: integer;\r
+begin\r
+  (* Initialize library and graphics mode *)\r
+  mxInit;\r
+  mxSetMode( MX_320x200 );\r
+  (* Set a 640x400 virtual screen *)\r
+  mxSetVirtualScreen( 640, 400 );\r
+  mxSetClip( TRUE );\r
+\r
+  X := 0;\r
+  Y := 0;\r
+  DX := 1;\r
+  DY := 1;\r
+\r
+  (* Main loop: draw lines, circles, points and rectangles in separate *)\r
+  (* 320x200 windows, while smoothly panning virtual screen *)\r
+  while( not KeyPressed ) do begin\r
+    (* Points *)\r
+    mxSetClipRegion( 0, 0, 320, 200 );\r
+    for I:=1 to STEPS do\r
+      mxPutPixel( Random(320), Random(200), Random(16) );\r
+    (* Lines *)\r
+    mxSetClipRegion( 0, 200, 320, 200 );\r
+    for I:=1 to STEPS do\r
+      mxLine( Random(320), Random(200)+200, Random(320), Random(200)+200, Random(16), OP_SET );\r
+    (* Circles *)\r
+    mxSetClipRegion( 320, 0, 320, 200 );\r
+    for I:=1 to STEPS do\r
+      mxCircle( Random(320)+320, Random(200), Random(100), Random(16) );\r
+    (* Boxes *)\r
+    mxSetClipRegion( 320, 200, 320, 200 );\r
+    for I:=1 to STEPS do\r
+      mxFillBox( Random(320)+320, Random(200)+200, Random(100)+1, Random(100)+1, Random(16), OP_SET );\r
+    (* Pan *)\r
+    Inc( X, DX );\r
+    Check( X+320 >= 639, X, DX, 319, -1 );\r
+    Check( X < 0, X, DX, 0, +1 );\r
+    Inc( Y, DY );\r
+    Check( Y+200 >= 399, Y, DY, 199, -1 );\r
+    Check( Y < 0, Y, DY, 0, +1 );\r
+    mxPan( X, Y );\r
+    mxWaitRetrace;\r
+  end;\r
+\r
+  (* Shutdown *)\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw_/modex/MATH.INC b/16/xw_/modex/MATH.INC
new file mode 100755 (executable)
index 0000000..742af41
--- /dev/null
@@ -0,0 +1,34 @@
+;\r
+; MATH.INC - Include file for THREED.ASM\r
+;\r
+\r
+; 3-dimensional point, coordinates in fixed format (16:16)\r
+;\r
+TPOINT  STRUC\r
+        X       DD      ?\r
+        Y       DD      ?\r
+        Z       DD      ?\r
+TPOINT  ENDS\r
+\r
+; 2-dimensional point, coordinates in integer format\r
+;\r
+TIMAGEPOINT     STRUC\r
+        IX      DW      ?\r
+        IY      DW      ?\r
+TIMAGEPOINT     ENDS\r
+\r
+; Fixed-point divide: EAX = EAX / arg\r
+;\r
+.xdiv   MACRO   arg\r
+        xor     edx, edx\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    arg\r
+ENDM\r
+\r
+; Fixed-point multiply: EAX = EAX * arg\r
+;\r
+.xmul   MACRO   arg\r
+        imul    arg\r
+        shrd    eax, edx, 16\r
+ENDM\r
diff --git a/16/xw_/modex/PLASMA.PAS b/16/xw_/modex/PLASMA.PAS
new file mode 100755 (executable)
index 0000000..237e292
--- /dev/null
@@ -0,0 +1,103 @@
+unit Plasma;\r
+interface\r
+\r
+const\r
+  PAL_RGB       = 0;\r
+  PAL_CLOUDS    = 1;\r
+  PAL_LANDSCAPE = 2;\r
+\r
+procedure MakePlasma( X, Y: integer; W, H: word; C1, C2, C3, C4: byte );\r
+procedure MakePlasmaPalette( var Palette; What: word );\r
+\r
+implementation uses Modex;\r
+\r
+procedure NewColor( XA, YA, X, Y, XB, YB: integer );\r
+var\r
+  Color: longint;\r
+begin\r
+  Color := Abs( XA-XB )+Abs( YA-YB );\r
+  Color := Random( Color shl 1 )-Color;\r
+  Color := (Color+mxGetPixel( XA, YA )+mxGetPixel( XB, YB )+1) shr 1;\r
+  if( Color < 1 ) then Color := 1;\r
+  if( Color > 192 ) then Color := 192;\r
+  if( mxGetPixel( X, Y ) = 0 ) then\r
+    mxPutPixel( X, Y, Lo(Color) );\r
+end;\r
+\r
+procedure Divide( X1, Y1, X2, Y2: integer );\r
+var\r
+  X, Y, Color: integer;\r
+begin\r
+  if not( (X2-X1<2)and(Y2-Y1<2) ) then begin\r
+    X := (X1+X2) shr 1;\r
+    Y := (Y1+Y2) shr 1;\r
+    NewColor( X1, Y1, X, Y1, X2, Y1 );\r
+    NewColor( X2, Y1, X2, Y, X2, Y2 );\r
+    NewColor( X1, Y2, X, Y2, X2, Y2 );\r
+    NewColor( X1, Y1, X1, Y, X1, Y2 );\r
+    Color := (mxGetPixel( X1, Y1 )+mxGetPixel( X2, Y1 )+\r
+              mxGetPixel( X2, Y2 )+mxGetPixel( X1, Y2 )) shr 2;\r
+    mxPutPixel( X, Y, Color );\r
+    Divide( X1, Y1, X, Y );\r
+    Divide( X, Y1, X2, Y );\r
+    Divide( X, Y, X2, Y2 );\r
+    Divide( X1, Y, X, Y2 );\r
+  end;\r
+end;\r
+\r
+procedure MakePlasma;\r
+begin\r
+  Dec( W );\r
+  Dec( H );\r
+  mxPutPixel( X, Y, C1 );\r
+  mxPutPixel( X, Y+H, C2 );\r
+  mxPutPixel( X+W, Y+H, C3 );\r
+  mxPutPixel( X+W, Y, C4 );\r
+  Divide( X, Y, X+W, Y+H );\r
+end;\r
+\r
+procedure MakePlasmaPalette;\r
+type\r
+  TPal = array[ byte ] of record R, G, B: byte end;\r
+var\r
+  I: word;\r
+begin\r
+  FillChar( TPal(Palette)[1], 192*3, 0 );\r
+  case What of\r
+    PAL_CLOUDS:\r
+      for I:=1 to 192 do begin\r
+        TPal(Palette)[I].R := Abs( I-96 )*63 div 96;\r
+        TPal(Palette)[I].G := Abs( I-96 )*63 div 96;\r
+        TPal(Palette)[I].B := 63;\r
+      end;\r
+    PAL_LANDSCAPE:\r
+      begin\r
+        for I:=0 to 31 do begin\r
+          TPal(Palette)[I+1].R := I;\r
+          TPal(Palette)[I+1].G := I;\r
+          TPal(Palette)[I+1].B := I + I shr 1+15;\r
+        end;\r
+        for I:=32 to 63 do begin\r
+          TPal(Palette)[I+1].R := 0;\r
+          TPal(Palette)[I+1].G := I;\r
+          TPal(Palette)[I+1].B := 0;\r
+        end;\r
+        for I:=64 to 191 do begin\r
+          TPal(Palette)[I+1].R := (I-64) div 3 + 15;\r
+          TPal(Palette)[I+1].G := (I-64) div 3 + 15;\r
+          TPal(Palette)[I+1].B := (I-64) div 3 + 15;\r
+        end;\r
+      end;\r
+    else\r
+      for I:=1 to 64 do begin\r
+        TPal(Palette)[I].G := I-1;\r
+        TPal(Palette)[I].B := 64-I;\r
+        TPal(Palette)[I+64].R := I-1;\r
+        TPal(Palette)[I+64].G := 64-I;\r
+        TPal(Palette)[I+128].B := I-1;\r
+        TPal(Palette)[I+128].R := 64-I;\r
+      end;\r
+  end;\r
+end;\r
+\r
+end.
\ No newline at end of file
diff --git a/16/xw_/modex/QIX2.EXE b/16/xw_/modex/QIX2.EXE
new file mode 100755 (executable)
index 0000000..a10d7db
Binary files /dev/null and b/16/xw_/modex/QIX2.EXE differ
diff --git a/16/xw_/modex/QIX2.PAS b/16/xw_/modex/QIX2.PAS
new file mode 100755 (executable)
index 0000000..d1b5979
--- /dev/null
@@ -0,0 +1,210 @@
+{$E-,N+}\r
+uses Crt, Modex;\r
+\r
+const\r
+  DEFVERT = 12;         (* Vertex count *)\r
+  DEFREPL = 3;          (* Repetition count *)\r
+  DEFQIXS = 2;          (* Qixs *)\r
+  FADESPEED = 48;\r
+type\r
+  TPoint = record\r
+    X, Y : integer;\r
+  end;\r
+  TRGB = record\r
+    R, G, B: byte;\r
+  end;\r
+  TQix = record\r
+    Color: integer;\r
+    Vert : array[ 0..DEFVERT-1, 0..DEFREPL-1 ] of TPoint;\r
+    Delta: array[ 0..DEFVERT-1 ] of TPoint;\r
+  end;\r
+var\r
+  Page : integer;\r
+  MaxX,\r
+  MaxY : word;\r
+  Qix  : array[ 0..DEFQIXS-1 ] of TQix;\r
+  Pal  : array[ byte ] of TRGB;\r
+\r
+type\r
+  TReal = double;\r
+  TRPoint = record\r
+    X, Y: TReal;\r
+  end;\r
+  TMatrix = array[ 0..3, 0..3 ] of TReal;\r
+var\r
+  M: TMatrix;\r
+  G: array[ 0..DEFVERT-1 ] of TRPoint;\r
+  C: array[ 0..DEFVERT-1 ] of TRPoint;\r
+\r
+procedure BumpPal( Idx, DR, DG, DB, Steps: integer );\r
+var\r
+  I: integer;\r
+begin\r
+  for I:=1 to Steps do begin\r
+    Pal[Idx+1].R := Pal[Idx].R + DR;\r
+    Pal[Idx+1].G := Pal[Idx].G + DG;\r
+    Pal[Idx+1].B := Pal[Idx].B + DB;\r
+    Inc( Idx );\r
+  end;\r
+end;\r
+\r
+procedure InitPalette;\r
+begin\r
+  with Pal[0] do begin R:=0; G:=0; B:=0; end;\r
+  with Pal[1] do begin R:=0; G:=0; B:=62; end;\r
+  BumpPal( 1,   0, 2, -2,  31 );\r
+  BumpPal( 32,  2, -2, 0,  31 );\r
+  BumpPal( 63,  -2, 2, 2,  31 );\r
+  BumpPal( 94,  2, 0, -2,  31 );\r
+  BumpPal( 125, -2, -2, 2, 31 );\r
+end;\r
+\r
+procedure Init( var Qix: TQix; Color: integer );\r
+var\r
+  I: integer;\r
+begin\r
+  FillChar( Qix.Vert, SizeOf(Qix.Vert), 0 );\r
+  for I:=0 to DEFVERT-1 do begin\r
+    Qix.Vert[I, DEFREPL-1].X := Random( MaxX );\r
+    Qix.Vert[I, DEFREPL-1].Y := Random( MaxY );\r
+    Qix.Delta[I].X := Random(5)+1;\r
+    Qix.Delta[I].Y := Random(5)+1;\r
+  end;\r
+  Qix.Color := Color;\r
+\r
+  (* Initialize matrix (Catmull-Rom) *)\r
+  M[0,0] := -1/2; M[0,1] := 3/2; M[0,2] := -3/2; M[0,3] := 1/2;\r
+  M[1,0] := 1; M[1,1] := -5/2; M[1,2] := 2; M[1,3] := -1/2;\r
+  M[2,0] := -1/2; M[2,1] := 0; M[2,2] := 1/2; M[2,3] := 0;\r
+  M[3,0] := 0; M[3,1] := 1; M[3,2] := 0; M[3,3] := 0;\r
+end;\r
+\r
+procedure mxBezier( var Qix: TQix; I0, Idx, N: integer );\r
+var\r
+  I, J: integer;\r
+  T, T2, T3: TReal;\r
+  X0, Y0, X, Y: TReal;\r
+  Delta: TReal;\r
+begin\r
+  (* Compute coefficients *)\r
+  for I:=0 to 3 do begin\r
+    C[I].X := 0;\r
+    for J:=0 to 3 do C[I].X := C[I].X + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].X;\r
+    C[I].Y := 0;\r
+    for J:=0 to 3 do C[I].Y := C[I].Y + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].Y;\r
+  end;\r
+  X0 := C[3].X;\r
+  Y0 := C[3].Y;\r
+  Delta := 1 / N;\r
+  T := 0;\r
+  for I:=1 to N do begin\r
+    T := T + Delta;\r
+    T2 := T*T;\r
+    T3 := T*T2;\r
+    X := C[0].X*T3 + C[1].X*T2 + C[2].X*T + C[3].X;\r
+    Y := C[0].Y*T3 + C[1].Y*T2 + C[2].Y*T + C[3].Y;\r
+    mxLine( Round(X0), Page+Round(Y0), Round(X), Page+Round(Y), Qix.Color, OP_SET );\r
+    X0 := X;\r
+    Y0 := Y;\r
+  end;\r
+end;\r
+\r
+procedure Plot( var Qix: TQix; Idx: integer );\r
+var\r
+  I, J: integer;\r
+begin\r
+  for I:=0 to DEFVERT-1 do begin\r
+    mxBezier( Qix, I, Idx, 12 );\r
+  end;\r
+end;\r
+\r
+procedure Update( var Qix: TQix; Idx: integer );\r
+var\r
+  I: integer;\r
+begin\r
+  for I:=0 to DEFVERT-1 do with Qix do begin\r
+    Inc( Vert[I,Idx].X, Delta[I].X );\r
+    if( Vert[I,Idx].X < 0 ) then begin\r
+      Vert[I,Idx].X := 0;\r
+      Delta[I].X := Random( 5 )+1;\r
+    end;\r
+    if( Vert[I,Idx].X > MaxX ) then begin\r
+      Vert[I,Idx].X := MaxX;\r
+      Delta[I].X := -Random( 5 )-1;\r
+    end;\r
+    Inc( Vert[I,Idx].Y, Delta[I].Y );\r
+    if( Vert[I,Idx].Y < 0 ) then begin\r
+      Vert[I,Idx].Y := 0;\r
+      Delta[I].Y := Random( 5 )+1;\r
+    end;\r
+    if( Vert[I,Idx].Y > MaxY ) then begin\r
+      Vert[I,Idx].Y := MaxY;\r
+      Delta[I].Y := -Random( 5 )-1;\r
+    end;\r
+  end;\r
+end;\r
+\r
+procedure Copy( var Qix: TQix; Dest, Src: integer );\r
+var\r
+  I: integer;\r
+begin\r
+  for I:=0 to DEFVERT-1 do with Qix do begin\r
+    Vert[I,Dest].X := Vert[I,Src].X;\r
+    Vert[I,Dest].Y := Vert[I,Src].Y;\r
+  end;\r
+end;\r
+\r
+procedure AnimateQix;\r
+var\r
+  Q, Idx, I, J, P, Count: integer;\r
+begin\r
+  Count := 0;\r
+  P := DEFREPL-1;\r
+  I := 0;\r
+  J := 1;\r
+  repeat\r
+    mxSetClipRegion( 0, Page, MaxX+1, MaxY+1 );\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, MaxX+1, MaxY+1, 0, OP_SET );\r
+    for Q:=0 to DEFQIXS-1 do begin\r
+      Copy( Qix[Q], I, P );\r
+      Update( Qix[Q], I );\r
+      for Idx:=0 to DEFREPL-1 do begin\r
+        Plot( Qix[Q], Idx );\r
+      end;\r
+    end;\r
+    I := (I+1) mod DEFREPL;\r
+    J := (J+1) mod DEFREPL;\r
+    P := (P+1) mod DEFREPL;\r
+    Inc( Count );\r
+    mxStartLine( Page );\r
+    if( Count >= FADESPEED ) then begin\r
+      for Q:=0 to DEFQIXS-1 do begin\r
+        Inc( Qix[Q].Color );\r
+        if( Qix[Q].Color > 156 ) then\r
+          Qix[Q].Color := 1;\r
+      end;\r
+      Count := 0;\r
+    end;\r
+    Page := 240-Page;\r
+  until( KeyPressed );\r
+end;\r
+\r
+var\r
+  I: integer;\r
+begin\r
+  Randomize;\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  mxGetScreenSize( MaxX, MaxY );\r
+  for I:=0 to DEFQIXS-1 do\r
+    Init( Qix[I], (I*(155 div DEFQIXS)) mod 155 + 1 );\r
+  InitPalette;\r
+  mxSetPalette( @Pal, 0, 157 );\r
+  Page := 240;\r
+  Dec( MaxX );\r
+  Dec( MaxY );\r
+  AnimateQix;\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw_/modex/README.TXT b/16/xw_/modex/README.TXT
new file mode 100755 (executable)
index 0000000..306e8b9
--- /dev/null
@@ -0,0 +1,8 @@
+ModeX - A graphical library for DOS programs\r
+Copyright (c) 1993-1994 Alessandro Scotti\r
+http://www.ascotti.org/\r
+\r
+Please look at the above site in the "Art of..." and\r
+then in the "Old programs" section for more information.\r
+\r
+\r
diff --git a/16/xw_/modex/SINCOS.INC b/16/xw_/modex/SINCOS.INC
new file mode 100755 (executable)
index 0000000..6986eee
--- /dev/null
@@ -0,0 +1,518 @@
+;\r
+; SINCOS.INC - Sin/cos tables for THREED.ASM\r
+;\r
+\r
+tblSin  LABEL DWORD\r
+  DD    0\r
+  DD    411733\r
+  DD    823219\r
+  DD    1234209\r
+  DD    1644455\r
+  DD    2053710\r
+  DD    2461729\r
+  DD    2868265\r
+  DD    3273072\r
+  DD    3675909\r
+  DD    4076531\r
+  DD    4474698\r
+  DD    4870169\r
+  DD    5262706\r
+  DD    5652074\r
+  DD    6038037\r
+  DD    6420363\r
+  DD    6798821\r
+  DD    7173184\r
+  DD    7543226\r
+  DD    7908725\r
+  DD    8269459\r
+  DD    8625213\r
+  DD    8975771\r
+  DD    9320922\r
+  DD    9660458\r
+  DD    9994176\r
+  DD    10321873\r
+  DD    10643353\r
+  DD    10958422\r
+  DD    11266890\r
+  DD    11568571\r
+  DD    11863283\r
+  DD    12150850\r
+  DD    12431097\r
+  DD    12703856\r
+  DD    12968963\r
+  DD    13226258\r
+  DD    13475586\r
+  DD    13716797\r
+  DD    13949745\r
+  DD    14174291\r
+  DD    14390298\r
+  DD    14597637\r
+  DD    14796184\r
+  DD    14985817\r
+  DD    15166424\r
+  DD    15337895\r
+  DD    15500126\r
+  DD    15653022\r
+  DD    15796488\r
+  DD    15930439\r
+  DD    16054795\r
+  DD    16169479\r
+  DD    16274424\r
+  DD    16369565\r
+  DD    16454846\r
+  DD    16530216\r
+  DD    16595628\r
+  DD    16651044\r
+  DD    16696429\r
+  DD    16731757\r
+  DD    16757007\r
+  DD    16772163\r
+  DD    16777216\r
+  DD    16772163\r
+  DD    16757007\r
+  DD    16731757\r
+  DD    16696429\r
+  DD    16651044\r
+  DD    16595628\r
+  DD    16530216\r
+  DD    16454846\r
+  DD    16369565\r
+  DD    16274424\r
+  DD    16169479\r
+  DD    16054795\r
+  DD    15930439\r
+  DD    15796488\r
+  DD    15653022\r
+  DD    15500126\r
+  DD    15337895\r
+  DD    15166424\r
+  DD    14985817\r
+  DD    14796184\r
+  DD    14597637\r
+  DD    14390298\r
+  DD    14174291\r
+  DD    13949745\r
+  DD    13716797\r
+  DD    13475586\r
+  DD    13226258\r
+  DD    12968963\r
+  DD    12703856\r
+  DD    12431097\r
+  DD    12150850\r
+  DD    11863283\r
+  DD    11568571\r
+  DD    11266890\r
+  DD    10958422\r
+  DD    10643353\r
+  DD    10321873\r
+  DD    9994176\r
+  DD    9660458\r
+  DD    9320922\r
+  DD    8975771\r
+  DD    8625213\r
+  DD    8269459\r
+  DD    7908725\r
+  DD    7543226\r
+  DD    7173184\r
+  DD    6798821\r
+  DD    6420363\r
+  DD    6038037\r
+  DD    5652074\r
+  DD    5262706\r
+  DD    4870169\r
+  DD    4474698\r
+  DD    4076531\r
+  DD    3675909\r
+  DD    3273072\r
+  DD    2868265\r
+  DD    2461729\r
+  DD    2053710\r
+  DD    1644455\r
+  DD    1234209\r
+  DD    823219\r
+  DD    411733\r
+  DD    0\r
+  DD    -411733\r
+  DD    -823219\r
+  DD    -1234209\r
+  DD    -1644455\r
+  DD    -2053710\r
+  DD    -2461729\r
+  DD    -2868265\r
+  DD    -3273072\r
+  DD    -3675909\r
+  DD    -4076531\r
+  DD    -4474698\r
+  DD    -4870169\r
+  DD    -5262706\r
+  DD    -5652074\r
+  DD    -6038037\r
+  DD    -6420363\r
+  DD    -6798821\r
+  DD    -7173184\r
+  DD    -7543226\r
+  DD    -7908725\r
+  DD    -8269459\r
+  DD    -8625213\r
+  DD    -8975771\r
+  DD    -9320922\r
+  DD    -9660458\r
+  DD    -9994176\r
+  DD    -10321873\r
+  DD    -10643353\r
+  DD    -10958422\r
+  DD    -11266890\r
+  DD    -11568571\r
+  DD    -11863283\r
+  DD    -12150850\r
+  DD    -12431097\r
+  DD    -12703856\r
+  DD    -12968963\r
+  DD    -13226258\r
+  DD    -13475586\r
+  DD    -13716797\r
+  DD    -13949745\r
+  DD    -14174291\r
+  DD    -14390298\r
+  DD    -14597637\r
+  DD    -14796184\r
+  DD    -14985817\r
+  DD    -15166424\r
+  DD    -15337895\r
+  DD    -15500126\r
+  DD    -15653022\r
+  DD    -15796488\r
+  DD    -15930439\r
+  DD    -16054795\r
+  DD    -16169479\r
+  DD    -16274424\r
+  DD    -16369565\r
+  DD    -16454846\r
+  DD    -16530216\r
+  DD    -16595628\r
+  DD    -16651044\r
+  DD    -16696429\r
+  DD    -16731757\r
+  DD    -16757007\r
+  DD    -16772163\r
+  DD    -16777216\r
+  DD    -16772163\r
+  DD    -16757007\r
+  DD    -16731757\r
+  DD    -16696429\r
+  DD    -16651044\r
+  DD    -16595628\r
+  DD    -16530216\r
+  DD    -16454846\r
+  DD    -16369565\r
+  DD    -16274424\r
+  DD    -16169479\r
+  DD    -16054795\r
+  DD    -15930439\r
+  DD    -15796488\r
+  DD    -15653022\r
+  DD    -15500126\r
+  DD    -15337895\r
+  DD    -15166424\r
+  DD    -14985817\r
+  DD    -14796184\r
+  DD    -14597637\r
+  DD    -14390298\r
+  DD    -14174291\r
+  DD    -13949745\r
+  DD    -13716797\r
+  DD    -13475586\r
+  DD    -13226258\r
+  DD    -12968963\r
+  DD    -12703856\r
+  DD    -12431097\r
+  DD    -12150850\r
+  DD    -11863283\r
+  DD    -11568571\r
+  DD    -11266890\r
+  DD    -10958422\r
+  DD    -10643353\r
+  DD    -10321873\r
+  DD    -9994176\r
+  DD    -9660458\r
+  DD    -9320922\r
+  DD    -8975771\r
+  DD    -8625213\r
+  DD    -8269459\r
+  DD    -7908725\r
+  DD    -7543226\r
+  DD    -7173184\r
+  DD    -6798821\r
+  DD    -6420363\r
+  DD    -6038037\r
+  DD    -5652074\r
+  DD    -5262706\r
+  DD    -4870169\r
+  DD    -4474698\r
+  DD    -4076531\r
+  DD    -3675909\r
+  DD    -3273072\r
+  DD    -2868265\r
+  DD    -2461729\r
+  DD    -2053710\r
+  DD    -1644455\r
+  DD    -1234209\r
+  DD    -823219\r
+  DD    -411733\r
+tblCos  LABEL DWORD\r
+  DD    16777216\r
+  DD    16772163\r
+  DD    16757007\r
+  DD    16731757\r
+  DD    16696429\r
+  DD    16651044\r
+  DD    16595628\r
+  DD    16530216\r
+  DD    16454846\r
+  DD    16369565\r
+  DD    16274424\r
+  DD    16169479\r
+  DD    16054795\r
+  DD    15930439\r
+  DD    15796488\r
+  DD    15653022\r
+  DD    15500126\r
+  DD    15337895\r
+  DD    15166424\r
+  DD    14985817\r
+  DD    14796184\r
+  DD    14597637\r
+  DD    14390298\r
+  DD    14174291\r
+  DD    13949745\r
+  DD    13716797\r
+  DD    13475586\r
+  DD    13226258\r
+  DD    12968963\r
+  DD    12703856\r
+  DD    12431097\r
+  DD    12150850\r
+  DD    11863283\r
+  DD    11568571\r
+  DD    11266890\r
+  DD    10958422\r
+  DD    10643353\r
+  DD    10321873\r
+  DD    9994176\r
+  DD    9660458\r
+  DD    9320922\r
+  DD    8975771\r
+  DD    8625213\r
+  DD    8269459\r
+  DD    7908725\r
+  DD    7543226\r
+  DD    7173184\r
+  DD    6798821\r
+  DD    6420363\r
+  DD    6038037\r
+  DD    5652074\r
+  DD    5262706\r
+  DD    4870169\r
+  DD    4474698\r
+  DD    4076531\r
+  DD    3675909\r
+  DD    3273072\r
+  DD    2868265\r
+  DD    2461729\r
+  DD    2053710\r
+  DD    1644455\r
+  DD    1234209\r
+  DD    823219\r
+  DD    411733\r
+  DD    0\r
+  DD    -411733\r
+  DD    -823219\r
+  DD    -1234209\r
+  DD    -1644455\r
+  DD    -2053710\r
+  DD    -2461729\r
+  DD    -2868265\r
+  DD    -3273072\r
+  DD    -3675909\r
+  DD    -4076531\r
+  DD    -4474698\r
+  DD    -4870169\r
+  DD    -5262706\r
+  DD    -5652074\r
+  DD    -6038037\r
+  DD    -6420363\r
+  DD    -6798821\r
+  DD    -7173184\r
+  DD    -7543226\r
+  DD    -7908725\r
+  DD    -8269459\r
+  DD    -8625213\r
+  DD    -8975771\r
+  DD    -9320922\r
+  DD    -9660458\r
+  DD    -9994176\r
+  DD    -10321873\r
+  DD    -10643353\r
+  DD    -10958422\r
+  DD    -11266890\r
+  DD    -11568571\r
+  DD    -11863283\r
+  DD    -12150850\r
+  DD    -12431097\r
+  DD    -12703856\r
+  DD    -12968963\r
+  DD    -13226258\r
+  DD    -13475586\r
+  DD    -13716797\r
+  DD    -13949745\r
+  DD    -14174291\r
+  DD    -14390298\r
+  DD    -14597637\r
+  DD    -14796184\r
+  DD    -14985817\r
+  DD    -15166424\r
+  DD    -15337895\r
+  DD    -15500126\r
+  DD    -15653022\r
+  DD    -15796488\r
+  DD    -15930439\r
+  DD    -16054795\r
+  DD    -16169479\r
+  DD    -16274424\r
+  DD    -16369565\r
+  DD    -16454846\r
+  DD    -16530216\r
+  DD    -16595628\r
+  DD    -16651044\r
+  DD    -16696429\r
+  DD    -16731757\r
+  DD    -16757007\r
+  DD    -16772163\r
+  DD    -16777216\r
+  DD    -16772163\r
+  DD    -16757007\r
+  DD    -16731757\r
+  DD    -16696429\r
+  DD    -16651044\r
+  DD    -16595628\r
+  DD    -16530216\r
+  DD    -16454846\r
+  DD    -16369565\r
+  DD    -16274424\r
+  DD    -16169479\r
+  DD    -16054795\r
+  DD    -15930439\r
+  DD    -15796488\r
+  DD    -15653022\r
+  DD    -15500126\r
+  DD    -15337895\r
+  DD    -15166424\r
+  DD    -14985817\r
+  DD    -14796184\r
+  DD    -14597637\r
+  DD    -14390298\r
+  DD    -14174291\r
+  DD    -13949745\r
+  DD    -13716797\r
+  DD    -13475586\r
+  DD    -13226258\r
+  DD    -12968963\r
+  DD    -12703856\r
+  DD    -12431097\r
+  DD    -12150850\r
+  DD    -11863283\r
+  DD    -11568571\r
+  DD    -11266890\r
+  DD    -10958422\r
+  DD    -10643353\r
+  DD    -10321873\r
+  DD    -9994176\r
+  DD    -9660458\r
+  DD    -9320922\r
+  DD    -8975771\r
+  DD    -8625213\r
+  DD    -8269459\r
+  DD    -7908725\r
+  DD    -7543226\r
+  DD    -7173184\r
+  DD    -6798821\r
+  DD    -6420363\r
+  DD    -6038037\r
+  DD    -5652074\r
+  DD    -5262706\r
+  DD    -4870169\r
+  DD    -4474698\r
+  DD    -4076531\r
+  DD    -3675909\r
+  DD    -3273072\r
+  DD    -2868265\r
+  DD    -2461729\r
+  DD    -2053710\r
+  DD    -1644455\r
+  DD    -1234209\r
+  DD    -823219\r
+  DD    -411733\r
+  DD    0\r
+  DD    411733\r
+  DD    823219\r
+  DD    1234209\r
+  DD    1644455\r
+  DD    2053710\r
+  DD    2461729\r
+  DD    2868265\r
+  DD    3273072\r
+  DD    3675909\r
+  DD    4076531\r
+  DD    4474698\r
+  DD    4870169\r
+  DD    5262706\r
+  DD    5652074\r
+  DD    6038037\r
+  DD    6420363\r
+  DD    6798821\r
+  DD    7173184\r
+  DD    7543226\r
+  DD    7908725\r
+  DD    8269459\r
+  DD    8625213\r
+  DD    8975771\r
+  DD    9320922\r
+  DD    9660458\r
+  DD    9994176\r
+  DD    10321873\r
+  DD    10643353\r
+  DD    10958422\r
+  DD    11266890\r
+  DD    11568571\r
+  DD    11863283\r
+  DD    12150850\r
+  DD    12431097\r
+  DD    12703856\r
+  DD    12968963\r
+  DD    13226258\r
+  DD    13475586\r
+  DD    13716797\r
+  DD    13949745\r
+  DD    14174291\r
+  DD    14390298\r
+  DD    14597637\r
+  DD    14796184\r
+  DD    14985817\r
+  DD    15166424\r
+  DD    15337895\r
+  DD    15500126\r
+  DD    15653022\r
+  DD    15796488\r
+  DD    15930439\r
+  DD    16054795\r
+  DD    16169479\r
+  DD    16274424\r
+  DD    16369565\r
+  DD    16454846\r
+  DD    16530216\r
+  DD    16595628\r
+  DD    16651044\r
+  DD    16696429\r
+  DD    16731757\r
+  DD    16757007\r
+  DD    16772163\r
diff --git a/16/xw_/modex/THREED.ASM b/16/xw_/modex/THREED.ASM
new file mode 100755 (executable)
index 0000000..5ecd3ba
--- /dev/null
@@ -0,0 +1,872 @@
+COMMENT /\r
+        Fixed-point math functions and 3D transforms\r
+        Copyright (c) 1993,94 by Alessandro Scotti\r
+/\r
+WARN    PRO\r
+P386\r
+JUMPS\r
+LOCALS\r
+\r
+INCLUDE MATH.INC\r
+\r
+PUBLIC  tdFixedMul\r
+PUBLIC  tdGetNormal\r
+PUBLIC  tdRotate\r
+PUBLIC  tdGetSurfaceLight\r
+PUBLIC  tdSetLight\r
+PUBLIC  tdSetRotation\r
+PUBLIC  tdSetTranslation\r
+PUBLIC  tdTransform\r
+PUBLIC  tdTransformToImage\r
+PUBLIC  tdTransformLight\r
+PUBLIC  tdBackPlaneCull\r
+PUBLIC  tdSetPerspective\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Data segment\r
+;\r
+MATH_DATA       SEGMENT USE16 PARA PUBLIC 'DATA'\r
+                ASSUME ds:MATH_DATA\r
+\r
+INCLUDE         SINCOS.INC              ; Fixed 8:24 sin/cos table\r
+\r
+XRotation       TPOINT  <>              ; 3x3 rotation matrix\r
+YRotation       TPOINT  <>\r
+ZRotation       TPOINT  <>\r
+\r
+Translation     TPOINT  <>              ; Translation vector\r
+\r
+Light           TPOINT  <>              ; Light vector\r
+AmbientLight    DW      00              ; Ambient light\r
+\r
+XScale                  DD      10000h  ; Scaling factor for X coordinate\r
+YScale                  DD      10000h  ; Scaling factor for Y coordinate\r
+PerspectiveDistance     DD      20000000h\r
+\r
+MATH_DATA       ENDS\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Code segment\r
+;\r
+MATH_TEXT       SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MATH_TEXT, es:NOTHING, fs:NOTHING\r
+\r
+tdSetPerspective        PROC PASCAL FAR\r
+        ARG     Perspective:DWORD,      \\r
+                ScaleX:DWORD,           \\r
+                ScaleY:DWORD\r
+        USES    ds\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        mov     eax, [Perspective]\r
+        mov     [PerspectiveDistance], eax\r
+        mov     eax, [ScaleX]\r
+        mov     [XScale], eax\r
+        mov     eax, [ScaleY]\r
+        mov     [YScale], eax\r
+\r
+        ret\r
+tdSetPerspective        ENDP\r
+\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the rotation matrix.\r
+;\r
+; Input:\r
+;       RX      = X-axis rotation angle\r
+;       RY      = X-axis rotation angle\r
+;       RZ      = X-axis rotation angle\r
+; Output:\r
+;       none\r
+;\r
+tdSetRotation   PROC PASCAL FAR\r
+        ARG     RX:WORD,        \\r
+                RY:WORD,        \\r
+                RZ:WORD\r
+        USES    ds, si, di\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        mov     bx, [RZ]\r
+        mov     si, [RY]\r
+        mov     di, [RX]\r
+        shl     bx, 2\r
+        shl     si, 2\r
+        shl     di, 2\r
+\r
+        push    ebp                     ; We use EBP as a scratch register\r
+\r
+; Set X rotation\r
+        mov     eax, tblCos[bx]\r
+        imul    tblCos[si]\r
+        mov     [XRotation.X], edx\r
+\r
+        mov     eax, tblSin[bx]\r
+        imul    tblCos[si]\r
+        mov     [XRotation.Y], edx\r
+\r
+        mov     eax, tblSin[si]\r
+        sar     eax, 8                  ; Convert fixed 8:24 to fixed 16:16\r
+        mov     [XRotation.Z], eax\r
+\r
+; Set Y rotation\r
+        mov     eax, tblCos[bx]\r
+        imul    tblSin[si]              ; EDX:EAX = fixed 16:48\r
+        shrd    eax, edx, 24            ; EAX = fixed 8:24\r
+        imul    tblSin[di]              ; EDX:EAX = fixed 16:48\r
+        mov     ebp, eax\r
+        mov     ecx, edx\r
+        mov     eax, tblSin[bx]\r
+        imul    tblCos[di]\r
+        add     eax, ebp\r
+        adc     edx, ecx                ; EDX:EAX = fixed 16:48\r
+        neg     edx\r
+        mov     [YRotation.X], edx\r
+\r
+        mov     eax, tblSin[bx]\r
+        imul    tblSin[si]\r
+        shrd    eax, edx, 24\r
+        imul    tblSin[di]\r
+        mov     ebp, eax\r
+        mov     ecx, edx\r
+        mov     eax, tblCos[bx]\r
+        imul    tblCos[di]\r
+        sub     eax, ebp\r
+        sbb     edx, ecx\r
+        mov     [YRotation.Y], edx\r
+\r
+        mov     eax, tblCos[si]\r
+        imul    tblSin[di]\r
+        mov     [YRotation.Z], edx\r
+\r
+; Set Z rotation\r
+        mov     eax, tblCos[bx]\r
+        imul    tblSin[si]\r
+        shrd    eax, edx, 24\r
+        imul    tblCos[di]\r
+        mov     ebp, eax\r
+        mov     ecx, edx\r
+        mov     eax, tblSin[bx]\r
+        imul    tblSin[di]\r
+        sub     eax, ebp\r
+        sbb     edx, ecx\r
+        mov     [ZRotation.X], edx\r
+\r
+        mov     eax, tblSin[bx]\r
+        imul    tblSin[si]\r
+        shrd    eax, edx, 24\r
+        imul    tblCos[di]\r
+        mov     ebp, eax\r
+        mov     ecx, edx\r
+        mov     eax, tblCos[bx]\r
+        imul    tblSin[di]\r
+        add     eax, ebp\r
+        add     edx, ecx\r
+        neg     edx\r
+        mov     [ZRotation.Y], edx\r
+\r
+        mov     eax, tblCos[si]\r
+        imul    tblCos[di]\r
+        mov     [ZRotation.Z], edx\r
+\r
+        pop     ebp                     ; Restore EBP\r
+\r
+        ret\r
+tdSetRotation   ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the translation vector.\r
+;\r
+; Input:\r
+;       TV      = pointer to translation vector\r
+; Output:\r
+;       none\r
+;\r
+tdSetTranslation        PROC PASCAL FAR\r
+        ARG     TV:DWORD\r
+        USES    ds, es, di\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        les     di, [TV]\r
+        mov     eax, es:[di].X\r
+        mov     [Translation.X], eax\r
+        mov     eax, es:[di].Y\r
+        mov     [Translation.Y], eax\r
+        mov     eax, es:[di].Z\r
+        mov     [Translation.Z], eax\r
+\r
+        ret\r
+tdSetTranslation        ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Transforms an array of TPOINT.\r
+;\r
+; Input:\r
+;       Source  = pointer to source array of TPOINT\r
+;       Dest    = pointer to destination array of TPOINT\r
+;       Count   = number of entries to transform\r
+; Output:\r
+;       none\r
+;\r
+tdTransform     PROC PASCAL FAR\r
+        ARG     Source:DWORD,   \\r
+                Dest:DWORD,     \\r
+                Count:WORD\r
+        LOCAL   Adjust:DWORD\r
+        USES    ds, si, es, di, fs\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        lfs     si, [Source]\r
+        les     di, [Dest]\r
+\r
+        ALIGN   DWORD\r
+@@Loop:\r
+; Transform Z coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [ZRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [ZRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [ZRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        mov     ebx, eax\r
+        shrd    eax, edx, 16\r
+        add     eax, [Translation.Z]    ; EAX = new Z coord (fixed 16:16)\r
+        mov     es:[di].Z, eax\r
+; Get perspective factor\r
+        mov     ebx, [PerspectiveDistance]\r
+        sub     eax, ebx\r
+        neg     eax                     ; EAX = PD - Z\r
+        xor     edx, edx\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    ebx                     ; EAX = fixed 16:16 result\r
+        mov     [Adjust], eax\r
+\r
+; Transform X coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [XRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [XRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [XRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        add     eax, [Translation.X]\r
+        imul    [Adjust]\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].X, eax\r
+\r
+; Transform Y coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [YRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [YRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [YRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        add     eax, [Translation.Y]\r
+        imul    [Adjust]\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].Y, eax\r
+\r
+        add     si, SIZE TPOINT\r
+        add     di, SIZE TPOINT\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        ret\r
+tdTransform     ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Transforms an array of TPOINT into an array of TIMAGEPOINT.\r
+;\r
+; Input:\r
+;       Source  = pointer to source array of TPOINT\r
+;       Dest    = pointer to destination array of TIMAGEPOINT\r
+;       Count   = number of entries to transform\r
+;       DeltaX  = translation distance for the X coordinate\r
+;       DeltaY  = translation distance for the Y coordinate\r
+; Output:\r
+;       the maximum Z value\r
+;\r
+tdTransformToImage      PROC PASCAL FAR\r
+        ARG     Source:DWORD,   \\r
+                Dest:DWORD,     \\r
+                Count:WORD,     \\r
+                DeltaX:WORD,    \\r
+                DeltaY:WORD\r
+        LOCAL   Adjust:DWORD,   \\r
+                Max:DWORD\r
+        USES    ds, si, es, di, fs\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        lfs     si, [Source]\r
+        les     di, [Dest]\r
+        mov     [Max], 80000000h\r
+\r
+@@Loop:\r
+; Check max Z\r
+        mov     eax, fs:[si].Z\r
+        cmp     eax, [Max]\r
+        jle     @@1\r
+        mov     [Max], eax\r
+@@1:\r
+\r
+; Transform X coordinate\r
+        mov     ax, WORD PTR fs:[si].X[2]\r
+        add     ax, [DeltaX]\r
+        mov     es:[di].IX, ax\r
+\r
+; Transform Y coordinate\r
+        mov     ax, WORD PTR fs:[si].Y[2]\r
+        add     ax, [DeltaY]\r
+        mov     es:[di].IY, ax\r
+\r
+        add     si, SIZE TPOINT\r
+        add     di, SIZE TIMAGEPOINT\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        mov     eax, [Max]\r
+        shld    edx, eax, 16\r
+        ret\r
+tdTransformToImage      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the light source.\r
+;\r
+; Input:\r
+;       Light   = pointer to light vector\r
+; Output:\r
+;       none\r
+;\r
+tdSetLight      PROC PASCAL FAR\r
+        ARG     L:DWORD\r
+        USES    ds, es, di\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        les     di, [L]\r
+        mov     eax, es:[di].X\r
+        mov     [Light.X], eax\r
+        mov     eax, es:[di].Y\r
+        mov     [Light.Y], eax\r
+        mov     eax, es:[di].Z\r
+        mov     [Light.Z], eax\r
+\r
+        ret\r
+tdSetLight      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Computes light intensity for an array of surfaces.\r
+;\r
+; Input:\r
+;       Normals = pointer to an array of surface normals\r
+;       Lights  = pointer to an array of integer to be filled with\r
+;                 light intensity\r
+;       Count   = number of elements to transform\r
+; Output:\r
+;       none\r
+;\r
+tdTransformLight        PROC PASCAL FAR\r
+        ARG     Normals:DWORD,  \\r
+                Lights:DWORD,   \\r
+                Count:WORD\r
+        USES    ds, si, es, di, fs\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     fs, ax\r
+        ASSUME  fs:MATH_DATA\r
+\r
+        lds     si, [Normals]\r
+        les     di, [Lights]\r
+        ASSUME  ds:NOTHING\r
+\r
+; Intensity is given by the dot product between the Light vector and\r
+; the surface normal\r
+@@Loop:\r
+        mov     eax, ds:[si].Z\r
+        imul    [Light.Z]\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, ds:[si].Y\r
+        imul    [Light.Y]\r
+        add     ebx, eax\r
+        adc     ecx, edx\r
+        mov     eax, ds:[si].X\r
+        imul    [Light.X]\r
+        add     eax, ebx\r
+        adc     edx, ecx                ; EDX:EAX = fixed 32:32 intensity\r
+        add     dx, [AmbientLight]\r
+        test    dx, dx\r
+        jg      @@1\r
+        xor     dx, dx                  ; Return 0 for no light\r
+@@1:\r
+        mov     es:[di], dx\r
+        inc     di\r
+        inc     di\r
+        add     si, SIZE TPOINT\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        ASSUME  fs:NOTHING\r
+        ret\r
+tdTransformLight        ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the light value given the normal to a surface.\r
+;\r
+; Input:\r
+;       Normal  = pointer to TPOINT surface normal vector\r
+; Output:\r
+;       AX      = light intensity (>=0)\r
+; Notes:\r
+;       the normal is rotated according to the current setting.\r
+;\r
+tdGetSurfaceLight       PROC PASCAL FAR\r
+        ARG     Normal:DWORD\r
+        USES    ds, esi, es, di\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        les     di, [Normal]\r
+\r
+; Transform Z coordinate\r
+        mov     eax, es:[di].X\r
+        imul    [ZRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, es:[di].Y\r
+        imul    [ZRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, es:[di].Z\r
+        imul    [ZRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        imul    [Light.Z]\r
+        shrd    eax, edx, 16\r
+        mov     esi, eax\r
+\r
+; Transform X coordinate\r
+        mov     eax, es:[di].X\r
+        imul    [XRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, es:[di].Y\r
+        imul    [XRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, es:[di].Z\r
+        imul    [XRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        imul    [Light.X]\r
+        shrd    eax, edx, 16\r
+        add     esi, eax\r
+\r
+; Transform Y coordinate\r
+        mov     eax, es:[di].X\r
+        imul    [YRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, es:[di].Y\r
+        imul    [YRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, es:[di].Z\r
+        imul    [YRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        imul    [Light.X]\r
+        shrd    eax, edx, 16\r
+        add     eax, esi\r
+        shr     eax, 16\r
+\r
+; Add ambient light\r
+        add     ax, [AmbientLight]\r
+        test    ax, ax\r
+        jge     @@Exit\r
+        xor     ax, ax\r
+\r
+@@Exit:\r
+        ret\r
+tdGetSurfaceLight       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Rotates an array of TPOINT.\r
+;\r
+; Input:\r
+;       Source  = pointer to source array of TPOINT\r
+;       Dest    = pointer to destination array of TPOINT\r
+;       Count   = number of entries to transform\r
+; Output:\r
+;       none\r
+;\r
+tdRotate        PROC PASCAL FAR\r
+        ARG     Source:DWORD,   \\r
+                Dest:DWORD,     \\r
+                Count:WORD\r
+        USES    ds, si, es, di, fs\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        lfs     si, [Source]\r
+        les     di, [Dest]\r
+\r
+@@Loop:\r
+; Transform Z coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [ZRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [ZRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [ZRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].Z, eax\r
+\r
+; Transform X coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [XRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [XRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [XRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].X, eax\r
+\r
+; Transform Y coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [YRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [YRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [YRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].Y, eax\r
+\r
+        add     si, SIZE TPOINT\r
+        add     di, SIZE TPOINT\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        ret\r
+tdRotate        ENDP\r
+\r
+tdFixedMul      PROC PASCAL FAR\r
+        ARG     F1:DWORD,       \\r
+                F2:DWORD\r
+\r
+        mov     eax, [F1]\r
+        imul    [F2]\r
+        shr     eax, 16\r
+\r
+        ret\r
+tdFixedMul      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns in EAX the square root of EDX:EAX.\r
+;\r
+subSqrt PROC NEAR\r
+        push    esi\r
+        push    edi\r
+\r
+        add     eax, eax\r
+        adc     edx, 0\r
+        mov     eax, edx                ; Just discard the low bits\r
+\r
+        mov     esi, eax\r
+        xor     edi, edi\r
+        shld    edi, esi, 16\r
+        shl     esi, 16\r
+@@Loop:\r
+        mov     ebx, eax\r
+        mul     eax\r
+        add     eax, esi\r
+        adc     edx, edi\r
+        shrd    eax, edx, 1\r
+        shr     edx, 1\r
+        div     ebx\r
+        cmp     eax, ebx\r
+        jne     @@Loop\r
+\r
+; Adjust EAX\r
+        shl     eax, 8\r
+\r
+        pop     edi\r
+        pop     esi\r
+        ret\r
+subSqrt ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Finds the unitary normal to a given surface.\r
+;\r
+; Input:\r
+;       Dest            = pointer to TPOINT (vector) result\r
+;       P1, P2, P3      = pointer to TPOINT points on surface\r
+; Output:\r
+;       none\r
+; Notes:\r
+;       the normal is given by the cross-product between (P3-P1) and\r
+;       (P2-P1), so its orientation depends on the parameters order.\r
+;\r
+tdGetNormal     PROC PASCAL FAR\r
+        ARG     Dest:DWORD,     \\r
+                P1:DWORD,       \\r
+                P2:DWORD,       \\r
+                P3:DWORD\r
+        LOCAL   V1:TPOINT,      \\r
+                V2:TPOINT,      \\r
+                N:TPOINT\r
+        USES    ds, si, es, di\r
+\r
+; Get vector V1\r
+        lds     si, [P1]\r
+        les     di, [P3]\r
+        mov     eax, es:[di].X\r
+        sub     eax, ds:[si].X\r
+        mov     [V1.X], eax\r
+        mov     eax, es:[di].Y\r
+        sub     eax, ds:[si].Y\r
+        mov     [V1.Y], eax\r
+        mov     eax, es:[di].Z\r
+        sub     eax, ds:[si].Z\r
+        mov     [V1.Z], eax\r
+\r
+; Get vector V2\r
+        les     di, [P2]\r
+        mov     eax, es:[di].X\r
+        sub     eax, ds:[si].X\r
+        mov     [V2.X], eax\r
+        mov     eax, es:[di].Y\r
+        sub     eax, ds:[si].Y\r
+        mov     [V2.Y], eax\r
+        mov     eax, es:[di].Z\r
+        sub     eax, ds:[si].Z\r
+        mov     [V2.Z], eax\r
+\r
+; Get normal vector (V1 x V2)\r
+        mov     eax, [V1.Z]\r
+        imul    [V2.Y]\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, [V1.Y]\r
+        imul    [V2.Z]\r
+        sub     eax, ebx\r
+        sbb     edx, ecx\r
+        shrd    eax, edx, 16\r
+        mov     [N.X], eax\r
+\r
+        mov     eax, [V1.X]\r
+        imul    [V2.Z]\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, [V1.Z]\r
+        imul    [V2.X]\r
+        sub     eax, ebx\r
+        sbb     edx, ecx\r
+        shrd    eax, edx, 16\r
+        mov     [N.Y], eax\r
+\r
+        mov     eax, [V1.Y]\r
+        imul    [V2.X]\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, [V1.X]\r
+        imul    [V2.Y]\r
+        sub     eax, ebx\r
+        sbb     edx, ecx\r
+        shrd    eax, edx, 16\r
+        mov     [N.Z], eax\r
+\r
+; Get normal length\r
+        mov     eax, [N.X]\r
+        imul    eax\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, [N.Y]\r
+        imul    eax\r
+        add     ebx, eax\r
+        adc     ecx, edx\r
+        mov     eax, [N.Z]\r
+        imul    eax\r
+        add     eax, ebx\r
+        adc     edx, ecx                ; EDX:EAX = N.X*N.X + N.Y*N.Y + N.Z*N.Z\r
+        call    subSqrt                 ; EAX = normal length\r
+        mov     ebx, eax\r
+\r
+; Adjust vector and save it\r
+        les     di, [Dest]\r
+        mov     eax, [N.X]\r
+        cdq\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    ebx\r
+        mov     es:[di].X, eax\r
+        mov     eax, [N.Y]\r
+        cdq\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    ebx\r
+        mov     es:[di].Y, eax\r
+        mov     eax, [N.Z]\r
+        cdq\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    ebx\r
+        mov     es:[di].Z, eax\r
+\r
+        ret\r
+tdGetNormal     ENDP\r
+\r
+TPOLY   STRUC\r
+        Vtx     DW      4 DUP(?)\r
+TPOLY   ENDS\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Performs surface removal on an array of polygons.\r
+;\r
+; Input:\r
+;       Poly    = pointer to an array of TPOLY\r
+;       Vertex  = pointer to an array of TPOINT\r
+;       Dest    = pointer to an array of integer\r
+;       Count   = number of polygons to check\r
+;       Step    = size of TPOLY structure\r
+; Output:\r
+;       if the n-th polygon is invisible the n-th entry of the\r
+;       Dest array is set to -1, other entries are not modified\r
+;       (so it's possible to use the Light array for Dest, because\r
+;       the light intensity is always >= 0)\r
+;\r
+tdBackPlaneCull PROC PASCAL FAR\r
+        ARG     Step:WORD,      \\r
+                Poly:DWORD,     \\r
+                Vertex:DWORD,   \\r
+                Dest:DWORD,     \\r
+                Count:WORD\r
+        USES    ds, si, es, di, fs\r
+        ASSUME  ds:NOTHING\r
+\r
+        mov     ds, WORD PTR Vertex[2]\r
+        les     di, [Poly]\r
+        mov     fs, WORD PTR Dest[2]\r
+\r
+@@Loop:\r
+        mov     ax, es:[di].Vtx[2]      ; Index of 2nd vertex\r
+        shl     ax, 2\r
+        mov     bx, ax\r
+        shl     ax, 1\r
+        add     bx, ax                  ; BX = index*SIZE TPOINT\r
+        add     bx, WORD PTR [Vertex]   ; BX = offset of 2nd vertex\r
+        mov     ax, es:[di].Vtx[4]      ; Index of 3rd vertex\r
+        shl     ax, 2\r
+        mov     si, ax\r
+        shl     ax, 1\r
+        add     si, ax\r
+        add     si, WORD PTR [Vertex]   ; SI = offset of 3rd vertex\r
+        mov     ecx, ds:[si].X\r
+        sub     ecx, ds:[bx].X          ; ECX = V3.X-V2.X\r
+        mov     edx, ds:[si].Y\r
+        sub     edx, ds:[bx].Y          ; EDX = V3.Y-V2.Y\r
+        mov     ax, es:[di].Vtx[0]      ; Index of 1st vertex\r
+        shl     ax, 2\r
+        mov     si, ax\r
+        shl     ax, 1\r
+        add     si, ax\r
+        add     si, WORD PTR [Vertex]   ; SI = offset of 1st vertex\r
+        mov     eax, ds:[si].X\r
+        sub     eax, ds:[bx].X          ; EAX = V1.X-V2.X\r
+        mov     esi, ds:[si].Y\r
+        sub     esi, ds:[bx].Y          ; ESI = V1.Y-V2.Y\r
+        imul    edx\r
+        mov     ebx, eax\r
+        xchg    ecx, edx                ; ECX:EBX = (V1.X-V2.X)*(V3.Y-V2.Y)\r
+        mov     eax, esi\r
+        imul    edx                     ; EDX:EAX = (V1.Y-V2.Y)*(V3.X-V2.X)\r
+        sub     eax, ebx\r
+        sbb     edx, ecx\r
+        jl      @@Next                  ; Polygon is visible\r
+        mov     bx, WORD PTR [Dest]     ; FS:BX -> current Dest entry\r
+        mov     WORD PTR fs:[bx], -1    ; Remove polygon\r
+@@Next:\r
+        add     WORD PTR [Dest], 2      ; Next entry for dest\r
+        add     di, [Step]              ; Next polygon\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        ret\r
+tdBackPlaneCull ENDP\r
+\r
+MATH_TEXT       ENDS\r
+END\r
diff --git a/16/xw_/modex/THREED.H b/16/xw_/modex/THREED.H
new file mode 100755 (executable)
index 0000000..b993ef8
--- /dev/null
@@ -0,0 +1,32 @@
+typedef struct {\r
+    long    x, y, z;\r
+} TVECTOR;\r
+\r
+#define PVECTOR TVECTOR far *\r
+\r
+#define TPOINT  TVECTOR\r
+#define PPOINT  PVECTOR\r
+\r
+#define VPTR    void far *\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+long far pascal tdFixedMul( long, long );\r
+int  far pascal tdGetSurfaceLight( PPOINT );\r
+long far pascal tdTransformToImage( VPTR, VPTR, short, short, short );\r
+\r
+void far pascal tdBackPlaneCull( VPTR, VPTR, VPTR, short, short );\r
+void far pascal tdGetNormal( VPTR, PPOINT, PPOINT, PPOINT );\r
+void far pascal tdRotate( VPTR, VPTR, short );\r
+void far pascal tdSetLight( PVECTOR );\r
+void far pascal tdSetRotation( short, short, short );\r
+void far pascal tdSetTranslation( PVECTOR );\r
+void far pascal tdSetPerspective( long, long, long );\r
+void far pascal tdTransform( VPTR, VPTR, short );\r
+void far pascal tdTransformLight( VPTR, VPTR, short );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
diff --git a/16/xw_/modex/THREED.PAS b/16/xw_/modex/THREED.PAS
new file mode 100755 (executable)
index 0000000..8b712c9
--- /dev/null
@@ -0,0 +1,40 @@
+unit ThreeD;\r
+interface\r
+\r
+type\r
+  TVector       = record\r
+    X, Y, Z     : longint;\r
+  end;\r
+  TPoint        = TVector;\r
+\r
+function tdFixedMul( F1, F2: longint ): longint;\r
+function tdGetSurfaceLight( var Normal: TPoint ): integer;\r
+function tdTransformToImage( var Source, Dest; Count, DeltaX, DeltaY: integer ): longint;\r
+\r
+procedure tdBackPlaneCull( var Poly, Vertex, Dest; Count, Step: word );\r
+procedure tdGetNormal( var Dest, P1, P2, P3: TVector );\r
+procedure tdRotate( var Source, Dest; Count: word );\r
+procedure tdSetLight( var Light: TVector );\r
+procedure tdSetRotation( RX, RY, RZ: word );\r
+procedure tdSetTranslation( var TV: TVector );\r
+procedure tdSetPerspective( PD, XF, YF: longint );\r
+procedure tdTransform( var Source, Dest; Count: word );\r
+procedure tdTransformLight( var Source, Dest; Count: word );\r
+\r
+implementation\r
+\r
+function tdGetSurfaceLight;                             external;\r
+procedure tdSetRotation( RX, RY, RZ: word );            external;\r
+procedure tdGetNormal;                                  external;\r
+procedure tdSetTranslation( var TV: TVector );          external;\r
+procedure tdTransform( var Source, Dest; Count: word ); external;\r
+procedure tdRotate;                                     external;\r
+function  tdTransformToImage;                           external;\r
+procedure tdSetLight( var Light: TVector );             external;\r
+procedure tdSetPerspective;                             external;\r
+procedure tdTransformLight;                             external;\r
+function tdFixedMul( F1, F2: longint ): longint;        external;\r
+procedure tdBackPlaneCull;                              external;\r
+{$L THREED}\r
+\r
+end.\r
diff --git a/16/xw_/modex/demo01.c b/16/xw_/modex/demo01.c
new file mode 100755 (executable)
index 0000000..98086b6
--- /dev/null
@@ -0,0 +1,133 @@
+/*\r
+               DEMO01 - Sprites, page flipping and palette rotation\r
+               Copyright (c) 1994 Alessandro Scotti\r
+*/\r
+#include ../../x/\r
+\r
+#DEFINE MAX_SPRITE 100\r
+\r
+/* Sprite structure */\r
+typedef struct {\r
+               int X, Y;                                                                                               /* Sprite coordinates */\r
+               int DX,DY;                                                                                              /* Deltas for sprite movement */\r
+               int W, H;                                                                                               /* Sprite width and height */\r
+               unsigned char Image[16,16];     /* Sprite image data */\r
+} TSprite;\r
+\r
+/* RGB color structure */\r
+typedef struct {\r
+               R, G, B: byte;\r
+} TRgb;\r
+var\r
+       S                       : array[ 1..MAX_SPRITE ] of TSprite;     /* An array of sprites */\r
+       Palette: array[ byte ] of TRgb;                                                  /* Palette */\r
+       Page     : word;                                                                                                                                /* Page offset */\r
+       I                       : word;\r
+\r
+/* Initializes a sprite structure */\r
+procedure sxInit( var S: TSprite );\r
+var\r
+       I: word;\r
+begin\r
+       S.X = Random( 320 );    /* Initialize position with random values */\r
+       S.Y = Random( 240 );\r
+       S.DX = Random( 7 )-3; /* Initialize speed with random values */\r
+       S.DY = Random( 7 )-3;\r
+       S.W = 16;                                                /* Size is fixed in this program */\r
+       S.H = 16;\r
+       /* The image is a square with a hole inside */\r
+       FillChar( S.Image, SizeOf(S.Image), Random(15)+1 );\r
+       for I=5 to 12 do FillChar( S.Image[ I, 5 ], 8, 0 );\r
+}\r
+\r
+/* Moves a sprite */\r
+procedure sxMove( var S: TSprite );\r
+begin\r
+       Inc( S.X, S.DX );                /* Get new position */\r
+       Inc( S.Y, S.DY );\r
+       /* Check sprite position, change delta if needed */\r
+       if( S.X > 320 ) then begin\r
+               S.X = 320;\r
+               S.DX = -S.DX;\r
+       }\r
+       if( S.X < -16 ) then begin\r
+               S.X = -16;\r
+               S.DX = -S.DX;\r
+       }\r
+       if( S.Y > 240 ) then begin\r
+               S.Y = 240;\r
+               S.DY = -S.DY;\r
+       }\r
+       if( S.Y < -16 ) then begin\r
+               S.Y = -16;\r
+               S.DY = -S.DY;\r
+       }\r
+       /* Draw the sprite, note the Page offset added to the */\r
+       /* Y coordinate of the image */\r
+       mxPutImage( @S.Image, S.X, Page+S.Y, S.W, S.H, OP_TRANS );\r
+}\r
+\r
+void main()\r
+{\r
+       int i;\r
+       /* Initialize library */\r
+       mxInit();\r
+\r
+       /* Enter graphics mode */\r
+       mxSetMode( MX_320x240 );\r
+\r
+       /* Print initialization message */\r
+       mxSetTextColor( 15, OP_TRANS );\r
+       mxOutStr( 4, 4, 'Initializing...' );\r
+\r
+       /* Initialize sprites */\r
+       for(i=1;i<=MAX_SPRITE;i++)\r
+               sxInit( S[i] );\r
+\r
+       /* Draw background */\r
+       for(i=1;i<=192;i++)\r
+       {\r
+               mxCircle( 160, 480+120, I, I+63 );\r
+               mxCircle( 161, 480+120, I, I+63 );\r
+       }\r
+\r
+       /* Compute and set palette */\r
+       for(i=1;i<= 192;Palette[i+63])\r
+        {\r
+               short R = 0;\r
+               short G = 0;\r
+               short B = 0;\r
+               if( i < 64 )\r
+                       R = i shr 1+31\r
+               else if( i < 128 )\r
+                       G = (i-64) shr 1+31\r
+               else\r
+                       B = (i-128) shr 1+31;\r
+       }\r
+       mxSetPalette( @Palette[64], 64, 192 );\r
+\r
+       /* Main loop */\r
+       short Page = 240;\r
+       while(!kbhit())\r
+       {\r
+               /* Set clip region to current page */\r
+               mxSetClipRegion( 0, Page, 320, 240 );\r
+               mxSetClip( TRUE );\r
+               /* Restore background */\r
+               mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+               /* Draw sprites */\r
+               for(i=1; i <= MAX_SPRITE; sxMove( S[i] ));\r
+               /* Print message */\r
+               mxOutStr( 4, Page+4, 'Some sprites moving...' );\r
+               /* Flip page */\r
+               mxStartLine( Page );\r
+               Page = 240-Page;\r
+               /* Animate palette */\r
+               mxSetPalette( @Palette[64], 64, 192 );\r
+               mxRotatePalette( @Palette[64], 192, 3 );\r
+       }\r
+\r
+       mxSetMode( MX_TEXT );\r
+       mxTerm;\r
+\r
+}\r
diff --git a/16/xw_/mxbb.asm b/16/xw_/mxbb.asm
new file mode 100755 (executable)
index 0000000..5598cd1
--- /dev/null
@@ -0,0 +1,207 @@
+               PUBLIC  MXBITBLT
+               EXTRN   SUBHORIZONTALLINEINFO:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+               EXTRN   MX_BYTESPERLINE:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXBITBLT:
+       push            bp
+       mov             bp,sp
+       sub             sp,16H
+       push            ds
+       push            si
+       push            es
+       push            di
+       cmp             word ptr 0cH[bp],0
+       je              L$2
+       mov             ax,word ptr 10H[bp]
+       and             al,3
+       mov             dx,word ptr 8[bp]
+       and             dl,3
+       mov             bx,offset L$10
+       cmp             al,dl
+       jne             L$1
+       mov             bx,offset L$3
+L$1:
+       call            bx
+L$2:
+       xor             ax,ax
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0cH
+L$3:
+       mov             bx,word ptr 8[bp]
+       mov             ax,word ptr 6[bp]
+       mov             cx,word ptr 0cH[bp]
+       call            near ptr MX_TEXT:SUBHORIZONTALLINEINFO
+       mov             byte ptr -14H[bp],al
+       mov             byte ptr -16H[bp],ah
+       mov             word ptr 0cH[bp],cx
+       mov             ax,word ptr cs:MX_VIDEOSEGMENT
+       mov             ds,ax
+       mov             es,ax
+       mov             ax,word ptr 0eH[bp]
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             si,word ptr 10H[bp]
+       shr             si,1
+       shr             si,1
+       add             si,ax
+       mov             dx,3ceH
+       mov             ax,4105H
+       out             dx,ax
+       cld
+       mov             ah,byte ptr -14H[bp]
+       or              ah,ah
+       je              L$5
+       mov             dx,3c4H
+       mov             al,2
+       out             dx,ax
+       mov             ax,word ptr cs:MX_BYTESPERLINE
+       dec             ax
+       mov             cx,word ptr 0aH[bp]
+       push            si
+       push            di
+L$4:
+       movsb
+       add             si,ax
+       add             di,ax
+       dec             cx
+       jne             L$4
+       pop             di
+       pop             si
+       inc             si
+       inc             di
+L$5:
+       mov             bx,word ptr 0cH[bp]
+       test            bx,bx
+       je              L$7
+       mov             dx,3c4H
+       mov             ax,0f02H
+       out             dx,ax
+       mov             ax,word ptr cs:MX_BYTESPERLINE
+       sub             ax,bx
+       mov             dx,word ptr 0aH[bp]
+       push            si
+       push            di
+L$6:
+       mov             cx,bx
+       rep movsb
+       add             si,ax
+       add             di,ax
+       dec             dx
+       jne             L$6
+       pop             di
+       pop             si
+       add             si,bx
+       add             di,bx
+L$7:
+       mov             ah,byte ptr -16H[bp]
+       or              ah,ah
+       je              L$9
+       mov             dx,3c4H
+       mov             al,2
+       out             dx,ax
+       mov             ax,word ptr cs:MX_BYTESPERLINE
+       dec             ax
+       mov             cx,word ptr 0aH[bp]
+L$8:
+       movsb
+       add             si,ax
+       add             di,ax
+       dec             cx
+       jne             L$8
+L$9:
+       mov             dx,3ceH
+       mov             ax,4005H
+       out             dx,ax
+       ret
+L$10:
+       mov             cx,word ptr 0cH[bp]
+       mov             bx,cx
+       shr             bx,1
+       shr             bx,1
+       and             cl,3
+       mov             al,8
+       shr             al,cl
+       mov             si,6
+L$11:
+       mov             word ptr -8[bp+si],bx
+       shr             al,1
+       adc             bx,0
+       dec             si
+       dec             si
+       jge             L$11
+       mov             ax,word ptr cs:MX_VIDEOSEGMENT
+       mov             ds,ax
+       mov             es,ax
+       mov             ax,word ptr 0eH[bp]
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             si,word ptr 10H[bp]
+       shr             si,1
+       shr             si,1
+       add             si,ax
+       mov             word ptr -0aH[bp],si
+       mov             ax,word ptr 6[bp]
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             di,word ptr 8[bp]
+       shr             di,1
+       shr             di,1
+       add             di,ax
+       mov             word ptr -0cH[bp],di
+       mov             ax,word ptr 10H[bp]
+       and             al,3
+       mov             byte ptr -10H[bp],al
+       mov             cx,word ptr 8[bp]
+       and             cl,3
+       mov             al,11H
+       shl             al,cl
+       mov             byte ptr -12H[bp],al
+       cld
+       mov             byte ptr -0eH[bp],4
+       lea             bx,-8[bp]
+L$12:
+       cmp             word ptr ss:[bx],0
+       je              L$15
+       mov             ah,byte ptr -12H[bp]
+       and             ah,0fH
+       mov             al,2
+       mov             dx,3c4H
+       out             dx,ax
+       mov             ah,byte ptr -10H[bp]
+       mov             al,4
+       mov             dx,3ceH
+       out             dx,ax
+       mov             dx,word ptr 0aH[bp]
+       mov             ax,word ptr cs:MX_BYTESPERLINE
+       sub             ax,word ptr ss:[bx]
+L$13:
+       mov             cx,word ptr ss:[bx]
+       shr             cx,1
+       rep movsw
+       rcl             cx,1
+       rep movsb
+       add             si,ax
+       add             di,ax
+       dec             dx
+       jne             L$13
+       inc             bx
+       inc             bx
+       inc             byte ptr -10H[bp]
+       and             byte ptr -10H[bp],3
+       jne             L$14
+       inc             word ptr -0aH[bp]
+L$14:
+       rol             byte ptr -12H[bp],1
+       adc             word ptr -0cH[bp],0
+       mov             si,word ptr -0aH[bp]
+       mov             di,word ptr -0cH[bp]
+       dec             byte ptr -0eH[bp]
+       jne             L$12
+L$15:
+       ret
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxcc.asm b/16/xw_/mxcc.asm
new file mode 100755 (executable)
index 0000000..efe64f3
--- /dev/null
@@ -0,0 +1,628 @@
+               PUBLIC  XSUBCLIPLINE
+               EXTRN   MX_CLIPY1:BYTE
+               EXTRN   MX_CLIPY2:BYTE
+               EXTRN   MX_CLIPX2:BYTE
+               EXTRN   MX_CLIPX1:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+               EXTRN   MX_BYTESPERLINE:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+       or              al,byte ptr [bx+si]
+L$2:
+    DW offset L$3
+       or              al,byte ptr [bx+si]
+    DW offset L$4
+       or              word ptr [bx+si],ax
+    DW offset L$5
+;      ????
+       inc             word ptr [bx+si]
+       add             byte ptr [bp+si],cl
+       add             byte ptr 0a00H[bx+si],al
+       add             byte ptr 900H[bp],dl
+       add             byte ptr -100H[si],ch
+       inc             word ptr [bx+si]
+       add             byte ptr ds:[0c000H],al
+       add             byte ptr ds:[0ce00H],al
+       add             byte ptr [di],al
+       add             ah,bl
+       add             bh,bh
+       inc             word ptr [bx+si]
+       add             bh,bh
+       inc             word ptr [bx+si]
+       add             bh,bh
+       inc             word ptr [bx+si]
+       add             bh,bh
+       inc             word ptr [bx+si]
+       add             bh,bh
+       inc             word ptr [bx+si]
+    DB 0
+L$3:
+    DW offset MX_TEXT+0ecH
+    DW offset MX_TEXT+0eeH
+    DW offset MX_TEXT+0f1H
+    DW offset MX_TEXT+0eaH
+    DW offset MX_TEXT+0f4H
+    DW offset MX_TEXT+0f7H
+    DW offset MX_TEXT+104H
+    DW offset MX_TEXT+0eaH
+    DW offset MX_TEXT+111H
+    DW offset MX_TEXT+114H
+    DW offset MX_TEXT+121H
+L$4:
+    DW offset MX_TEXT+132H
+    DW offset MX_TEXT+0eaH
+    DW offset MX_TEXT+135H
+    DW offset MX_TEXT+0eaH
+    DW offset MX_TEXT+13bH
+    DW offset MX_TEXT+0eaH
+    DW offset MX_TEXT+148H
+    DW offset L$7
+    DW offset L$10
+    DW offset L$7
+    DW offset L$11
+L$5:
+    DW offset L$14
+    DW offset L$15
+    DW offset L$7
+    DW offset L$7
+    DW offset L$16
+    DW offset L$17
+    DW offset L$7
+    DW offset L$7
+    DW offset L$18
+    DW offset L$19
+    DW offset L$22
+    DW offset L$23
+    DW offset L$24
+    DW offset L$7
+    DW offset L$7
+    DW offset L$7
+    DW offset L$7
+    DW offset L$7
+    DW offset L$25
+    DW offset L$26
+    DW offset L$27
+    DW offset L$30
+    DW offset L$7
+    DW offset L$31
+    DW offset L$7
+    DW offset L$7
+    DW offset L$7
+    DW offset L$7
+    DW offset L$7
+    DW offset L$32
+    DW offset L$7
+    DW offset L$33
+    DW offset L$36
+    DW offset L$37
+    DW offset L$7
+    DW offset L$7
+    DW offset L$7
+    DW offset L$7
+    DW offset L$7
+    DW offset L$7
+    DW offset L$38
+    DW offset L$39
+    DW offset L$43
+    DW offset L$44
+    DW offset L$45
+    DW offset L$7
+    DW offset L$46
+    DW offset L$47
+    DW offset L$48
+    DW offset L$51
+    DW offset L$7
+    DW offset L$52
+    DW offset L$7
+    DW offset L$53
+    DW offset L$7
+    DW offset L$54
+    DW offset L$58
+    DW offset L$59
+    DW offset L$7
+    DW offset L$7
+    DW offset L$60
+    DW offset L$61
+L$6:
+       clc
+       ret
+L$7:
+       stc
+       ret
+       clc
+       ret
+       jmp             near ptr L$67
+       jmp             near ptr L$68
+       jmp             near ptr L$70
+       call            near ptr L$67
+       cmp             si,word ptr cs:MX_CLIPY1
+       jge             L$6
+       jmp             near ptr L$70
+       call            near ptr L$68
+       cmp             si,word ptr cs:MX_CLIPY1
+       jge             L$6
+       jmp             near ptr L$70
+       jmp             near ptr L$69
+       call            near ptr L$67
+       cmp             si,word ptr cs:MX_CLIPY2
+       jle             L$6
+       jmp             near ptr L$69
+       call            near ptr L$68
+       cmp             si,word ptr cs:MX_CLIPY2
+       jle             L$6
+       jmp             near ptr L$69
+L$8:
+       stc
+       ret
+L$9:
+       clc
+       ret
+       jmp             near ptr L$63
+       call            near ptr L$63
+       jmp             near ptr L$68
+       call            near ptr L$63
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jl              L$8
+       jmp             near ptr L$70
+       call            near ptr L$63
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jl              L$8
+       call            near ptr L$70
+       cmp             cx,word ptr cs:MX_CLIPX2
+       jle             L$9
+       jmp             near ptr L$68
+L$10:
+       call            near ptr L$63
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jg              L$8
+       jmp             near ptr L$69
+L$11:
+       call            near ptr L$63
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jg              L$8
+       call            near ptr L$69
+       cmp             cx,word ptr cs:MX_CLIPX2
+       jle             L$9
+       jmp             near ptr L$68
+L$12:
+       clc
+       ret
+L$13:
+       stc
+       ret
+L$14:
+       jmp             near ptr L$64
+L$15:
+       call            near ptr L$64
+       jmp             near ptr L$67
+L$16:
+       call            near ptr L$64
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jl              L$13
+       jmp             near ptr L$70
+L$17:
+       call            near ptr L$64
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jl              L$13
+       call            near ptr L$70
+       cmp             cx,word ptr cs:MX_CLIPX1
+       jge             L$12
+       jmp             near ptr L$67
+L$18:
+       call            near ptr L$64
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jg              L$13
+       jmp             near ptr L$69
+L$19:
+       call            near ptr L$64
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jg              L$13
+       call            near ptr L$69
+       cmp             cx,word ptr cs:MX_CLIPX1
+       jge             L$12
+       jmp             near ptr L$67
+L$20:
+       clc
+       ret
+L$21:
+       stc
+       ret
+L$22:
+       jmp             near ptr L$66
+L$23:
+       call            near ptr L$66
+       cmp             di,word ptr cs:MX_CLIPX1
+       jl              L$21
+       call            near ptr L$67
+       cmp             si,word ptr cs:MX_CLIPY1
+       jge             L$20
+       jmp             near ptr L$70
+L$24:
+       call            near ptr L$66
+       cmp             di,word ptr cs:MX_CLIPX2
+       jg              L$21
+       jmp             near ptr L$68
+L$25:
+       call            near ptr L$66
+       jmp             near ptr L$69
+L$26:
+       call            near ptr L$66
+       cmp             di,word ptr cs:MX_CLIPX1
+       jl              L$21
+       call            near ptr L$67
+       cmp             si,word ptr cs:MX_CLIPY2
+       jle             L$20
+       jmp             near ptr L$69
+L$27:
+       call            near ptr L$66
+       cmp             di,word ptr cs:MX_CLIPX2
+       jg              L$21
+       call            near ptr L$68
+       cmp             si,word ptr cs:MX_CLIPY2
+       jle             L$20
+       jmp             near ptr L$69
+L$28:
+       clc
+       ret
+L$29:
+       stc
+       ret
+L$30:
+       call            near ptr L$63
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jge             L$28
+       jmp             near ptr L$66
+L$31:
+       call            near ptr L$68
+       cmp             si,word ptr cs:MX_CLIPY1
+       jl              L$29
+       call            near ptr L$66
+       cmp             di,word ptr cs:MX_CLIPX1
+       jge             L$28
+       jmp             near ptr L$63
+L$32:
+       call            near ptr L$69
+       cmp             cx,word ptr cs:MX_CLIPX1
+       jl              L$29
+       call            near ptr L$66
+       cmp             di,word ptr cs:MX_CLIPX1
+       jge             L$28
+       jmp             near ptr L$63
+L$33:
+       call            near ptr L$63
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jg              L$29
+       call            near ptr L$68
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jl              L$29
+       cmp             si,word ptr cs:MX_CLIPY2
+       jle             L$28
+       jmp             near ptr L$69
+L$34:
+       clc
+       ret
+L$35:
+       stc
+       ret
+L$36:
+       call            near ptr L$64
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jge             L$34
+       jmp             near ptr L$66
+L$37:
+       call            near ptr L$67
+       cmp             si,word ptr cs:MX_CLIPY2
+       jl              L$35
+       call            near ptr L$66
+       cmp             di,word ptr cs:MX_CLIPX2
+       jle             L$34
+       jmp             near ptr L$64
+L$38:
+       call            near ptr L$69
+       cmp             cx,word ptr cs:MX_CLIPX2
+       jg              L$35
+       call            near ptr L$64
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jge             L$34
+       jmp             near ptr L$66
+L$39:
+       call            near ptr L$67
+       cmp             si,word ptr cs:MX_CLIPY1
+       jl              L$35
+       call            near ptr L$64
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jg              L$35
+       cmp             si,word ptr cs:MX_CLIPY2
+       jle             L$40
+       call            near ptr L$69
+L$40:
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jge             L$34
+       jmp             near ptr L$66
+L$41:
+       clc
+       ret
+L$42:
+       stc
+       ret
+L$43:
+       jmp             near ptr L$65
+L$44:
+       call            near ptr L$65
+       cmp             di,word ptr cs:MX_CLIPX1
+       jl              L$42
+       jmp             near ptr L$67
+L$45:
+       call            near ptr L$65
+       cmp             di,word ptr cs:MX_CLIPX2
+       jg              L$42
+       jmp             near ptr L$68
+L$46:
+       call            near ptr L$65
+       jmp             near ptr L$70
+L$47:
+       call            near ptr L$65
+       cmp             di,word ptr cs:MX_CLIPX1
+       jl              L$42
+       call            near ptr L$67
+       cmp             si,word ptr cs:MX_CLIPY1
+       jge             L$42
+       jmp             near ptr L$70
+L$48:
+       call            near ptr L$65
+       cmp             di,word ptr cs:MX_CLIPX2
+       jg              L$42
+       call            near ptr L$68
+       cmp             si,word ptr cs:MX_CLIPY1
+       jge             L$41
+       jmp             near ptr L$70
+L$49:
+       clc
+       ret
+L$50:
+       stc
+       ret
+L$51:
+       call            near ptr L$63
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jle             L$49
+       jmp             near ptr L$65
+L$52:
+       call            near ptr L$68
+       cmp             si,word ptr cs:MX_CLIPY2
+       jg              L$50
+       call            near ptr L$65
+       cmp             di,word ptr cs:MX_CLIPX1
+       jge             L$49
+       jmp             near ptr L$63
+L$53:
+       call            near ptr L$70
+       cmp             cx,word ptr cs:MX_CLIPX1
+       jl              L$50
+       call            near ptr L$63
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jle             L$49
+       jmp             near ptr L$65
+L$54:
+       call            near ptr L$63
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jl              L$50
+       call            near ptr L$68
+       cmp             si,word ptr cs:MX_CLIPY2
+       jg              L$50
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jle             L$55
+       call            near ptr L$65
+L$55:
+       cmp             si,word ptr cs:MX_CLIPY1
+       jge             L$49
+       jmp             near ptr L$70
+L$56:
+       clc
+       ret
+L$57:
+       stc
+       ret
+L$58:
+       call            near ptr L$64
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jle             L$56
+       jmp             near ptr L$65
+L$59:
+       call            near ptr L$67
+       cmp             si,word ptr cs:MX_CLIPY2
+       jg              L$57
+       call            near ptr L$65
+       cmp             di,word ptr cs:MX_CLIPX2
+       jle             L$56
+       jmp             L$64
+L$60:
+       call            near ptr L$70
+       cmp             cx,word ptr cs:MX_CLIPX2
+       jg              L$57
+       call            near ptr L$64
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jle             L$56
+       jmp             L$65
+L$61:
+       call            near ptr L$67
+       cmp             si,word ptr cs:MX_CLIPY2
+       jg              L$57
+       call            near ptr L$64
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jl              L$57
+       cmp             si,word ptr cs:MX_CLIPY1
+       jge             L$62
+       call            near ptr L$70
+L$62:
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jle             L$56
+       jmp             L$65
+L$63:
+       mov             ax,si
+       sub             ax,bx
+       mov             dx,word ptr cs:MX_CLIPX1
+       sub             dx,di
+       imul            dx
+       mov             bp,cx
+       sub             bp,di
+       idiv            bp
+       add             bx,ax
+       mov             di,word ptr cs:MX_CLIPX1
+       clc
+       ret
+L$64:
+       mov             ax,si
+       sub             ax,bx
+       mov             dx,word ptr cs:MX_CLIPX2
+       sub             dx,di
+       imul            dx
+       mov             bp,cx
+       sub             bp,di
+       idiv            bp
+       add             bx,ax
+       mov             di,word ptr cs:MX_CLIPX2
+       clc
+       ret
+L$65:
+       mov             ax,cx
+       sub             ax,di
+       mov             dx,word ptr cs:MX_CLIPY2
+       sub             dx,bx
+       imul            dx
+       mov             bp,si
+       sub             bp,bx
+       idiv            bp
+       add             di,ax
+       mov             bx,word ptr cs:MX_CLIPY2
+       clc
+       ret
+L$66:
+       mov             ax,cx
+       sub             ax,di
+       mov             dx,word ptr cs:MX_CLIPY1
+       sub             dx,bx
+       imul            dx
+       mov             bp,si
+       sub             bp,bx
+       idiv            bp
+       add             di,ax
+       mov             bx,word ptr cs:MX_CLIPY1
+       clc
+       ret
+L$67:
+       mov             ax,bx
+       sub             ax,si
+       mov             dx,word ptr cs:MX_CLIPX1
+       sub             dx,cx
+       imul            dx
+       mov             bp,di
+       sub             bp,cx
+       idiv            bp
+       add             si,ax
+       mov             cx,word ptr cs:MX_CLIPX1
+       clc
+       ret
+L$68:
+       mov             ax,bx
+       sub             ax,si
+       mov             dx,word ptr cs:MX_CLIPX2
+       sub             dx,cx
+       imul            dx
+       mov             bp,di
+       sub             bp,cx
+       idiv            bp
+       add             si,ax
+       mov             cx,word ptr cs:MX_CLIPX2
+       clc
+       ret
+L$69:
+       mov             ax,di
+       sub             ax,cx
+       mov             dx,word ptr cs:MX_CLIPY2
+       sub             dx,si
+       imul            dx
+       mov             bp,bx
+       sub             bp,si
+       idiv            bp
+       add             cx,ax
+       mov             si,word ptr cs:MX_CLIPY2
+       clc
+       ret
+L$70:
+       mov             ax,di
+       sub             ax,cx
+       mov             dx,word ptr cs:MX_CLIPY1
+       sub             dx,si
+       imul            dx
+       mov             bp,bx
+       sub             bp,si
+       idiv            bp
+       add             cx,ax
+       mov             si,word ptr cs:MX_CLIPY1
+       clc
+       ret
+XSUBCLIPLINE:
+       push            bp
+       xor             si,si
+       cmp             dx,word ptr cs:MX_CLIPY2
+       jle             L$71
+       or              si,8
+       jmp             L$72
+L$71:
+       cmp             dx,word ptr cs:MX_CLIPY1
+       jge             L$72
+       or              si,4
+L$72:
+       cmp             cx,word ptr cs:MX_CLIPX2
+       jle             L$73
+       or              si,2
+       jmp             L$74
+L$73:
+       cmp             cx,word ptr cs:MX_CLIPX1
+       jge             L$74
+       or              si,1
+L$74:
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jle             L$75
+       or              si,80H
+       jmp             L$76
+L$75:
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jge             L$76
+       or              si,40H
+L$76:
+       cmp             ax,word ptr cs:MX_CLIPX2
+       jle             L$77
+       or              si,20H
+       jmp             L$78
+L$77:
+       cmp             ax,word ptr cs:MX_CLIPX1
+       jge             L$78
+       or              si,10H
+L$78:
+       mov             di,si
+       and             di,0fH
+       and             si,0f0H
+       shr             si,1
+       shr             si,1
+       cmp             di,word ptr cs:L$1[si]
+       jg              L$79
+       mov             si,word ptr cs:L$2[si]
+       shl             di,1
+       add             si,di
+       mov             di,ax
+       mov             si,word ptr cs:[si]
+       xchg            si,dx
+       call            dx
+       mov             ax,di
+       mov             dx,si
+       pop             bp
+       ret
+L$79:
+       pop             bp
+       stc
+       ret
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxcg.asm b/16/xw_/mxcg.asm
new file mode 100755 (executable)
index 0000000..c29a48e
--- /dev/null
@@ -0,0 +1,42 @@
+               PUBLIC  MXCOLORTOGRAY
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXCOLORTOGRAY:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             cx,word ptr 6[bp]
+       jcxz            L$2
+       lds             si,dword ptr 0cH[bp]
+       les             di,dword ptr 8[bp]
+       cld
+       mov             bx,4d97H
+L$1:
+       lodsb
+       mul             bh
+       mov             dx,ax
+       lodsb
+       mul             bl
+       add             dx,ax
+       lodsb
+       mov             ah,1cH
+       mul             ah
+       add             ax,dx
+       mov             al,ah
+       stosw
+       stosb
+       loop            L$1
+L$2:
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0aH
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxcl.asm b/16/xw_/mxcl.asm
new file mode 100755 (executable)
index 0000000..549bc8c
--- /dev/null
@@ -0,0 +1,110 @@
+               PUBLIC  MXCIRCLE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+               EXTRN   MX_CLIPX1:BYTE
+               EXTRN   MX_CLIPX2:BYTE
+               EXTRN   MX_CLIPY1:BYTE
+               EXTRN   MX_CLIPY2:BYTE
+               EXTRN   MX_BYTESPERLINE:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXCIRCLE:
+       push            bp
+       mov             bp,sp
+       sub             sp,2
+       push            ds
+       push            si
+       push            di
+       xor             si,si
+       mov             di,word ptr 8[bp]
+       mov             ax,3
+       sub             ax,di
+       sub             ax,di
+       mov             word ptr -2[bp],ax
+       mov             ds,word ptr cs:MX_VIDEOSEGMENT
+L$1:
+       cmp             si,di
+       jg              L$3
+       mov             ax,si
+       mov             bx,di
+       call            near ptr L$4
+       mov             ax,si
+       neg             ax
+       mov             bx,di
+       call            near ptr L$4
+       mov             ax,si
+       mov             bx,di
+       neg             bx
+       call            near ptr L$4
+       mov             ax,si
+       neg             ax
+       mov             bx,di
+       neg             bx
+       call            near ptr L$4
+       mov             ax,di
+       mov             bx,si
+       call            near ptr L$4
+       mov             ax,di
+       neg             ax
+       mov             bx,si
+       call            near ptr L$4
+       mov             ax,di
+       mov             bx,si
+       neg             bx
+       call            near ptr L$4
+       mov             ax,di
+       neg             ax
+       mov             bx,si
+       neg             bx
+       call            near ptr L$4
+       mov             ax,word ptr -2[bp]
+       test            ax,ax
+       jl              L$2
+       mov             ax,di
+       shl             ax,1
+       shl             ax,1
+       sub             ax,4
+       sub             word ptr -2[bp],ax
+       dec             di
+L$2:
+       mov             ax,si
+       shl             ax,1
+       shl             ax,1
+       add             ax,6
+       add             word ptr -2[bp],ax
+       inc             si
+       jmp             L$1
+L$3:
+       xor             ax,ax
+       pop             di
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+L$4:
+       add             bx,word ptr 0cH[bp]
+       add             ax,word ptr 0aH[bp]
+       cmp             bx,word ptr cs:MX_CLIPX1
+       jl              L$5
+       cmp             bx,word ptr cs:MX_CLIPX2
+       jg              L$5
+       cmp             ax,word ptr cs:MX_CLIPY1
+       jl              L$5
+       cmp             ax,word ptr cs:MX_CLIPY2
+       jg              L$5
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             cx,bx
+       shr             bx,1
+       shr             bx,1
+       add             bx,ax
+       and             cl,3
+       mov             ax,102H
+       shl             ah,cl
+       mov             dx,3c4H
+       out             dx,ax
+       mov             al,byte ptr 6[bp]
+       mov             byte ptr [bx],al
+L$5:
+       ret
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxcr.asm b/16/xw_/mxcr.asm
new file mode 100755 (executable)
index 0000000..826e065
--- /dev/null
@@ -0,0 +1,243 @@
+               PUBLIC  MX_CLIPX1
+               PUBLIC  MX_CLIPY1
+               PUBLIC  MX_CLIPX2
+               PUBLIC  MX_CLIPY2
+               PUBLIC  MXSETCLIP
+               PUBLIC  MXGETCLIP
+               PUBLIC  MXSETSYSCLIPREGION
+               PUBLIC  MXSETCLIPREGION
+               PUBLIC  MXGETCLIPREGION
+               PUBLIC  SUBCLIPIMAGE
+               PUBLIC  SUBCLIPBOX
+               EXTRN   MX_CODESEGMENT:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MX_CLIPX1:
+       add             byte ptr [bx+si],al
+MX_CLIPY1:
+       add             byte ptr [bx+si],al
+MX_CLIPX2:
+       add             byte ptr [bx+si],al
+MX_CLIPY2:
+       add             byte ptr [bx+si],al
+L$1:
+       add             byte ptr [bx+si],al
+L$2:
+       add             byte ptr [bx+si],al
+L$3:
+       add             byte ptr [bx+si],al
+L$4:
+       add             byte ptr [bx+si],al
+L$5:
+       add             byte ptr [bx+si],al
+L$6:
+       add             byte ptr [bx+si],al
+L$7:
+       add             byte ptr [bx+si],al
+L$8:
+       add             byte ptr [bx+si],al
+L$9:
+    DB 0
+MXSETCLIP:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       mov             ax,word ptr L$5
+       mov             bx,word ptr L$6
+       mov             cx,word ptr L$7
+       mov             dx,word ptr L$8
+       cmp             byte ptr 6[bp],1
+       je              L$10
+       mov             ax,word ptr L$1
+       mov             bx,word ptr L$2
+       mov             cx,word ptr L$3
+       mov             dx,word ptr L$4
+L$10:
+       mov             word ptr MX_CLIPX1,ax
+       mov             word ptr MX_CLIPY1,bx
+       mov             word ptr MX_CLIPX2,cx
+       mov             word ptr MX_CLIPY2,dx
+       mov             al,byte ptr 6[bp]
+       xchg            byte ptr L$9,al
+       xor             ah,ah
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            2
+MXGETCLIP:
+       mov             al,byte ptr cs:L$9
+       xor             ah,ah
+       retf
+MXSETSYSCLIPREGION:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       xor             ax,ax
+       mov             word ptr L$1,ax
+       mov             word ptr L$2,ax
+       mov             ax,word ptr 8[bp]
+       dec             ax
+       mov             word ptr L$3,ax
+       mov             ax,word ptr 6[bp]
+       dec             ax
+       mov             word ptr L$4,ax
+       mov             ax,0
+       push            ax
+       push            cs
+       call            near ptr MXSETCLIP
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            4
+MXSETCLIPREGION:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       mov             ax,word ptr 0cH[bp]
+       mov             word ptr L$5,ax
+       mov             ax,word ptr 0aH[bp]
+       mov             word ptr L$6,ax
+       mov             ax,word ptr 8[bp]
+       add             ax,word ptr 0cH[bp]
+       dec             ax
+       mov             word ptr L$7,ax
+       mov             ax,word ptr 6[bp]
+       add             ax,word ptr 0aH[bp]
+       dec             ax
+       mov             word ptr L$8,ax
+       mov             al,byte ptr L$9
+       cmp             al,1
+       jne             L$11
+       push            ax
+       push            cs
+       call            near ptr MXSETCLIP
+L$11:
+       xor             ax,ax
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+MXGETCLIPREGION:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            es
+       push            di
+       mov             ax,word ptr cs:L$5
+       les             di,dword ptr 12H[bp]
+       mov             word ptr es:[di],ax
+       mov             ax,word ptr cs:L$6
+       les             di,dword ptr 0eH[bp]
+       mov             word ptr es:[di],ax
+       mov             ax,word ptr cs:L$7
+       sub             ax,word ptr cs:L$5
+       inc             ax
+       les             di,dword ptr 0aH[bp]
+       mov             word ptr es:[di],ax
+       mov             ax,word ptr cs:L$8
+       sub             ax,word ptr cs:L$6
+       inc             ax
+       les             di,dword ptr 6[bp]
+       mov             word ptr es:[di],ax
+       mov             al,byte ptr cs:L$9
+       xor             ah,ah
+       pop             di
+       pop             es
+       mov             sp,bp
+       pop             bp
+       retf            10H
+SUBCLIPIMAGE:
+       xor             si,si
+       mov             di,word ptr cs:MX_CLIPY1
+       cmp             ax,di
+       jge             L$12
+       sub             di,ax
+       sub             dx,di
+       jle             L$16
+       mov             ax,di
+       mov             di,dx
+       mul             cx
+       mov             si,ax
+       mov             dx,di
+       mov             ax,word ptr cs:MX_CLIPY1
+L$12:
+       mov             di,word ptr cs:MX_CLIPY2
+       cmp             ax,di
+       jg              L$16
+       inc             di
+       sub             di,dx
+       sub             di,ax
+       jge             L$13
+       add             dx,di
+L$13:
+       mov             di,word ptr cs:MX_CLIPX1
+       cmp             bx,di
+       jge             L$14
+       sub             di,bx
+       sub             cx,di
+       jle             L$16
+       add             si,di
+       mov             bx,word ptr cs:MX_CLIPX1
+L$14:
+       mov             di,word ptr cs:MX_CLIPX2
+       cmp             bx,di
+       jg              L$16
+       inc             di
+       sub             di,bx
+       sub             di,cx
+       jge             L$15
+       add             cx,di
+L$15:
+       clc
+       ret
+L$16:
+       stc
+       ret
+SUBCLIPBOX:
+       mov             di,word ptr cs:MX_CLIPY1
+       cmp             ax,di
+       jge             L$17
+       sub             di,ax
+       sub             dx,di
+       jle             L$21
+       mov             ax,word ptr cs:MX_CLIPY1
+L$17:
+       mov             di,word ptr cs:MX_CLIPY2
+       cmp             ax,di
+       jg              L$21
+       inc             di
+       sub             di,dx
+       sub             di,ax
+       jge             L$18
+       add             dx,di
+L$18:
+       mov             di,word ptr cs:MX_CLIPX1
+       cmp             bx,di
+       jge             L$19
+       sub             di,bx
+       sub             cx,di
+       jle             L$21
+       mov             bx,word ptr cs:MX_CLIPX1
+L$19:
+       mov             di,word ptr cs:MX_CLIPX2
+       cmp             bx,di
+       jg              L$21
+       inc             di
+       sub             di,bx
+       sub             di,cx
+       jge             L$20
+       add             cx,di
+L$20:
+       clc
+       ret
+L$21:
+       stc
+       ret
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxel.asm b/16/xw_/mxel.asm
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/16/xw_/mxfb.asm b/16/xw_/mxfb.asm
new file mode 100755 (executable)
index 0000000..e20f1dc
--- /dev/null
@@ -0,0 +1,133 @@
+               PUBLIC  MXFILLBOX
+               EXTRN   SUBCLIPBOX:BYTE
+               EXTRN   SUBHORIZONTALLINEINFO:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+               EXTRN   MX_BYTESPERLINE:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+       mov             ah,al
+       shr             cx,1
+       rep stosw
+       rcl             cx,1
+       rep stosb
+       ret
+L$2:
+       mov             byte ptr [bx],al
+       add             bx,dx
+       loop            L$2
+       ret
+L$3:
+       mov             si,di
+L$4:
+       mov             ah,byte ptr [si]
+       mov             byte ptr [si],al
+       inc             si
+       loop            L$4
+       ret
+L$5:
+       mov             ah,byte ptr [bx]
+       mov             byte ptr [bx],al
+       add             bx,dx
+       loop            L$5
+       ret
+MXFILLBOX:
+       push            bp
+       mov             bp,sp
+       sub             sp,8
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             bx,word ptr 10H[bp]
+       mov             ax,word ptr 0eH[bp]
+       mov             cx,word ptr 0cH[bp]
+       mov             dx,word ptr 0aH[bp]
+       call            near ptr MX_TEXT:SUBCLIPBOX
+       jae             L$6
+       jmp             near ptr L$12
+L$6:
+       mov             word ptr 0aH[bp],dx
+       call            near ptr MX_TEXT:SUBHORIZONTALLINEINFO
+       mov             word ptr 0cH[bp],cx
+       mov             byte ptr -2[bp],al
+       mov             byte ptr -4[bp],ah
+       mov             ax,word ptr cs:MX_VIDEOSEGMENT
+       mov             es,ax
+       mov             ds,ax
+       cld
+       mov             word ptr -6[bp],offset L$2
+       mov             word ptr -8[bp],offset L$1
+       mov             ax,word ptr 6[bp]
+       cmp             al,3
+       ja              L$7
+       cmp             al,0
+       je              L$7
+       shl             al,1
+       shl             al,1
+       shl             al,1
+       mov             ah,al
+       mov             al,3
+       mov             dx,3ceH
+       out             dx,ax
+       mov             word ptr -6[bp],offset L$5
+       mov             word ptr -8[bp],offset L$3
+L$7:
+       mov             ah,byte ptr -2[bp]
+       or              ah,ah
+       je              L$8
+       mov             dx,3c4H
+       mov             al,2
+       out             dx,ax
+       mov             dx,word ptr cs:MX_BYTESPERLINE
+       mov             cx,word ptr 0aH[bp]
+       mov             bx,di
+       mov             al,byte ptr 8[bp]
+       call            word ptr -6[bp]
+       inc             di
+L$8:
+       mov             cx,word ptr 0cH[bp]
+       jcxz            L$10
+       mov             dx,3c4H
+       mov             ax,0f02H
+       out             dx,ax
+       mov             al,byte ptr 8[bp]
+       mov             bx,di
+       mov             dx,word ptr 0aH[bp]
+       push            di
+L$9:
+       mov             di,bx
+       call            word ptr -8[bp]
+       mov             cx,word ptr 0cH[bp]
+       add             bx,word ptr cs:MX_BYTESPERLINE
+       dec             dx
+       jne             L$9
+       pop             di
+       add             di,word ptr 0cH[bp]
+L$10:
+       mov             ah,byte ptr -4[bp]
+       or              ah,ah
+       je              L$11
+       mov             dx,3c4H
+       mov             al,2
+       out             dx,ax
+       mov             dx,word ptr cs:MX_BYTESPERLINE
+       mov             cx,word ptr 0aH[bp]
+       mov             bx,di
+       mov             al,byte ptr 8[bp]
+       call            word ptr -6[bp]
+L$11:
+       mov             dx,3ceH
+       mov             ax,3
+       out             dx,ax
+L$12:
+       xor             ax,ax
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0cH
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxfp.asm b/16/xw_/mxfp.asm
new file mode 100755 (executable)
index 0000000..7ff2617
--- /dev/null
@@ -0,0 +1,219 @@
+               PUBLIC  MXFADEPALETTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+       inc             bx
+       outsw
+       jo              L$5
+       jb              L$4
+       push            2074H
+       sub             byte ptr 29H[bp+di],ah
+       and             byte ptr [bx+di],dh
+       cmp             word ptr [bx+di],di
+       xor             ch,byte ptr [di]
+       xor             word ptr [bx+di],di
+       cmp             word ptr [si],si
+       and             byte ptr 52H[bx+di],al
+       push            sp
+       dec             cx
+       push            bx
+       and             byte ptr 2eH[bp+di],dh
+       jb              L$1
+       insb
+       and             byte ptr cs:6cH[bx+di],al
+       insb
+       and             byte ptr 69H[bp+si],dh
+       push            7374H
+       and             byte ptr 65H[bp+si],dh
+       jae             L$7
+       jb              L$9
+    DB 65H, 64H, 2eH
+MXFADEPALETTE:
+       push            bp
+       mov             bp,sp
+       sub             sp,60aH
+       push            si
+       push            di
+       push            ds
+       push            es
+       mov             word ptr -608H[bp],1
+       mov             ax,word ptr 10H[bp]
+       and             ax,0ff00H
+L$1:
+       je              L$2
+       mov             cl,8
+       shr             ax,cl
+       mov             word ptr -608H[bp],ax
+L$2:
+       mov             ax,word ptr 10H[bp]
+       and             ax,0feH
+       mov             cl,1
+       shr             ax,cl
+       or              ax,ax
+       jne             L$3
+       mov             ax,30H
+L$3:
+       mov             word ptr -60aH[bp],ax
+L$4:
+       inc             ax
+       mov             byte ptr -606H[bp],al
+       mov             byte ptr -604H[bp],1
+    DB 0c6H, 86H, 0feH, 0f9H
+L$5:
+       add             byte ptr 0e46H[bp+di],cl
+       cmp             ax,100H
+       jb              L$6
+       jmp             near ptr L$12
+L$6:
+       add             ax,word ptr 0cH[bp]
+       cmp             ax,100H
+       jbe             L$8
+       mov             ax,100H
+       sub             ax,word ptr 0eH[bp]
+    DB 89H, 46H
+L$7:
+       or              al,0bH
+       ????
+       jne             L$8
+       jmp             near ptr L$12
+L$8:
+       mov             cx,word ptr 0cH[bp]
+       mov             ax,cx
+       shl             ax,1
+       add             cx,ax
+       mov             ax,ss
+L$9:
+       mov             es,ax
+       lea             di,-300H[bp]
+       mov             ax,word ptr 0eH[bp]
+       mov             si,ax
+       shl             ax,1
+       add             ax,si
+       lds             si,dword ptr 12H[bp]
+       add             si,ax
+       cld
+       shr             cx,1
+       rep movsw
+       rcl             cx,1
+       rep movsb
+       test            word ptr 10H[bp],1
+       je              L$10
+       mov             ax,word ptr -60aH[bp]
+       mov             byte ptr -602H[bp],al
+       mov             byte ptr -604H[bp],0ffH
+       mov             ax,ss
+       mov             ds,ax
+       mov             es,ax
+       lea             di,-300H[bp]
+       mov             ax,word ptr 0eH[bp]
+       mov             cx,word ptr 0cH[bp]
+       call            near ptr L$19
+L$10:
+       mov             bh,byte ptr 0aH[bp]
+       and             bh,3fH
+       mov             bl,byte ptr 8[bp]
+       and             bl,3fH
+       mov             dh,byte ptr 6[bp]
+       and             dh,3fH
+       mov             dl,byte ptr -602H[bp]
+       mov             ax,ss
+       mov             ds,ax
+       mov             es,ax
+L$11:
+       mov             ax,word ptr 0cH[bp]
+       mov             cx,word ptr -60aH[bp]
+       lea             si,-300H[bp]
+       lea             di,-600H[bp]
+       call            near ptr L$13
+       push            bx
+       push            dx
+       lea             si,-600H[bp]
+       mov             ax,word ptr 0eH[bp]
+       mov             bx,word ptr 0cH[bp]
+       mov             cx,word ptr -608H[bp]
+       call            near ptr L$15
+       pop             dx
+       pop             bx
+       add             dl,byte ptr -604H[bp]
+       dec             byte ptr -606H[bp]
+       jne             L$11
+L$12:
+       pop             es
+       pop             ds
+       pop             di
+       pop             si
+       mov             sp,bp
+       pop             bp
+       retf            10H
+L$13:
+       cld
+       push            bp
+       mov             bp,ax
+L$14:
+       lodsb
+       sub             al,bh
+       imul            dl
+       idiv            cl
+       add             al,bh
+       stosb
+       lodsb
+       sub             al,bl
+       imul            dl
+       idiv            cl
+       add             al,bl
+       stosb
+       lodsb
+       sub             al,dh
+       imul            dl
+       idiv            cl
+       add             al,dh
+       stosb
+       dec             bp
+       jne             L$14
+       pop             bp
+       ret
+L$15:
+       mov             ah,al
+       mov             dx,3daH
+L$16:
+       in              al,dx
+       test            al,8
+       jne             L$16
+L$17:
+       in              al,dx
+       test            al,8
+       je              L$17
+       loop            L$16
+       mov             cx,bx
+       mov             dx,3c8H
+       mov             al,ah
+       out             dx,al
+       inc             dx
+       cld
+       cli
+L$18:
+       lodsb
+       out             dx,al
+       lodsb
+       out             dx,al
+       lodsb
+       out             dx,al
+       loop            L$18
+       sti
+       ret
+L$19:
+       mov             dx,3c7H
+       out             dx,al
+       inc             dx
+       inc             dx
+       cld
+L$20:
+       in              al,dx
+       stosb
+       in              al,dx
+       stosb
+       in              al,dx
+       stosb
+       loop            L$20
+       ret
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxgc.asm b/16/xw_/mxgc.asm
new file mode 100755 (executable)
index 0000000..2f29763
--- /dev/null
@@ -0,0 +1,30 @@
+               PUBLIC  MXGETCOLOR
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXGETCOLOR:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       mov             ax,word ptr 12H[bp]
+       mov             dx,3c7H
+       out             dx,al
+       inc             dx
+       inc             dx
+       lds             si,dword ptr 0eH[bp]
+       in              al,dx
+       mov             byte ptr [si],al
+       lds             si,dword ptr 0aH[bp]
+       in              al,dx
+       mov             byte ptr [si],al
+       lds             si,dword ptr 6[bp]
+       in              al,dx
+       mov             byte ptr [si],al
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0eH
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxgi.asm b/16/xw_/mxgi.asm
new file mode 100755 (executable)
index 0000000..0570d49
--- /dev/null
@@ -0,0 +1,98 @@
+               PUBLIC  MXGETIMAGE
+               EXTRN   SUBCLIPIMAGE:BYTE
+               EXTRN   MX_BYTESPERLINE:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXGETIMAGE:
+       push            bp
+       mov             bp,sp
+       sub             sp,10H
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             bx,word ptr 0cH[bp]
+       mov             ax,word ptr 0aH[bp]
+       mov             cx,word ptr 8[bp]
+       mov             dx,word ptr 6[bp]
+       call            near ptr MX_TEXT:SUBCLIPIMAGE
+       jae             L$1
+       jmp             near ptr L$7
+L$1:
+       mov             word ptr 6[bp],dx
+       add             word ptr 0eH[bp],si
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             si,bx
+       shr             si,1
+       shr             si,1
+       add             si,ax
+       mov             word ptr -0aH[bp],si
+       mov             ds,word ptr cs:MX_VIDEOSEGMENT
+       and             bl,3
+       mov             byte ptr -0eH[bp],bl
+       mov             bx,cx
+       shr             bx,1
+       shr             bx,1
+       and             cl,3
+       mov             al,8
+       shr             al,cl
+       mov             di,6
+L$2:
+       mov             word ptr -8[bp+di],bx
+       shr             al,1
+       adc             bx,0
+       dec             di
+       dec             di
+       jge             L$2
+       cld
+       mov             byte ptr -10H[bp],4
+       lea             bx,-8[bp]
+       mov             es,word ptr 10H[bp]
+       mov             ah,byte ptr -0eH[bp]
+L$3:
+       cmp             word ptr ss:[bx],0
+       je              L$7
+       mov             di,word ptr 0eH[bp]
+       mov             al,4
+       mov             dx,3ceH
+       out             dx,ax
+       mov             dx,word ptr 6[bp]
+       mov             si,word ptr -0aH[bp]
+L$4:
+       push            si
+       push            di
+       mov             cx,word ptr ss:[bx]
+L$5:
+       movsb
+       add             di,3
+       dec             cx
+       jne             L$5
+       pop             di
+       pop             si
+       add             di,word ptr 8[bp]
+       add             si,word ptr cs:MX_BYTESPERLINE
+       dec             dx
+       jne             L$4
+       inc             bx
+       inc             bx
+       inc             ah
+       test            ah,4
+       je              L$6
+       inc             word ptr -0aH[bp]
+       and             ah,3
+L$6:
+       inc             word ptr 0eH[bp]
+       dec             byte ptr -10H[bp]
+       jne             L$3
+L$7:
+       xor             ax,ax
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0cH
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxgm.asm b/16/xw_/mxgm.asm
new file mode 100755 (executable)
index 0000000..8ca07a1
--- /dev/null
@@ -0,0 +1,68 @@
+               PUBLIC  MXGAMMACORRECT
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+       add             byte ptr [bp+si],cl
+       push            cs
+       adc             word ptr [bp+di],dx
+       adc             ax,1817H
+       sbb             bl,byte ptr [bp+di]
+       sbb             al,1dH
+       pop             ds
+       and             byte ptr [bx+di],ah
+       and             ah,byte ptr [bp+di]
+       and             al,25H
+       and             ax,2726H
+       sub             byte ptr [bx+di],ch
+       sub             word ptr [bp+si],bp
+       sub             bp,word ptr [si]
+       sub             al,2dH
+       das
+       xor             byte ptr [bx+si],dh
+       xor             word ptr [bx+di],si
+       xor             dh,byte ptr [bp+di]
+       xor             si,word ptr [si]
+       xor             al,35H
+       xor             ax,3636H
+       aaa
+       aaa
+       cmp             byte ptr [bx+si],bh
+       cmp             word ptr [bx+di],di
+       cmp             bh,byte ptr [bp+si]
+       cmp             di,word ptr [bp+di]
+       cmp             al,3cH
+       cmp             ax,3e3dH
+       aas
+       aas
+MXGAMMACORRECT:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             cx,word ptr 6[bp]
+       jcxz            L$3
+       lds             si,dword ptr 0cH[bp]
+       les             di,dword ptr 8[bp]
+       mov             bx,offset L$1
+       cld
+       mov             ax,cx
+       add             cx,cx
+       add             cx,ax
+L$2:
+       lodsb
+       xlat            word ptr cs:[bx]
+       stosb
+       loop            L$2
+L$3:
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0aH
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxgp.asm b/16/xw_/mxgp.asm
new file mode 100755 (executable)
index 0000000..14dfc17
--- /dev/null
@@ -0,0 +1,32 @@
+               PUBLIC  MXGETPALETTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXGETPALETTE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            es
+       push            di
+       les             di,dword ptr 0aH[bp]
+       mov             cx,word ptr 6[bp]
+       mov             ax,word ptr 8[bp]
+       mov             dx,3c7H
+       out             dx,al
+       inc             dx
+       inc             dx
+       cld
+L$1:
+       in              al,dx
+       stosb
+       in              al,dx
+       stosb
+       in              al,dx
+       stosb
+       loop            L$1
+       pop             di
+       pop             es
+       mov             sp,bp
+       pop             bp
+       retf            8
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxgv.asm b/16/xw_/mxgv.asm
new file mode 100755 (executable)
index 0000000..44b30dd
--- /dev/null
@@ -0,0 +1,8 @@
+               PUBLIC  MXGETVERSION
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXGETVERSION:
+       mov             ax,128H
+       retf
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxhl.asm b/16/xw_/mxhl.asm
new file mode 100755 (executable)
index 0000000..f664632
--- /dev/null
@@ -0,0 +1,45 @@
+               PUBLIC  SUBHORIZONTALLINEINFO
+               EXTRN   MX_BYTESPERLINE:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+       add             byte ptr [bx+si],al
+       add             ax,word ptr [bx+si]
+       add             al,byte ptr [bx+si]
+       add             word ptr [bx+si],ax
+L$2:
+       add             byte ptr ds:[80cH],cl
+L$3:
+       add             byte ptr [bx+di],al
+       add             ax,word ptr [bx]
+L$4:
+    DB 2, 6
+SUBHORIZONTALLINEINFO:
+    ;DD        ds:[63278]
+    ASSUME  ds:NOTHING
+       add             byte ptr -2e05H[bp+di],cl
+       out             dx,ax
+       shr             di,1
+       add             di,ax
+       and             bx,3
+       mov             al,byte ptr cs:L$2[bx]
+       shl             bx,1
+       sub             cx,word ptr cs:L$1[bx]
+       jge             L$5
+       mov             bx,cx
+       inc             bx
+       inc             bx
+       and             al,byte ptr cs:L$4[bx]
+       xor             ah,ah
+       xor             cx,cx
+       jmp             L$6
+L$5:
+       mov             bx,cx
+       and             bx,3
+       mov             ah,byte ptr cs:L$3[bx]
+       shr             cx,1
+       shr             cx,1
+L$6:
+       ret
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxit.asm b/16/xw_/mxit.asm
new file mode 100755 (executable)
index 0000000..25bce3c
--- /dev/null
@@ -0,0 +1,98 @@
+;-----------------------------------------------------------\r
+;\r
+; MXIT.ASM - Initialization/termination functions\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+;WARN    PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxInit\r
+PUBLIC  mxTerm\r
+\r
+PUBLIC  mx_VideoSegment\r
+PUBLIC  mx_CodeSegment\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+DB      'MODEX library - Copyright (c) 1992-1994 Alessandro Scotti'\r
+\r
+mx_VideoSegment DW      0A000h\r
+mx_CodeSegment  DW      SEG MX_TEXT\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Initialization.\r
+;\r
+; Input:\r
+;       none\r
+; Output:\r
+;       AX      = 0 on success\r
+;\r
+mxInit  PROC FAR\r
+        LOCAL   Result:WORD,            \\r
+                VideoSeg:WORD,          \\r
+                CStoDSalias:WORD        = AUTO_SIZE\r
+        ASSUME  ds:NOTHING\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+\r
+        mov     [Result], -1            ; Assume an error\r
+        mov     [VideoSeg], 0A000h      ; Real mode video segment\r
+        mov     [CStoDSalias], cs       ; Real mode data alias for CS\r
+\r
+; Check if running in protected mode under DPMI\r
+        mov     ax, 1686h\r
+        int     2Fh\r
+        or      ax, ax\r
+         jnz    @@1                     ; DPMI not found, continue in real mode\r
+\r
+; Get a data alias for CS\r
+        mov     ax, 000Ah               ; DMPI: create data alias\r
+        mov     bx, cs\r
+        int     31h\r
+         jc     @@Exit                  ; Exit if service failed\r
+        mov     [CStoDSalias], ax       ; Save data alias for CS\r
+; Get a protected-mode selector for the video segment\r
+        mov     ax, 0002h\r
+        mov     bx, 0A000h              ; Real mode segment of video\r
+        int     31h                     ; DPMI: get segment selector\r
+         jc     @@Exit                  ; Exit if service failed\r
+        mov     [VideoSeg], ax          ; Save protected mode video selector\r
+\r
+; Initialize variables\r
+@@1:\r
+        mov     ds, [CStoDSalias]\r
+        ASSUME  ds:MX_TEXT\r
+        mov     [mx_CodeSegment], ds\r
+        mov     ax, [VideoSeg]\r
+        mov     [mx_VideoSegment], ax\r
+\r
+; Don't bother with VGA check for now...\r
+\r
+        mov     [Result], 0\r
+\r
+@@Exit:\r
+        mov     ax, [Result]\r
+        .pop    ds, si, es, di\r
+;        .leave\r
+mxInit  ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Termination.\r
+;\r
+; Input:\r
+;       none\r
+; Output:\r
+;       always 0.\r
+;\r
+mxTerm  PROC FAR\r
+        ASSUME  ds:NOTHING\r
+        xor     ax, ax\r
+        ret\r
+mxTerm  ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw_/mxll.asm b/16/xw_/mxll.asm
new file mode 100755 (executable)
index 0000000..f08de8d
--- /dev/null
@@ -0,0 +1,50 @@
+               PUBLIC  MXLOADLATCHES
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXLOADLATCHES:
+       push            ds
+       push            si
+       mov             dx,3ceH
+       mov             ax,0ff08H
+       out             dx,ax
+       mov             ax,3
+       out             dx,ax
+       mov             ax,5
+       out             dx,ax
+       mov             ax,word ptr cs:MX_VIDEOSEGMENT
+       mov             ds,ax
+       mov             si,0ffffH
+       mov             bh,8
+       mov             cx,3
+L$1:
+       mov             dx,3ceH
+       mov             al,4
+       mov             ah,cl
+       out             dx,ax
+       mov             dx,3c4H
+       mov             al,2
+       mov             ah,bh
+       out             dx,ax
+       mov             al,byte ptr [si]
+       push            ax
+       mov             byte ptr [si],bl
+       mov             al,byte ptr [di]
+       shr             bh,1
+       loop            L$1
+       mov             cx,3
+       mov             bh,8
+       mov             dx,3c4H
+L$2:
+       mov             al,2
+       mov             ah,bh
+       out             dx,ax
+       pop             ax
+       mov             byte ptr [si],al
+       shr             bh,1
+       loop            L$2
+       pop             si
+       pop             ds
+       ret
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxln.asm b/16/xw_/mxln.asm
new file mode 100755 (executable)
index 0000000..77d2b64
--- /dev/null
@@ -0,0 +1,332 @@
+               PUBLIC  MXLINE
+               EXTRN   MX_BYTESPERLINE:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+               EXTRN   MX_CLIPX1:BYTE
+               EXTRN   MX_CLIPX2:BYTE
+               EXTRN   MX_CLIPY1:BYTE
+               EXTRN   MX_CLIPY2:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+    DW offset L$29
+    DW offset L$32
+    DW offset L$35
+    DW offset L$38
+MXLINE:
+       push            bp
+       mov             bp,sp
+       sub             sp,12H
+       push            ds
+       push            si
+       push            di
+       mov             ax,word ptr 10H[bp]
+       mov             bx,word ptr 0eH[bp]
+       mov             cx,word ptr 0cH[bp]
+       mov             dx,word ptr 0aH[bp]
+       call            near ptr L$8
+       jae             L$2
+       jmp             near ptr L$7
+L$2:
+       mov             si,cx
+       xchg            ax,si
+       sub             ax,si
+       jge             L$3
+       xchg            cx,si
+       xchg            dx,bx
+       neg             ax
+L$3:
+       mov             word ptr -2[bp],ax
+       mov             cx,word ptr cs:MX_BYTESPERLINE
+       mov             ax,dx
+       sub             ax,bx
+       jge             L$4
+       neg             cx
+       neg             ax
+L$4:
+       mov             word ptr -4[bp],ax
+       mov             word ptr -0cH[bp],cx
+       mov             ax,bx
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             cx,si
+       shr             si,1
+       shr             si,1
+       add             si,ax
+       and             cl,3
+       mov             ax,1102H
+       shl             ah,cl
+       mov             byte ptr -12H[bp],ah
+       mov             dx,3c4H
+       out             dx,ax
+       mov             ax,word ptr cs:MX_VIDEOSEGMENT
+       mov             ds,ax
+       xor             bx,bx
+       mov             al,byte ptr 6[bp]
+       cmp             al,0
+       je              L$5
+       and             al,3
+       shl             al,1
+       shl             al,1
+       shl             al,1
+       mov             ah,al
+       mov             al,3
+       mov             dx,3ceH
+       out             dx,ax
+       inc             bx
+       inc             bx
+L$5:
+       mov             ax,word ptr -2[bp]
+       mov             cx,word ptr -4[bp]
+       cmp             ax,cx
+       jae             L$6
+       inc             bx
+L$6:
+       shl             bx,1
+       call            word ptr cs:L$1[bx]
+       cmp             byte ptr 6[bp],0
+       je              L$7
+       mov             ax,3
+       mov             dx,3ceH
+       out             dx,ax
+L$7:
+       xor             ax,ax
+       pop             di
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0cH
+L$8:
+       mov             di,ax
+       mov             si,dx
+       xor             al,al
+       cmp             cx,word ptr cs:MX_CLIPX1
+       jge             L$9
+       or              al,1
+L$9:
+       cmp             cx,word ptr cs:MX_CLIPX2
+       jle             L$10
+       or              al,2
+L$10:
+       cmp             si,word ptr cs:MX_CLIPY1
+       jge             L$11
+       or              al,4
+L$11:
+       cmp             si,word ptr cs:MX_CLIPY2
+       jle             L$12
+       or              al,8
+L$12:
+       mov             byte ptr -10H[bp],al
+       xor             al,al
+       cmp             di,word ptr cs:MX_CLIPX1
+       jge             L$13
+       or              al,1
+L$13:
+       cmp             di,word ptr cs:MX_CLIPX2
+       jle             L$14
+       or              al,2
+L$14:
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jge             L$15
+       or              al,4
+L$15:
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jle             L$16
+       or              al,8
+L$16:
+       mov             byte ptr -0eH[bp],al
+       mov             ah,byte ptr -10H[bp]
+       test            ah,al
+       je              L$17
+       jmp             near ptr L$28
+L$17:
+       or              ah,al
+       jne             L$18
+       jmp             near ptr L$27
+L$18:
+       mov             ax,cx
+       sub             ax,di
+       mov             word ptr -0aH[bp],ax
+       mov             ax,si
+       sub             ax,bx
+       mov             word ptr -0cH[bp],ax
+       mov             al,byte ptr -0eH[bp]
+L$19:
+       test            al,al
+       jne             L$20
+       xchg            di,cx
+       xchg            si,bx
+       xchg            byte ptr -10H[bp],al
+L$20:
+       test            al,1
+       je              L$21
+       mov             ax,word ptr cs:MX_CLIPX1
+       sub             ax,di
+       mov             di,word ptr cs:MX_CLIPX1
+       jmp             L$22
+L$21:
+       test            al,2
+       je              L$23
+       mov             ax,word ptr cs:MX_CLIPX2
+       sub             ax,di
+       mov             di,word ptr cs:MX_CLIPX2
+L$22:
+       imul            word ptr -0cH[bp]
+       idiv            word ptr -0aH[bp]
+       add             bx,ax
+       mov             al,8
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jg              L$26
+       mov             al,4
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jl              L$26
+       xor             al,al
+       jmp             L$26
+L$23:
+       test            al,4
+       je              L$24
+       mov             ax,word ptr cs:MX_CLIPY1
+       sub             ax,bx
+       mov             bx,word ptr cs:MX_CLIPY1
+       jmp             L$25
+L$24:
+       mov             ax,word ptr cs:MX_CLIPY2
+       sub             ax,bx
+       mov             bx,word ptr cs:MX_CLIPY2
+L$25:
+       imul            word ptr -0aH[bp]
+       idiv            word ptr -0cH[bp]
+       add             di,ax
+       mov             al,1
+       cmp             di,word ptr cs:MX_CLIPX1
+       jl              L$26
+       mov             al,2
+       cmp             di,word ptr cs:MX_CLIPX2
+       jg              L$26
+       xor             al,al
+L$26:
+       mov             ah,byte ptr -10H[bp]
+       test            ah,al
+       jne             L$28
+       or              ah,al
+       je              L$27
+       jmp             near ptr L$19
+L$27:
+       mov             ax,di
+       mov             dx,si
+       clc
+       ret
+L$28:
+       stc
+       ret
+L$29:
+       mov             di,ax
+       neg             di
+       shl             cx,1
+       mov             word ptr -6[bp],cx
+       mov             cx,ax
+       shl             ax,1
+       mov             word ptr -8[bp],ax
+       mov             al,2
+       mov             ah,byte ptr -12H[bp]
+       mov             bl,byte ptr 8[bp]
+       mov             dx,3c4H
+       inc             cx
+L$30:
+       mov             byte ptr [si],bl
+       dec             cx
+       je              L$31
+       rol             ah,1
+       adc             si,0
+       out             dx,ax
+       add             di,word ptr -6[bp]
+       jl              L$30
+       add             si,word ptr -0cH[bp]
+       sub             di,word ptr -8[bp]
+       jmp             L$30
+L$31:
+       ret
+L$32:
+       mov             di,cx
+       neg             di
+       shl             ax,1
+       mov             word ptr -6[bp],ax
+       mov             ax,cx
+       shl             ax,1
+       mov             word ptr -8[bp],ax
+       mov             bl,byte ptr 8[bp]
+       mov             ah,byte ptr -12H[bp]
+       mov             al,2
+       mov             dx,3c4H
+       inc             cx
+L$33:
+       mov             byte ptr [si],bl
+       dec             cx
+       je              L$34
+       add             si,word ptr -0cH[bp]
+       add             di,word ptr -6[bp]
+       jl              L$33
+       rol             ah,1
+       adc             si,0
+       out             dx,ax
+       sub             di,word ptr -8[bp]
+       jmp             L$33
+L$34:
+       ret
+L$35:
+       mov             di,ax
+       neg             di
+       shl             cx,1
+       mov             word ptr -6[bp],cx
+       mov             cx,ax
+       shl             ax,1
+       mov             word ptr -8[bp],ax
+       mov             al,2
+       mov             ah,byte ptr -12H[bp]
+       mov             bl,byte ptr 8[bp]
+       mov             dx,3c4H
+       inc             cx
+L$36:
+       mov             bh,byte ptr [si]
+       mov             byte ptr [si],bl
+       dec             cx
+       je              L$37
+       rol             ah,1
+       adc             si,0
+       out             dx,ax
+       add             di,word ptr -6[bp]
+       jl              L$36
+       add             si,word ptr -0cH[bp]
+       sub             di,word ptr -8[bp]
+       jmp             L$36
+L$37:
+       ret
+L$38:
+       mov             di,cx
+       neg             di
+       shl             ax,1
+       mov             word ptr -6[bp],ax
+       mov             ax,cx
+       shl             ax,1
+       mov             word ptr -8[bp],ax
+       mov             bl,byte ptr 8[bp]
+       mov             ah,byte ptr -12H[bp]
+       mov             al,2
+       mov             dx,3c4H
+       inc             cx
+L$39:
+       mov             bh,byte ptr [si]
+       mov             byte ptr [si],bl
+       dec             cx
+       je              L$40
+       add             si,word ptr -0cH[bp]
+       add             di,word ptr -6[bp]
+       jl              L$39
+       rol             ah,1
+       adc             si,0
+       out             dx,ax
+       sub             di,word ptr -8[bp]
+       jmp             L$39
+L$40:
+       ret
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxot.asm b/16/xw_/mxot.asm
new file mode 100755 (executable)
index 0000000..f7e6fde
--- /dev/null
@@ -0,0 +1,1330 @@
+               PUBLIC  MXSETFONT
+               PUBLIC  MXSETTEXTCOLOR
+               PUBLIC  MXOUTCHAR
+               PUBLIC  MXOUTTEXT
+               PUBLIC  MXSETTEXTSTEP
+               PUBLIC  MXGETTEXTSTEP
+               EXTRN   MX_CODESEGMENT:BYTE
+               EXTRN   MXPUTIMAGE:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+; Default 8x8 font
+fnt_Default     LABEL  BYTE
+        INCLUDE DEFAULT.FNT
+
+; Table of system fonts
+tbl_SystemFont   LABEL   WORD
+        DW      fnt_Default, 8, 8
+
+MX_MAXSYSFONT   EQU     ($-OFFSET tbl_SystemFont) SHR 2
+
+mx_FontPtr      DW      OFFSET fnt_Default, SEG MX_TEXT
+mx_FontWidth    DW      8               ; Font width in pixels
+mx_FontHeight   DW      8               ; Font height in pixels
+mx_FontCharSize DW      8               ; Size in bytes of a font character
+mx_FontColor    DW      00FFh           ; Color: foreground + background*256
+mx_FontOp       DW      0         ; Raster op
+mx_DeltaX       DW      8               ; Horizontal step
+mx_DeltaY       DW      0               ; Vertical step
+
+L$1:
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       ; The label referred to here is an undefined location
+       ;;;;ffff
+       ;jle            0xff8bh
+       movsw
+       and             word ptr -7e67H[di],7e7eH
+       call            bx
+       call            bx
+       out             0ffH,ax
+       jle             L$9
+;      ;????
+;      ;????
+;      ;????
+       jl              L$7
+       adc             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],bh
+L$2:
+       jl              L$2
+       jl              L$8
+       adc             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],bh
+       adc             byte ptr -2[si],dl
+       push            sp
+       adc             dh,bh
+       adc             byte ptr [bx+si],bh
+L$3:
+       jl              L$3
+L$4:
+       ;????
+       jl              L$5
+       inc             byte ptr [bx+si]
+       sbb             byte ptr [si],bh
+       jle             L$11
+       cmp             al,18H
+       add             bh,bh
+       out             0c3H,ax
+    DB 81H, 81H, 0c3H, 0e7H
+L$5:
+       inc             word ptr [bx+si]
+       cmp             al,66H
+       inc             dx
+       inc             dx
+    DB 66H, 3cH
+L$6:
+       add             bh,bh
+       ret
+       cwd
+       mov             bp,99bdH
+L$7:
+       ret
+       inc             word ptr [bx]
+       add             ax,word ptr [di]
+       ; The label referred to here is an undefined location
+       ;;;;;0ffff
+       ;;;;;js         0ffffffe1H
+    DB 84H
+L$8:
+       test            byte ptr 7cH[bx+si],bh
+       add             byte ptr 7c82H[bp+si],10H
+       cmp             byte ptr [bx+si],dl
+       sbb             al,10H
+       sbb             al,10H
+       adc             byte ptr [bx+si],dl
+       xor             byte ptr [bx+si],dh
+       and             bh,byte ptr ds:[2222H]
+       ;;;;;pushad
+       cwd
+       pop             dx
+       cmp             al,0e7H
+       out             3cH,ax
+       pop             dx
+       cwd
+       add             byte ptr [bx+si],dl
+       xor             byte ptr -10H[bx+si],dh
+L$9:
+       jo              L$10
+       adc             byte ptr [bx+si],al
+       add             al,0e0H
+       ;;;;lock loopnz L$6
+       adc             byte ptr [bx+si],38H
+       push            sp
+       adc             byte ptr [bx+si],dl
+       push            sp
+       cmp             byte ptr [bx+si],dl
+       dec             ax
+       dec             ax
+       dec             ax
+       dec             ax
+       dec             ax
+       add             byte ptr [bx+si],cl
+       jle             L$4
+       xchg            ax,dx
+       jb              L$10
+       adc             dl,byte ptr [bp+si]
+       add             byte ptr [si],bh
+       and             bl,byte ptr [bx+si]
+       and             al,24H
+       sbb             byte ptr 3cH[si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+    DB 0, 3eH
+    ;;;;DD     ds:[03eh]
+L$10:
+       add             byte ptr [bx+si],bh
+       push            sp
+    DB 10H
+L$11:
+       adc             byte ptr [bx+si],dl
+       push            sp
+       cmp             dh,bh
+       add             byte ptr [bx+si],dl
+       cmp             byte ptr 10H[si],dl
+       adc             byte ptr [bx+si],dl
+       add             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr 38H[si],dl
+       adc             byte ptr [bx+si],al
+       add             byte ptr [bx+si],cl
+       add             al,0feH
+       add             al,8
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],ah
+       inc             ax
+       inc             byte ptr 20H[bx+si]
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr -380H[bx+si],0
+       add             byte ptr [bx+si],al
+       and             al,42H
+       inc             word ptr 24H[bp+si]
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],bh
+L$12:
+       jl              L$12
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       ;????
+       jl              L$15
+       adc             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       add             byte ptr [bx+si],dl
+       add             byte ptr [bx+si],al
+       and             al,24H
+       add             byte ptr [bx+si],al
+    DB 0
+L$13:
+       add             byte ptr [bx+si],al
+       and             al,24H
+       ;;;;jle         140H
+       ;;;;jle         142H
+L$14:
+       and             al,0
+       cmp             byte ptr 50H[si],dl
+       cmp             byte ptr [si],dl
+       push            sp
+       cmp             byte ptr [bx+si],dl
+       add             byte ptr [bp+si],al
+       inc             sp
+       or              byte ptr [bx+si],dl
+       and             byte ptr [bp+si],al
+       cmp             byte ptr 38H[si],al
+       ;;;;pusha
+       xchg            ax,sp
+L$15:
+    DB 88H
+L$16:
+       ;;;;je          138H
+       and             byte ptr [bx+si],ah
+       inc             ax
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],dl
+       and             byte ptr 40H[bx+si],al
+       inc             ax
+       and             byte ptr [bx+si],dl
+       add             byte ptr 20H[bx+si],al
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],ah
+L$17:
+       inc             ax
+       add             byte ptr [bx+si],al
+       and             al,18H
+       jle             L$18
+       and             al,0
+       add             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],dl
+       jl              L$18
+       adc             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],dl
+       and             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       cld
+    DB 0
+L$18:
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],dl
+       add             byte ptr [bx+si],al
+       add             al,8
+       adc             byte ptr [bx+si],ah
+       inc             ax
+L$19:
+       add             byte ptr [bx+si],7cH
+       ;????
+    DB 8aH, 92H
+L$20:
+       mov             byte ptr tbl_SystemFont[bx+2],al
+    DD L$21
+L$21:
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],bh
+       add             byte ptr L$13[bx+si],bh
+       add             al,18H
+       ;;;;pusha
+       cmp             ah,0
+       js              L$14
+       add             al,38H
+       add             al,84H
+       js              L$22
+L$22:
+       sbb             al,24H
+       inc             sp
+       test            dh,bh
+       add             al,0eH
+       add             ah,bh
+       cmp             al,4
+       add             al,84H
+       js              L$23
+L$23:
+       js              L$16
+       cmp             al,84H
+       test            byte ptr [bx+si],bh
+       cld
+       add             al,4
+       or              byte ptr [bx+si],dl
+       and             byte ptr [bx+si],ah
+       add             byte ptr -7cH[bx+si],bh
+       test            byte ptr -7cH[bx+si],bh
+       test            byte ptr [bx+si],bh
+       js              L$17
+       test            byte ptr 4[si],bh
+       test            byte ptr [bx+si],bh
+       add             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],al
+       add             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],ah
+       or              byte ptr [bx+si],dl
+       and             byte ptr 20H[bx+si],al
+       adc             byte ptr [bx+si],cl
+       add             byte ptr [bx+si],al
+       add             ah,bh
+       add             byte ptr [bx+si],al
+       cld
+       add             byte ptr [bx+si],al
+       inc             ax
+       and             byte ptr [bx+si],dl
+       or              byte ptr [bx+si],dl
+       and             byte ptr [bx+si],al
+       js              L$19
+       add             al,8
+       adc             byte ptr [bx+si],al
+L$24:
+       adc             byte ptr [bx+si],al
+       jl              L$20
+       mov             dx,0bea6H
+       cmp             byte ptr [si],78H
+       test            byte ptr -7b04H[si],al
+       test            byte ptr -800H[si],al
+       test            byte ptr -7b08H[si],al
+       test            al,bh
+       add             byte ptr -7cH[bx+si],bh
+       add             byte ptr -7b80H[bx+si],78H
+       add             al,dh
+       mov             byte ptr -7b7cH[si],al
+       mov             al,dh
+       add             ah,bh
+       add             byte ptr -7f10H[bx+si],80H
+       cld
+       add             ah,bh
+       add             byte ptr -7f10H[bx+si],80H
+       add             byte ptr [bx+si],78H
+       test            byte ptr -7b64H[bx+si],al
+       test            byte ptr [bx+si],bh
+       test            byte ptr -37cH[si],al
+       test            byte ptr 84H[si],al
+       cmp             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       cmp             byte ptr [bx+si],al
+       sbb             al,8
+       or              byte ptr [bx+si],cl
+       mov             byte ptr 70H[bx+si],cl
+       test            byte ptr -1f70H[bx+si],cl
+       nop
+       mov             byte ptr -8000H[si],al
+       add             byte ptr -7f80H[bx+si],80H
+       cld
+       add             dh,al
+       stosb
+       xchg            ax,dx
+       add             byte ptr -7d7eH[bp+si],0
+       add             dl,0a2H
+       xchg            ax,dx
+       mov             al,byte ptr 82H[bp]
+       js              L$24
+       test            byte ptr -7b7cH[si],al
+       js              L$25
+L$25:
+       clc
+       test            byte ptr -7f08H[si],al
+       add             byte ptr 7800H[bx+si],84H
+       test            byte ptr -776cH[si],al
+       jbe             L$26
+L$26:
+       clc
+       test            byte ptr -6f08H[si],al
+       mov             byte ptr 7800H[si],al
+       test            byte ptr 478H[bx+si],al
+       test            byte ptr [bx+si],bh
+       ;????
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       add             byte ptr -7b7cH[si],al
+       test            byte ptr 7884H[si],al
+       add             byte ptr -7b7cH[si],al
+       test            byte ptr 3048H[si],al
+       add             byte ptr -7d7eH[bp+si],al
+       adc             byte ptr -3956H[bp+si],0
+       add             byte ptr 28H[si],10H
+       sub             byte ptr -7eH[si],al
+       add             byte ptr 44H[si],al
+       inc             sp
+       cmp             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       add             dh,bh
+       add             al,8
+       adc             byte ptr [bx+si],ah
+       inc             ax
+       inc             byte ptr [bx+si]
+       js              L$32
+       inc             ax
+       inc             ax
+       inc             ax
+       inc             ax
+       js              L$27
+L$27:
+       add             byte ptr 2040H[bx+si],al
+       adc             byte ptr [bx+si],cl
+       add             al,0
+       js              L$29
+       or              byte ptr [bx+si],cl
+       or              byte ptr [bx+si],cl
+       js              L$28
+L$28:
+       adc             byte ptr [bx+si],ch
+L$29:
+       inc             sp
+       add             byte ptr [bx+si],0
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             bh,bh
+       and             byte ptr [bx+si],ah
+       adc             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       cmp             byte ptr [si],al
+       cmp             al,44H
+       jl              L$30
+L$30:
+       add             byte ptr 40H[bx+si],al
+       js              L$33
+       inc             sp
+       js              L$31
+L$31:
+       add             byte ptr [bx+si],al
+L$32:
+       cmp             al,40H
+       inc             ax
+       inc             ax
+       cmp             al,0
+       add             byte ptr [si],al
+       add             al,3cH
+       inc             sp
+       inc             sp
+       cmp             al,0
+       add             byte ptr [bx+si],al
+       cmp             byte ptr 7cH[si],al
+       inc             ax
+       cmp             al,0
+       add             byte ptr [si],cl
+       adc             byte ptr [si],bh
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       cmp             al,44H
+       inc             sp
+       cmp             al,4
+       cmp             byte ptr [bx+si],al
+       inc             ax
+       inc             ax
+       js              L$35
+       inc             sp
+       inc             sp
+       add             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       add             byte ptr [bx+si],al
+       add             al,0
+       add             al,4
+       add             al,44H
+       cmp             byte ptr [bx+si],al
+L$33:
+       inc             ax
+       inc             ax
+       push            ax
+       ;;;;pusha
+       push            ax
+       dec             ax
+       add             byte ptr [bx+si],al
+       xor             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       add             byte ptr [bx+si],al
+       add             byte ptr 54H[bx+si],ch
+       push            sp
+       inc             sp
+       inc             sp
+       add             byte ptr [bx+si],al
+       add             byte ptr 44H[bx+si],bh
+       inc             sp
+       inc             sp
+       inc             sp
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],bh
+       inc             sp
+       inc             sp
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+L$34:
+       js              L$42
+       inc             sp
+       js              L$41
+       inc             ax
+    DB 0
+L$35:
+       add             byte ptr [si],bh
+       inc             sp
+       inc             sp
+       cmp             al,4
+       add             al,0
+       add             byte ptr 60H[si],bl
+       inc             ax
+       inc             ax
+       inc             ax
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],bh
+L$36:
+       inc             ax
+       jl              L$38
+       jl              L$37
+L$37:
+       add             byte ptr [bx+si],dl
+L$38:
+       cmp             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       sbb             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       inc             sp
+       inc             sp
+       inc             sp
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       inc             sp
+       inc             sp
+       inc             sp
+       sub             byte ptr [bx+si],dl
+       add             byte ptr [bx+si],al
+       add             byte ptr 44H[si],al
+L$39:
+       push            sp
+       push            sp
+       ;;;;insb
+       add             byte ptr [bx+si],al
+       add             byte ptr 28H[si],al
+L$40:
+       adc             byte ptr [bx+si],ch
+       inc             sp
+L$41:
+    DB 0
+L$42:
+       add             byte ptr [bx+si],al
+       inc             sp
+       inc             sp
+       inc             sp
+       cmp             al,4
+       jl              L$43
+L$43:
+       add             byte ptr 4[si],bh
+       cmp             byte ptr 7cH[bx+si],al
+       add             byte ptr [bx+si],al
+       or              byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dh
+       adc             byte ptr [bx+si],dl
+       or              byte ptr [bx+si],al
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],al
+       and             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],bl
+       adc             byte ptr [bx+si],dl
+       and             byte ptr -68H[si],ah
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],dl
+       sub             byte ptr -7eH[si],al
+       cmp             dh,0
+       jl              L$34
+       add             byte ptr 7c80H[bx+si],4
+       jl              L$44
+L$44:
+       sub             byte ptr [bx+si],al
+       inc             sp
+       inc             sp
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       cmp             al,0
+       jl              L$54
+       jl              L$53
+       jl              L$45
+L$45:
+       jle             L$36
+       cmp             byte ptr [si],al
+       cmp             al,44H
+       jl              L$46
+L$46:
+       and             al,0
+L$47:
+       cmp             byte ptr [si],al
+       cmp             al,44H
+       jl              L$48
+L$48:
+       js              L$49
+L$49:
+       cmp             byte ptr [si],al
+       cmp             al,44H
+       jl              L$50
+L$50:
+       sbb             byte ptr [bx+si],bl
+       cmp             byte ptr [si],al
+       cmp             al,44H
+       jl              L$51
+L$51:
+       add             byte ptr [bx+si],al
+       js              L$39
+       cmp             byte ptr 8[bx+si],38H
+       jl              L$40
+       cmp             byte ptr 7cH[si],al
+       inc             ax
+       cmp             al,0
+       dec             ax
+       add             byte ptr [bx+si],bh
+       inc             sp
+       jl              L$55
+       cmp             al,0
+       js              L$52
+L$52:
+       cmp             byte ptr 7cH[si],al
+       inc             ax
+L$53:
+       cmp             al,0
+L$54:
+       add             byte ptr [bx+si],ch
+       add             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],ch
+       add             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],al
+       add             byte ptr [bx+si],dh
+       add             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],al
+       dec             ax
+       add             byte ptr -7cH[bx+si],bh
+       cld
+       test            byte ptr 3000H[si],al
+       xor             byte ptr -7cH[bx+si],bh
+       cld
+       test            byte ptr 3800H[si],al
+       add             ah,bh
+       xor             al,80H
+       cld
+       add             byte ptr [bx+si],al
+       add             byte ptr 8[bp],bh
+       jle             L$59
+L$55:
+       jle             L$56
+L$56:
+       jle             L$47
+       nop
+       cld
+       nop
+       nop
+       sahf
+       add             byte ptr -7eH[si],bh
+       cmp             byte ptr 44H[si],al
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       sub             byte ptr [bx+si],al
+       cmp             byte ptr 44H[si],al
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       jo              L$57
+L$57:
+       cmp             byte ptr 44H[si],al
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       cmp             byte ptr [si],al
+       inc             sp
+       inc             sp
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       jo              L$58
+L$58:
+       inc             sp
+       inc             sp
+       inc             sp
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       sub             byte ptr [bx+si],al
+       inc             sp
+       inc             sp
+       inc             sp
+       cmp             al,4
+       jl              L$64
+       add             byte ptr -7cH[bx+si],bh
+       test            byte ptr 78H[si],al
+       dec             ax
+       add             byte ptr -7b7cH[si],al
+    DB 84H
+L$59:
+       ;;;;js          4d8H
+       add             byte ptr [bx+si],dl
+       cmp             byte ptr 40H[bx+si],al
+       inc             ax
+       cmp             byte ptr [bx+si],dl
+       cmp             byte ptr 40H[si],al
+       loopnz          L$66
+       inc             ax
+       cmp             ah,44H
+       jl              L$60
+       jl              L$61
+       jl              L$62
+       add             al,dh
+       mov             byte ptr -7d09H[bp+si],cl
+       add             byte ptr 0c00H[bp+si],12H
+    DB 10H
+L$60:
+       sbb             byte ptr [bx+si],dh
+L$61:
+    DB 10H, 90H
+L$62:
+       ;;;;pusha
+       cmp             al,0
+       cmp             byte ptr [si],al
+       cmp             al,44H
+       jl              L$63
+L$63:
+       add             byte ptr [bx+si],bl
+       add             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],al
+    DB 1cH
+L$64:
+       add             byte ptr [bx+si],bh
+       inc             sp
+       inc             sp
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       sbb             al,0
+       inc             sp
+       inc             sp
+       inc             sp
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       jl              L$65
+L$65:
+       js              L$67
+       inc             sp
+L$66:
+       inc             sp
+       inc             sp
+       add             byte ptr [si],bh
+       inc             sp
+       push            sp
+       dec             sp
+       inc             sp
+       add             byte ptr [bx+si],bl
+       and             al,24H
+       push            ds
+       add             byte ptr ds:[0],bh
+       sbb             al,22H
+       and             bl,byte ptr [si]
+       add             byte ptr ds:[0],bh
+       adc             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],ah
+       inc             ax
+       inc             dx
+       cmp             al,0
+       add             byte ptr [bx+si],al
+       add             ah,bh
+       add             byte ptr [bx+si],0
+       add             byte ptr [bx+si],al
+       cld
+       add             al,4
+       add             byte ptr [bx+si],al
+       inc             ax
+       inc             sp
+       dec             ax
+       push            di
+       and             word ptr 4[bx],ax
+       pop             es
+       inc             ax
+       inc             sp
+       dec             ax
+       push            dx
+       dec             dx
+       pop             ds
+    DB 2
+L$67:
+       adc             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+L$68:
+       adc             byte ptr [bx+si],al
+       add             byte ptr [si],ah
+L$69:
+       dec             ax
+       nop
+       dec             ax
+       and             al,0
+       add             byte ptr [bx+si],al
+       dec             ax
+       and             al,12H
+       and             al,48H
+       add             byte ptr [bx+si],al
+       and             cl,byte ptr -77deH[bx+si]
+       and             cl,byte ptr -77deH[bx+si]
+       push            bp
+       stosb
+       push            bp
+       stosb
+       push            bp
+       stosb
+       push            bp
+       stosb
+       ;????
+       ja              L$68
+       out             dx,al
+       ;????
+       ja              L$69
+       out             dx,al
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       clc
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             al,bh
+       sbb             al,bh
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr ds:[3636H],dh
+       div             byte ptr ss:[3636H]
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       ;????
+       add             byte ptr ss:[bx+si],al
+       clc
+       sbb             al,bh
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr ds:[0f636H],dh
+       push            es
+       div             byte ptr ds:[3636H]
+       add             byte ptr ss:[bx+si],al
+       inc             byte ptr ds:[36f6H]
+       test            byte ptr ss:[0feH],0
+       add             byte ptr ds:[3636H],dh
+       inc             byte ptr ss:[bx+si]
+       add             byte ptr [bx+si],al
+       sbb             byte ptr [bx+si],bl
+       clc
+       sbb             al,bh
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             al,bh
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx],bl
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             bh,bh
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             bh,bh
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             bh,bh
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             bh,bh
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx],bl
+       sbb             byte ptr [bx],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr ds:[3636H],dh
+       aaa
+       aaa
+       xor             byte ptr [bx],bh
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx],bh
+       xor             byte ptr [bx],dh
+       test            word ptr ss:[bx+si],0ffH
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       inc             word ptr [bx+si]
+       div             word ptr ds:[3636H]
+       aaa
+       xor             byte ptr [bx],dh
+       add             byte ptr ss:[bx+si],al
+       inc             word ptr [bx+si]
+       inc             word ptr [bx+si]
+       add             byte ptr [bx+si],al
+       test            word ptr ss:[bx+si],36f7H
+       sbb             byte ptr ss:[bx+si],bl
+       inc             word ptr [bx+si]
+       inc             word ptr [bx+si]
+       add             byte ptr [bx+si],al
+       inc             word ptr ss:[bx+si]
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       inc             word ptr [bx+si]
+       call            dword ptr [bx+si]
+       sbb             byte ptr [bx+si],bl
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       push            word ptr ds:[3636H]
+       aas
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],bl
+       sbb             byte ptr [bx],bl
+       sbb             byte ptr [bx],bl
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx],bl
+       sbb             byte ptr [bx],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx],bh
+       push            word ptr ss:[3636H]
+       sbb             byte ptr [bx+si],bl
+       call            dword ptr [bx+si]
+       call            dword ptr [bx+si]
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       clc
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx],bl
+    DB 18H
+L$70:
+       sbb             byte ptr [bx+si],bl
+       ;????
+       ;????
+       ;????
+       ;????
+       ;????
+       ;????
+       ;????
+       inc             word ptr [bx+si]
+       add             byte ptr [bx+si],al
+       add             bh,bh
+       ;????
+       ;????
+       push            ax
+       ;????
+       ;????
+       ;????
+       ;????
+       ;????
+       ;????
+       ;????
+       ;????
+       ;????
+       ;????
+       ;????
+       ;????
+       ;????
+       ;????
+       ;????
+       ;????
+       ;????
+       ;????
+       inc             word ptr [bx+si]
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr -6cH[bp+si],ah
+       mov             byte ptr 62H[si],dl
+       add             al,dh
+       mov             al,dh
+       mov             byte ptr -7f10H[bx+si],cl
+       add             al,bh
+       mov             byte ptr -7f80H[bx+si],al
+       add             byte ptr [bx+si],0
+       cld
+       dec             ax
+       dec             ax
+       dec             ax
+       dec             ax
+       dec             ax
+       add             ah,bh
+       test            byte ptr 20H[bx+si],al
+       inc             ax
+       test            ah,bh
+       add             byte ptr [si],bh
+       inc             ax
+       cmp             byte ptr 44H[si],al
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       inc             sp
+       inc             sp
+       inc             sp
+       js              L$71
+       inc             ax
+       add             byte ptr ds:[848H],dh
+       or              byte ptr [bx+si],cl
+       or              byte ptr [bx+si],al
+       cmp             byte ptr [bx+si],dl
+       cmp             byte ptr 44H[si],al
+       cmp             byte ptr [bx+si],dl
+       cmp             byte ptr -7cH[bx+si],bh
+       test            ah,bh
+       test            byte ptr 78H[si],al
+       js              L$70
+       test            byte ptr 4848H[si],al
+       int             3
+       add             byte ptr 4[bx+si],bh
+       cmp             byte ptr 44H[si],al
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       ;;;;insb
+       xchg            ax,dx
+       xchg            ax,dx
+       ;;;;insb
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       cmp             al,byte ptr 5aH[si]
+       and             bl,byte ptr [si]
+       sbb             byte ptr [bx+si],ah
+       inc             ax
+       js              L$73
+       and             byte ptr [bx+si],bl
+L$71:
+       add             byte ptr -7cH[bx+si],bh
+       test            byte ptr -7b7cH[si],al
+       test            byte ptr [bx+si],al
+       add             ah,bh
+       add             ah,bh
+       add             ah,bh
+       add             byte ptr [bx+si],al
+       and             byte ptr [bx+si],ah
+       clc
+       and             byte ptr [bx+si],ah
+       add             al,bh
+       add             byte ptr [bx+si],ah
+       adc             byte ptr [bx+si],cl
+       adc             byte ptr [bx+si],ah
+       add             byte ptr [si],bh
+       or              byte ptr [bx+si],dl
+       and             byte ptr [bx+si],dl
+       or              byte ptr [bx+si],al
+       jl              L$72
+L$72:
+       or              al,12H
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       nop
+       ;;;;pusha
+       add             byte ptr [bx+si],dl
+       add             byte ptr [si],bh
+L$73:
+       adc             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       xor             cl,byte ptr [si]
+       xor             cl,byte ptr [si]
+       add             byte ptr [bx+si],bh
+       inc             sp
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       sbb             byte ptr [bx+si],bl
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],bl
+       add             byte ptr [bx+si],al
+       add             byte ptr ds:[808H],cl
+       or              byte ptr 28H[bx+si],cl
+       sbb             byte ptr [bx+si],cl
+       cmp             byte ptr [si],ah
+       and             al,24H
+       and             al,0
+       add             byte ptr [bx+si],al
+       cmp             al,4
+       cmp             al,20H
+       cmp             al,0
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       cmp             al,3cH
+       cmp             al,3cH
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+L$74:
+    DW offset L$1
+L$75:
+    DB 8
+L$76:
+       add             byte ptr [bx+si],cl
+    DB 0
+L$77:
+    DW offset L$1
+L$78:
+    DW seg L$1
+L$79:
+       or              byte ptr [bx+si],al
+L$80:
+       or              byte ptr [bx+si],al
+L$81:
+       or              byte ptr [bx+si],al
+L$82:
+       inc             word ptr [bx+si]
+L$83:
+       add             byte ptr [bx+si],al
+L$84:
+       or              byte ptr [bx+si],al
+L$85:
+       add             byte ptr [bx+si],al
+MXSETFONT:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       mov             ax,word ptr 0cH[bp]
+       test            ax,ax
+       jne             L$87
+       mov             ax,word ptr 0aH[bp]
+       cmp             ax,1
+       jb              L$86
+       xor             ax,ax
+L$86:
+       shl             ax,1
+       shl             ax,1
+       mov             bx,ax
+       mov             ax,word ptr L$74[bx]
+       mov             word ptr L$77,ax
+       mov             word ptr L$78,cs
+       mov             al,byte ptr L$75[bx]
+       xor             ah,ah
+       mov             word ptr L$79,ax
+       mov             word ptr L$84,ax
+       mov             dl,byte ptr L$76[bx]
+       xor             dh,dh
+       mov             word ptr L$80,dx
+       mul             dx
+       mov             word ptr L$81,ax
+       mov             word ptr L$84,ax
+       xor             ax,ax
+       mov             word ptr L$85,ax
+       jmp             L$88
+L$87:
+       mov             ax,0ffffH
+       mov             bx,word ptr 8[bp]
+       cmp             bx,10H
+       ja              L$88
+       mov             dx,word ptr 6[bp]
+       cmp             dx,20H
+       ja              L$88
+       mov             word ptr L$79,bx
+       mov             word ptr L$80,dx
+       mov             ax,bx
+       add             ax,7
+       shr             ax,1
+       shr             ax,1
+       shr             ax,1
+       mul             dx
+       mov             word ptr L$81,ax
+       mov             ax,word ptr 0aH[bp]
+       mov             word ptr L$77,ax
+       mov             ax,word ptr 0cH[bp]
+       mov             word ptr L$78,ax
+       xor             ax,ax
+L$88:
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+MXSETTEXTCOLOR:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       mov             ax,word ptr 8[bp]
+       mov             word ptr L$82,ax
+       mov             ax,word ptr 6[bp]
+       mov             word ptr L$83,ax
+       xor             ax,ax
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            4
+MXOUTCHAR:
+       push            bp
+       mov             bp,sp
+       sub             sp,202H
+       push            ds
+       push            si
+       push            es
+       push            di
+       lds             si,dword ptr cs:L$77
+       mov             al,byte ptr 6[bp]
+       xor             ah,ah
+       mul             word ptr cs:L$81
+       add             si,ax
+       mov             ax,ss
+       mov             es,ax
+       lea             di,-200H[bp]
+       mov             dx,word ptr cs:L$82
+       mov             ax,word ptr cs:L$80
+       mov             word ptr -202H[bp],ax
+L$89:
+       mov             cx,word ptr cs:L$79
+       mov             bh,byte ptr [si]
+       inc             si
+       cmp             cx,8
+       jbe             L$90
+       mov             bl,byte ptr [si]
+       inc             si
+L$90:
+       mov             al,dl
+       shl             bx,1
+       jb              L$91
+       mov             al,dh
+L$91:
+       mov             byte ptr es:[di],al
+       inc             di
+       dec             cx
+       jne             L$90
+       dec             word ptr -202H[bp]
+       jne             L$89
+       lea             ax,-200H[bp]
+       push            es
+       push            ax
+       push            word ptr 0aH[bp]
+       push            word ptr 8[bp]
+       push            word ptr cs:L$79
+       push            word ptr cs:L$80
+       push            word ptr cs:L$83
+       push            cs
+       call            near ptr MX_TEXT:MXPUTIMAGE
+       xor             ax,ax
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            6
+MXOUTTEXT:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       lds             si,dword ptr 6[bp]
+L$92:
+       mov             al,byte ptr [si]
+       test            al,al
+       je              L$93
+       inc             si
+       push            word ptr 0cH[bp]
+       push            word ptr 0aH[bp]
+       push            ax
+       push            cs
+       call            near ptr MXOUTCHAR
+       mov             ax,word ptr cs:L$84
+       add             word ptr 0cH[bp],ax
+       mov             ax,word ptr cs:L$85
+       add             word ptr 0aH[bp],ax
+       dec             word ptr -202H[bp]
+       jne             L$92
+L$93:
+       xor             ax,ax
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+       retf
+MXSETTEXTSTEP:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       mov             ax,word ptr 8[bp]
+       mov             word ptr L$84,ax
+       mov             ax,word ptr 6[bp]
+       mov             word ptr L$85,ax
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            4
+MXGETTEXTSTEP:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       mov             ax,word ptr cs:L$84
+       lds             si,dword ptr 0aH[bp]
+       mov             word ptr [si],ax
+       mov             ax,word ptr cs:L$85
+       lds             si,dword ptr 6[bp]
+       mov             word ptr [si],ax
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxot_.asm b/16/xw_/mxot_.asm
new file mode 100755 (executable)
index 0000000..e431b13
--- /dev/null
@@ -0,0 +1,333 @@
+;-----------------------------------------------------------\r
+;\r
+; MXOT.ASM - Text functions\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+;WARN    PRO\r
+;NOWARN  RES                             ; We use the reserved name 'WIDTH'\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxOutChar\r
+PUBLIC  mxOutText\r
+PUBLIC  mxSetFont\r
+PUBLIC  mxSetTextColor\r
+PUBLIC  mxGetTextStep\r
+PUBLIC  mxSetTextStep\r
+\r
+MAX_WIDTH       EQU     16              ; Must be <= 16\r
+MAX_HEIGHT      EQU     32\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_CodeSegment  : WORD\r
+EXTRN   mxPutImage      : FAR\r
+\r
+; Default 8x8 font\r
+fnt_Default     LABEL  BYTE\r
+        INCLUDE DEFAULT.FNT\r
+\r
+; Table of system fonts\r
+tbl_SystemFont   LABEL   WORD\r
+        DW      fnt_Default, 8, 8\r
+\r
+MX_MAXSYSFONT   EQU     ($-OFFSET tbl_SystemFont) SHR 2\r
+\r
+mx_FontPtr      DW      OFFSET fnt_Default, SEG MX_TEXT\r
+mx_FontWidth    DW      8               ; Font width in pixels\r
+mx_FontHeight   DW      8               ; Font height in pixels\r
+mx_FontCharSize DW      8               ; Size in bytes of a font character\r
+mx_FontColor    DW      00FFh           ; Color: foreground + background*256\r
+mx_FontOp       DW      OP_MOVE         ; Raster op\r
+mx_DeltaX       DW      8               ; Horizontal step\r
+mx_DeltaY       DW      0               ; Vertical step\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the current font.\r
+;\r
+; Input:\r
+;       Font    = pointer to font data\r
+;       Width   = width of font character in pixels\r
+;       Height  = height of font character in pixels\r
+; Output:\r
+;       AX = 0 on success, else invalid parameters\r
+;\r
+; Note: when the high word of Font (i.e. the segment) is zero, the low\r
+;       word is used to select one of the system fonts.\r
+;\r
+mxSetFont       PROC FAR\r
+       push            bp\r
+       mov             bp,sp\r
+       sub             sp,0\r
+       push            ds\r
+        .enter  0\r
+        .push   ds\r
+\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, WORD PTR Font[2]    ; Get font segment\r
+        test    ax, ax                  ; Null segment?\r
+        jnz     @@UserFont              ; No, install user font\r
+\r
+; Install system font\r
+        mov     ax, WORD PTR Font[0]    ; Get font number\r
+        cmp     ax, MX_MAXSYSFONT       ; Check range\r
+        jb      @@SystemFont\r
+        xor     ax, ax                  ; Out of range, use default font\r
+@@SystemFont:\r
+        shl     ax, 1\r
+        shl     ax, 1\r
+        mov     bx, ax\r
+        mov     ax, tbl_SystemFont[bx]  ; Get font offset\r
+        mov     WORD PTR mx_FontPtr[0], ax\r
+        mov     WORD PTR mx_FontPtr[2], cs\r
+        mov     al, BYTE PTR tbl_SystemFont[bx+2]\r
+        xor     ah, ah\r
+        mov     [mx_FontWidth], ax\r
+        mov     [mx_DeltaX], ax\r
+        mov     dl, BYTE PTR tbl_SystemFont[bx+3]\r
+        xor     dh, dh\r
+        mov     [mx_FontHeight], dx\r
+        mul     dx\r
+        mov     [mx_FontCharSize], ax\r
+        mov     [mx_DeltaX], ax\r
+        xor     ax, ax\r
+        mov     [mx_DeltaY], ax\r
+        jmp     @@Exit\r
+\r
+; Install user font\r
+@@UserFont:\r
+        mov     ax, -1                  ; Assume an error\r
+        mov     bx, [bp+8]\r
+        cmp     bx, MAX_WIDTH\r
+        ja      @@Exit                  ; Invalid character width\r
+        mov     dx, [bp+4]\r
+        cmp     dx, MAX_HEIGHT\r
+        ja      @@Exit                  ; Invalid character height\r
+        mov     [mx_FontWidth], bx\r
+        mov     [mx_FontHeight], dx\r
+        mov     ax, bx\r
+        add     ax, 7\r
+        shr    ax, 1\r
+        shr    ax, 1\r
+       shr    ax, 1\r
+        mul     dx\r
+        mov     [mx_FontCharSize], ax\r
+        mov     ax, WORD PTR Font[0]\r
+        mov     WORD PTR mx_FontPtr[0], ax\r
+        mov     ax, WORD PTR Font[2]\r
+        mov     WORD PTR mx_FontPtr[2], ax\r
+        xor     ax, ax\r
+\r
+@@Exit:\r
+        .pop    ds\r
+        ASSUME  ds:NOTHING\r
+        ;.leave  ARG_SIZE\r
+mxSetFont       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the text color and raster op.\r
+;\r
+; Input:\r
+;       Color   = text color (foreground + background*256)\r
+;       Op      = raster op\r
+; Output:\r
+;       none\r
+;\r
+mxSetTextColor  PROC FAR\r
+        ARG     Op:WORD,        \\r
+                Color:WORD      = ARG_SIZE\r
+        .enter  0\r
+        .push   ds\r
+\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, [Color]\r
+        mov     [mx_FontColor], ax\r
+        mov     ax, [Op]\r
+        mov     [mx_FontOp], ax\r
+\r
+        xor     ax, ax\r
+        .pop    ds\r
+        ASSUME  ds:NOTHING\r
+        .leave  ARG_SIZE\r
+mxSetTextColor  ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a character using the current font and attributes.\r
+;\r
+; Input:\r
+;       X, Y    = video coordinates\r
+;       C       = character to print\r
+; Output:\r
+;       none\r
+;\r
+mxOutChar       PROC FAR\r
+        ARG     C:BYTE:2,       \\r
+                Y:WORD,         \\r
+                X:WORD          = ARG_SIZE\r
+        LOCAL   Image:BYTE:MAX_WIDTH*MAX_HEIGHT,        \\r
+                Count:WORD                              = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+        ASSUME  ds:NOTHING\r
+\r
+; Gets the pointer to font data for the selected character\r
+        lds     si, DWORD PTR [mx_FontPtr]\r
+        mov     al, [C]\r
+        xor     ah, ah\r
+        mul     [mx_FontCharSize]       ; Offset into font\r
+        add     si, ax                  ; DS:SI -> font data for character\r
+\r
+; Converts font data into a 256-color linear image\r
+        mov     ax, ss\r
+        mov     es, ax\r
+        lea     di, [Image]\r
+        mov     dx, [mx_FontColor]\r
+        mov     ax, [mx_FontHeight]\r
+        mov     [Count], ax\r
+@@HeightLoop:\r
+        mov     cx, [mx_FontWidth]\r
+        mov     bh, ds:[si]\r
+        inc     si                      ; Get a byte from font data\r
+        cmp     cx, 8\r
+        jbe     @@WidthLoop             ; Ok for width <= 8\r
+        mov     bl, ds:[si]             ; Get another byte\r
+        inc     si\r
+@@WidthLoop:\r
+        mov     al, dl                  ; Assume foreground color\r
+        shl     bx, 1                   ; Is font bit set?\r
+        jc      @@1                     ; Yes, foreground is just great\r
+        mov     al, dh                  ; Get background color\r
+@@1:\r
+        mov     es:[di], al             ; Put pixel into image\r
+        inc     di\r
+        dec     cx\r
+        jnz     @@WidthLoop\r
+        dec     [Count]\r
+        jnz     @@HeightLoop\r
+\r
+; Now pass image to mx_PutImage\r
+        lea     ax, [Image]\r
+        push    es\r
+        push    ax                      ; Pointer to image\r
+        push    [X]\r
+        push    [Y]                     ; Image coordinates\r
+        push    [mx_FontWidth]\r
+        push    [mx_FontHeight]         ; Image size\r
+        push    [mx_FontOp]             ; Raster op\r
+        call    mxPutImage              ; Write character\r
+\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxOutChar       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a string at the coordinates specified.\r
+;\r
+; Input:\r
+;       X, Y    = text coordinates\r
+;       S       = pointer to ASCIIZ string\r
+; Output:\r
+;       none\r
+;\r
+mxOutText       PROC FAR\r
+        ARG     S:DWORD,        \\r
+                Y:WORD,         \\r
+                X:WORD          = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+        ASSUME  ds:NOTHING\r
+\r
+        lds     si, [S]\r
+@@Loop:\r
+        mov     al, ds:[si]\r
+        test    al, al                  ; End of string?\r
+        jz      @@Exit                  ; Yes, exit\r
+        inc     si\r
+        push    [X]                     ; Display character\r
+        push    [Y]\r
+        push    ax\r
+        call    mxOutChar\r
+        mov     ax, [mx_DeltaX]\r
+        add     [X], ax                 ; Bump X coordinate\r
+        mov     ax, [mx_DeltaY]\r
+        add     [Y], ax                 ; Bump Y coordinate\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+        ret\r
+mxOutText       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the distance between characters.\r
+;\r
+; Input:\r
+;       DeltaX  = horizontal distance in pixels\r
+;       DeltaY  = vertical distance in pixels\r
+; Output:\r
+;       none\r
+;\r
+; Note: this function may be used to set the text direction.\r
+;\r
+mxSetTextStep   PROC FAR\r
+        ARG     DeltaY:WORD,    \\r
+                DeltaX:WORD     = ARG_SIZE\r
+        .enter  0\r
+        .push   ds\r
+\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, [DeltaX]\r
+        mov     [mx_DeltaX], ax\r
+        mov     ax, [DeltaY]\r
+        mov     [mx_DeltaY], ax\r
+\r
+        .pop    ds\r
+        .leave  ARG_SIZE\r
+mxSetTextStep   ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Gets the current distance between characters.\r
+;\r
+; Input:\r
+;       DeltaX  = pointer to horizontal distance in pixels (integer)\r
+;       DeltaY  = pointer to vertical distance in pixels (integer)\r
+; Output:\r
+;       none\r
+;\r
+mxGetTextStep   PROC FAR\r
+        ARG     DeltaY:DWORD,   \\r
+                DeltaX:DWORD    = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+        ASSUME  ds:NOTHING\r
+\r
+        mov     ax, [mx_DeltaX]\r
+        lds     si, [DeltaX]\r
+        mov     ds:[si], ax\r
+        mov     ax, [mx_DeltaY]\r
+        lds     si, [DeltaY]\r
+        mov     ds:[si], ax\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetTextStep   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw_/mxpb.asm b/16/xw_/mxpb.asm
new file mode 100755 (executable)
index 0000000..b8536fd
--- /dev/null
@@ -0,0 +1,4102 @@
+               PUBLIC  MX_SCANBUFFER
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MX_SCANBUFFER:
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxpf.asm b/16/xw_/mxpf.asm
new file mode 100755 (executable)
index 0000000..f33158b
--- /dev/null
@@ -0,0 +1,327 @@
+               PUBLIC  MXFILLPOLY
+               EXTRN   MX_CLIPX1:BYTE
+               EXTRN   MX_CLIPX2:BYTE
+               EXTRN   MX_CLIPY1:BYTE
+               EXTRN   MX_CLIPY2:BYTE
+               EXTRN   MX_CODESEGMENT:BYTE
+               EXTRN   MX_SCANBUFFER:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+               EXTRN   MX_BYTESPERLINE:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+       mov             cx,word ptr [si]
+       sub             cx,word ptr [bx]
+       jg              L$2
+       ret
+L$2:
+       push            bp
+       mov             ax,word ptr 2[si]
+       mov             bx,word ptr 2[bx]
+       sub             ax,bx
+       jg              L$4
+       jl              L$6
+       mov             ax,bx
+L$3:
+       mov             word ptr es:[di],ax
+       add             di,4
+       dec             cx
+       jne             L$3
+       jmp             L$8
+L$4:
+       cwd
+       div             cx
+       mov             bp,ax
+       xor             ax,ax
+       div             cx
+       xchg            ax,bx
+       mov             dx,8000H
+L$5:
+       mov             word ptr es:[di],ax
+       add             di,4
+       add             dx,bx
+       adc             ax,bp
+       dec             cx
+       jne             L$5
+       jmp             L$8
+L$6:
+       neg             ax
+       cwd
+       div             cx
+       mov             bp,ax
+       xor             ax,ax
+       div             cx
+       xchg            ax,bx
+       mov             dx,8000H
+L$7:
+       mov             word ptr es:[di],ax
+       add             di,4
+       sub             dx,bx
+       sbb             ax,bp
+       dec             cx
+       jne             L$7
+L$8:
+       pop             bp
+       ret
+MXFILLPOLY:
+       push            bp
+       mov             bp,sp
+       sub             sp,1eH
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             cx,word ptr 10H[bp]
+       cmp             cx,3
+       jae             L$9
+       jmp             near ptr L$36
+L$9:
+       les             di,dword ptr 0cH[bp]
+       lds             si,dword ptr 8[bp]
+       mov             word ptr -16H[bp],7fffH
+       mov             word ptr -1aH[bp],8000H
+       mov             word ptr -18H[bp],7fffH
+       mov             word ptr -1eH[bp],8000H
+       xor             dx,dx
+L$10:
+       mov             bx,word ptr es:[di]
+       shl             bx,1
+       shl             bx,1
+       add             bx,si
+       mov             ax,word ptr [bx]
+       cmp             ax,word ptr -16H[bp]
+       jge             L$11
+       mov             word ptr -16H[bp],ax
+       mov             word ptr -0eH[bp],dx
+       mov             word ptr -10H[bp],dx
+L$11:
+       cmp             ax,word ptr -1aH[bp]
+       jle             L$12
+       mov             word ptr -1aH[bp],ax
+       mov             word ptr -12H[bp],dx
+L$12:
+       mov             ax,word ptr 2[bx]
+       cmp             ax,word ptr -18H[bp]
+       jge             L$13
+       mov             word ptr -18H[bp],ax
+L$13:
+       cmp             ax,word ptr -1eH[bp]
+       jle             L$14
+       mov             word ptr -1eH[bp],ax
+L$14:
+       inc             di
+       inc             dx
+       inc             di
+       inc             dx
+       dec             cx
+       jne             L$10
+       mov             ax,word ptr -1aH[bp]
+       cmp             ax,word ptr cs:MX_CLIPX1
+       jge             L$15
+       jmp             near ptr L$36
+L$15:
+       mov             bx,word ptr -16H[bp]
+       cmp             bx,word ptr cs:MX_CLIPX2
+       jle             L$16
+       jmp             near ptr L$36
+L$16:
+       sub             ax,bx
+       jg              L$17
+       jmp             near ptr L$36
+L$17:
+       mov             ax,word ptr -1eH[bp]
+       cmp             ax,word ptr cs:MX_CLIPY1
+       jge             L$18
+       jmp             near ptr L$36
+L$18:
+       mov             bx,word ptr -18H[bp]
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jle             L$19
+       jmp             near ptr L$36
+L$19:
+       sub             ax,bx
+       jg              L$20
+       jmp             near ptr L$36
+L$20:
+       dec             word ptr 10H[bp]
+       shl             word ptr 10H[bp],1
+       mov             es,word ptr cs:MX_CODESEGMENT
+       mov             ax,offset MX_TEXT:MX_SCANBUFFER
+       mov             word ptr -4[bp],ax
+       mov             si,word ptr -0eH[bp]
+L$21:
+       lds             bx,dword ptr 0cH[bp]
+       mov             di,word ptr [bx+si]
+       dec             si
+       dec             si
+       test            si,si
+       jge             L$22
+       mov             si,word ptr 10H[bp]
+L$22:
+       mov             word ptr -0eH[bp],si
+       mov             si,word ptr [bx+si]
+       shl             di,1
+       shl             di,1
+       shl             si,1
+       shl             si,1
+       lds             bx,dword ptr 8[bp]
+       add             si,bx
+       add             bx,di
+       mov             di,word ptr -4[bp]
+       call            near ptr L$1
+       mov             word ptr -4[bp],di
+       mov             si,word ptr -0eH[bp]
+       cmp             si,word ptr -12H[bp]
+       jne             L$21
+       mov             ax,offset MX_TEXT:MX_SCANBUFFER+2
+       mov             word ptr -6[bp],ax
+       mov             si,word ptr -10H[bp]
+L$23:
+       lds             bx,dword ptr 0cH[bp]
+       mov             di,word ptr [bx+si]
+       inc             si
+       inc             si
+       cmp             si,word ptr 10H[bp]
+       jbe             L$24
+       xor             si,si
+L$24:
+       mov             word ptr -10H[bp],si
+       mov             si,word ptr [bx+si]
+       shl             di,1
+       shl             di,1
+       shl             si,1
+       shl             si,1
+       lds             bx,dword ptr 8[bp]
+       add             si,bx
+       add             bx,di
+       mov             di,word ptr -6[bp]
+       call            near ptr L$1
+       mov             word ptr -6[bp],di
+       mov             si,word ptr -10H[bp]
+       cmp             si,word ptr -12H[bp]
+       jne             L$23
+       mov             si,offset MX_TEXT:MX_SCANBUFFER
+       mov             ax,word ptr -16H[bp]
+       mov             cx,word ptr -1aH[bp]
+       sub             cx,ax
+       mov             bx,word ptr cs:MX_CLIPX1
+       sub             bx,ax
+       jle             L$25
+       sub             cx,bx
+       add             ax,bx
+       mov             word ptr -16H[bp],ax
+       shl             bx,1
+       shl             bx,1
+       add             si,bx
+L$25:
+       mov             bx,ax
+       add             bx,cx
+       sub             bx,word ptr cs:MX_CLIPX2
+       jle             L$26
+       sub             cx,bx
+L$26:
+       test            cx,cx
+       jg              L$27
+       jmp             near ptr L$36
+L$27:
+       mov             word ptr -8[bp],cx
+       mov             word ptr -4[bp],si
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       mov             ax,word ptr -18H[bp]
+       cmp             ax,word ptr cs:MX_CLIPY1
+       jl              L$28
+       mov             ax,word ptr -1eH[bp]
+       cmp             ax,word ptr cs:MX_CLIPY2
+       jg              L$28
+       jmp             L$32
+L$28:
+       mov             di,cx
+       inc             di
+       sub             si,4
+L$29:
+       dec             di
+       je              L$32
+       add             si,4
+       mov             ax,word ptr [si]
+       mov             cx,word ptr 2[si]
+       mov             dx,word ptr cs:MX_CLIPY2
+       cmp             ax,dx
+       jg              L$31
+       cmp             cx,dx
+       jle             L$30
+       mov             word ptr 2[si],dx
+       mov             bx,cx
+       sub             bx,dx
+       sub             cx,ax
+       jle             L$31
+       mov             cx,word ptr 2[si]
+L$30:
+       mov             dx,word ptr cs:MX_CLIPY1
+       cmp             cx,dx
+       jl              L$31
+       sub             cx,ax
+       jle             L$31
+       cmp             ax,dx
+       jge             L$29
+       mov             word ptr [si],dx
+       sub             dx,ax
+       cmp             cx,dx
+       ja              L$29
+L$31:
+       mov             word ptr [si],0ffffH
+       jmp             L$29
+L$32:
+       mov             es,word ptr cs:MX_VIDEOSEGMENT
+       mov             si,word ptr -4[bp]
+       mov             cl,byte ptr -16H[bp]
+       and             cl,3
+       mov             al,11H
+       shl             al,cl
+       mov             byte ptr -2[bp],al
+       shr             word ptr -16H[bp],1
+       shr             word ptr -16H[bp],1
+L$33:
+       mov             ax,word ptr [si]
+       test            ax,ax
+       js              L$35
+       mov             cx,word ptr 2[si]
+       sub             cx,ax
+       jle             L$35
+       mul             word ptr cs:MX_BYTESPERLINE
+       add             ax,word ptr -16H[bp]
+       mov             di,ax
+       mov             ah,byte ptr -2[bp]
+       mov             dx,3c4H
+       mov             al,2
+       out             dx,ax
+       mov             ax,word ptr 6[bp]
+       mov             dx,word ptr cs:MX_BYTESPERLINE
+       shr             cx,1
+       jae             L$34
+       mov             byte ptr es:[di],al
+       add             di,dx
+       jcxz            L$35
+L$34:
+       mov             byte ptr es:[di],al
+       add             di,dx
+       mov             byte ptr es:[di],al
+       add             di,dx
+       dec             cx
+       jne             L$34
+L$35:
+       rol             byte ptr -2[bp],1
+       adc             word ptr -16H[bp],0
+       add             si,4
+       dec             word ptr -8[bp]
+       jne             L$33
+L$36:
+       xor             ax,ax
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0cH
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxpg.asm b/16/xw_/mxpg.asm
new file mode 100755 (executable)
index 0000000..d252576
--- /dev/null
@@ -0,0 +1,457 @@
+               PUBLIC  MXGOURAUDPOLY
+               EXTRN   MX_BYTESPERLINE:BYTE
+               EXTRN   MX_CLIPX1:BYTE
+               EXTRN   MX_CLIPX2:BYTE
+               EXTRN   MX_CLIPY1:BYTE
+               EXTRN   MX_CLIPY2:BYTE
+               EXTRN   MX_CODESEGMENT:BYTE
+               EXTRN   MX_SCANBUFFER:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+       mov             cx,word ptr [si]
+       sub             cx,word ptr [bx]
+       jg              L$2
+       ret
+L$2:
+       push            bp
+       push            di
+       push            cx
+       push            ax
+       push            dx
+       mov             ax,word ptr 2[si]
+       mov             bx,word ptr 2[bx]
+       sub             ax,bx
+       jg              L$4
+       jl              L$6
+       mov             ax,bx
+L$3:
+       mov             word ptr es:[di],ax
+       add             di,8
+       dec             cx
+       jne             L$3
+       jmp             L$8
+L$4:
+       cwd
+       div             cx
+       mov             bp,ax
+       xor             ax,ax
+       div             cx
+       xchg            ax,bx
+       mov             dx,8000H
+L$5:
+       mov             word ptr es:[di],ax
+       add             di,8
+       add             dx,bx
+       adc             ax,bp
+       dec             cx
+       jne             L$5
+       jmp             L$8
+L$6:
+       neg             ax
+       cwd
+       div             cx
+       mov             bp,ax
+       xor             ax,ax
+       div             cx
+       xchg            ax,bx
+       mov             dx,8000H
+L$7:
+       mov             word ptr es:[di],ax
+       add             di,8
+       sub             dx,bx
+       sbb             ax,bp
+       dec             cx
+       jne             L$7
+L$8:
+       pop             bx
+       pop             ax
+       pop             cx
+       pop             di
+       sub             ax,bx
+       jg              L$10
+       jl              L$12
+       mov             ah,bl
+       mov             al,80H
+L$9:
+       mov             word ptr es:2[di],ax
+       add             di,8
+       dec             cx
+       jne             L$9
+       jmp             L$14
+L$10:
+       cwd
+       div             cx
+       mov             bp,ax
+       xor             ax,ax
+       div             cx
+       xchg            ax,bx
+       mov             dx,8000H
+L$11:
+       mov             byte ptr es:3[di],al
+       mov             byte ptr es:2[di],dh
+       add             di,8
+       add             dx,bx
+       adc             ax,bp
+       dec             cx
+       jne             L$11
+       jmp             L$14
+L$12:
+       neg             ax
+       cwd
+       div             cx
+       mov             bp,ax
+       xor             ax,ax
+       div             cx
+       xchg            ax,bx
+       mov             dx,8000H
+L$13:
+       mov             byte ptr es:3[di],al
+       mov             byte ptr es:2[di],dh
+       add             di,8
+       sub             dx,bx
+       sbb             ax,bp
+       dec             cx
+       jne             L$13
+L$14:
+       pop             bp
+       ret
+L$15:
+       mov             ax,word ptr 6[si]
+       mov             bx,word ptr 2[si]
+       cmp             ah,bh
+       jg              L$17
+       jl              L$19
+       add             ax,dx
+       mov             dx,word ptr cs:MX_BYTESPERLINE
+L$16:
+       mov             byte ptr es:[di],ah
+       add             di,dx
+       dec             cx
+       jne             L$16
+       ret
+L$17:
+       push            bp
+       push            si
+       mov             si,bx
+       add             si,dx
+       sub             ax,bx
+       xor             dx,dx
+       div             cx
+       mov             bp,ax
+       xor             ax,ax
+       div             cx
+       mov             bx,ax
+       mov             dx,8000H
+       mov             ax,word ptr cs:MX_BYTESPERLINE
+       xchg            ax,si
+L$18:
+       mov             byte ptr es:[di],ah
+       add             dx,bx
+       adc             ax,bp
+       add             di,si
+       dec             cx
+       jne             L$18
+       pop             si
+       pop             bp
+       ret
+L$19:
+       push            bp
+       push            si
+       mov             si,bx
+       add             si,dx
+       sub             ax,bx
+       neg             ax
+       xor             dx,dx
+       div             cx
+       mov             bp,ax
+       xor             ax,ax
+       div             cx
+       mov             bx,ax
+       mov             dx,8000H
+       mov             ax,word ptr cs:MX_BYTESPERLINE
+       xchg            ax,si
+L$20:
+       mov             byte ptr es:[di],ah
+       sub             dx,bx
+       sbb             ax,bp
+       add             di,si
+       dec             cx
+       jne             L$20
+       pop             si
+       pop             bp
+       ret
+MXGOURAUDPOLY:
+       push            bp
+       mov             bp,sp
+       sub             sp,1eH
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             cx,word ptr 14H[bp]
+       cmp             cx,3
+       jae             L$21
+       jmp             near ptr L$47
+L$21:
+       les             di,dword ptr 10H[bp]
+       lds             si,dword ptr 0cH[bp]
+       mov             word ptr -16H[bp],7fffH
+       mov             word ptr -1aH[bp],8000H
+       mov             word ptr -18H[bp],7fffH
+       mov             word ptr -1eH[bp],8000H
+       xor             dx,dx
+L$22:
+       mov             bx,word ptr es:[di]
+       shl             bx,1
+       shl             bx,1
+       add             bx,si
+       mov             ax,word ptr [bx]
+       cmp             ax,word ptr -16H[bp]
+       jge             L$23
+       mov             word ptr -16H[bp],ax
+       mov             word ptr -0eH[bp],dx
+       mov             word ptr -10H[bp],dx
+L$23:
+       cmp             ax,word ptr -1aH[bp]
+       jle             L$24
+       mov             word ptr -1aH[bp],ax
+       mov             word ptr -12H[bp],dx
+L$24:
+       mov             ax,word ptr 2[bx]
+       cmp             ax,word ptr -18H[bp]
+       jge             L$25
+       mov             word ptr -18H[bp],ax
+L$25:
+       cmp             ax,word ptr -1eH[bp]
+       jle             L$26
+       mov             word ptr -1eH[bp],ax
+L$26:
+       inc             di
+       inc             di
+       inc             dx
+       inc             dx
+       dec             cx
+       jne             L$22
+       mov             ax,word ptr -1aH[bp]
+       cmp             ax,word ptr cs:MX_CLIPX1
+       jge             L$27
+       jmp             near ptr L$47
+L$27:
+       mov             bx,word ptr -16H[bp]
+       cmp             bx,word ptr cs:MX_CLIPX2
+       jle             L$28
+       jmp             near ptr L$47
+L$28:
+       sub             ax,bx
+       jg              L$29
+       jmp             near ptr L$47
+L$29:
+       mov             ax,word ptr -1eH[bp]
+       cmp             ax,word ptr cs:MX_CLIPY1
+       jge             L$30
+       jmp             near ptr L$47
+L$30:
+       mov             bx,word ptr -18H[bp]
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jle             L$31
+       jmp             near ptr L$47
+L$31:
+       sub             ax,bx
+       jg              L$32
+       jmp             near ptr L$47
+L$32:
+       dec             word ptr 14H[bp]
+       shl             word ptr 14H[bp],1
+       mov             es,word ptr cs:MX_CODESEGMENT
+       mov             ax,offset MX_TEXT:MX_SCANBUFFER
+       mov             word ptr -4[bp],ax
+       mov             si,word ptr -0eH[bp]
+L$33:
+       lds             bx,dword ptr 10H[bp]
+       mov             di,word ptr [bx+si]
+       dec             si
+       dec             si
+       test            si,si
+       jge             L$34
+       mov             si,word ptr 14H[bp]
+L$34:
+       mov             word ptr -0eH[bp],si
+       mov             si,word ptr [bx+si]
+       lds             bx,dword ptr 8[bp]
+       shl             di,1
+       shl             si,1
+       mov             ax,word ptr [bx+si]
+       mov             dx,word ptr [bx+di]
+       lds             bx,dword ptr 0cH[bp]
+       shl             si,1
+       shl             di,1
+       add             si,bx
+       add             bx,di
+       mov             di,word ptr -4[bp]
+       call            near ptr L$1
+       mov             word ptr -4[bp],di
+       mov             si,word ptr -0eH[bp]
+       cmp             si,word ptr -12H[bp]
+       jne             L$33
+       mov             ax,offset MX_TEXT:MX_SCANBUFFER+4
+       mov             word ptr -6[bp],ax
+       mov             si,word ptr -10H[bp]
+L$35:
+       lds             bx,dword ptr 10H[bp]
+       mov             di,word ptr [bx+si]
+       inc             si
+       inc             si
+       cmp             si,word ptr 14H[bp]
+       jbe             L$36
+       xor             si,si
+L$36:
+       mov             word ptr -10H[bp],si
+       mov             si,word ptr [bx+si]
+       lds             bx,dword ptr 8[bp]
+       shl             di,1
+       shl             si,1
+       mov             ax,word ptr [bx+si]
+       mov             dx,word ptr [bx+di]
+       lds             bx,dword ptr 0cH[bp]
+       shl             si,1
+       shl             di,1
+       add             si,bx
+       add             bx,di
+       mov             di,word ptr -6[bp]
+       call            near ptr L$1
+       mov             word ptr -6[bp],di
+       mov             si,word ptr -10H[bp]
+       cmp             si,word ptr -12H[bp]
+       jne             L$35
+       mov             si,offset MX_TEXT:MX_SCANBUFFER
+       mov             ax,word ptr -16H[bp]
+       mov             cx,word ptr -1aH[bp]
+       sub             cx,ax
+       mov             bx,word ptr cs:MX_CLIPX1
+       sub             bx,ax
+       jle             L$37
+       sub             cx,bx
+       add             ax,bx
+       mov             word ptr -16H[bp],ax
+       shl             bx,1
+       shl             bx,1
+       shl             bx,1
+       add             si,bx
+L$37:
+       mov             bx,ax
+       add             bx,cx
+       sub             bx,word ptr cs:MX_CLIPX2
+       jle             L$38
+       sub             cx,bx
+L$38:
+       test            cx,cx
+       jg              L$39
+       jmp             near ptr L$47
+L$39:
+       mov             word ptr -8[bp],cx
+       mov             word ptr -4[bp],si
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       mov             ax,word ptr -18H[bp]
+       cmp             ax,word ptr cs:MX_CLIPY1
+       jl              L$40
+       mov             ax,word ptr -1eH[bp]
+       cmp             ax,word ptr cs:MX_CLIPY2
+       jg              L$40
+       jmp             L$44
+L$40:
+       mov             di,cx
+       inc             di
+       sub             si,8
+L$41:
+       dec             di
+       je              L$44
+       add             si,8
+       mov             ax,word ptr [si]
+       mov             cx,word ptr 4[si]
+       mov             dx,word ptr cs:MX_CLIPY2
+       cmp             ax,dx
+       jg              L$43
+       cmp             cx,dx
+       jle             L$42
+       mov             word ptr 4[si],dx
+       mov             bx,cx
+       sub             bx,dx
+       sub             cx,ax
+       jle             L$43
+       mov             ax,word ptr 2[si]
+       sub             ax,word ptr 6[si]
+       imul            bx
+       idiv            cx
+       add             word ptr 6[si],ax
+       mov             ax,word ptr [si]
+       mov             cx,word ptr 4[si]
+L$42:
+       mov             dx,word ptr cs:MX_CLIPY1
+       cmp             cx,dx
+       jl              L$43
+       sub             cx,ax
+       jle             L$43
+       cmp             ax,dx
+       jge             L$41
+       mov             word ptr [si],dx
+       sub             dx,ax
+       cmp             cx,dx
+       jbe             L$43
+       mov             ax,word ptr 6[si]
+       sub             ax,word ptr 2[si]
+       imul            dx
+       idiv            cx
+       add             word ptr 2[si],ax
+       jmp             L$41
+L$43:
+       mov             word ptr [si],0ffffH
+       jmp             L$41
+L$44:
+       mov             es,word ptr cs:MX_VIDEOSEGMENT
+       mov             si,word ptr -4[bp]
+       mov             cl,byte ptr -16H[bp]
+       and             cl,3
+       mov             al,11H
+       shl             al,cl
+       mov             byte ptr -2[bp],al
+       shr             word ptr -16H[bp],1
+       shr             word ptr -16H[bp],1
+       mov             ax,word ptr 6[bp]
+       mov             ah,al
+       xor             al,al
+       mov             word ptr 6[bp],ax
+L$45:
+       mov             ax,word ptr [si]
+       test            ax,ax
+       js              L$46
+       mov             cx,word ptr 4[si]
+       sub             cx,ax
+       jle             L$46
+       mul             word ptr cs:MX_BYTESPERLINE
+       add             ax,word ptr -16H[bp]
+       mov             di,ax
+       mov             ah,byte ptr -2[bp]
+       mov             al,2
+       mov             dx,3c4H
+       out             dx,ax
+       mov             dx,word ptr 6[bp]
+       call            near ptr L$15
+L$46:
+       rol             byte ptr -2[bp],1
+       adc             word ptr -16H[bp],0
+       add             si,8
+       dec             word ptr -8[bp]
+       jne             L$45
+L$47:
+       xor             ax,ax
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            10H
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxpi.asm b/16/xw_/mxpi.asm
new file mode 100755 (executable)
index 0000000..2631d82
--- /dev/null
@@ -0,0 +1,218 @@
+               PUBLIC  MXPUTIMAGE
+               EXTRN   SUBCLIPIMAGE:BYTE
+               EXTRN   MX_BYTESPERLINE:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+    DW offset L$2
+    DW offset L$6
+    DW offset L$10
+    DW offset L$14
+    DW offset L$18
+    DW offset L$20
+L$2:
+       shr             cx,1
+       jb              L$5
+L$3:
+       movsb
+       add             si,3
+       movsb
+       add             si,3
+       dec             cx
+       jne             L$3
+L$4:
+       ret
+L$5:
+       movsb
+       add             si,3
+       jcxz            L$4
+       jmp             L$3
+L$6:
+       shr             cx,1
+       jb              L$9
+L$7:
+       mov             al,byte ptr [si]
+       mov             ah,byte ptr 4[si]
+       and             word ptr es:[di],ax
+       inc             di
+       inc             di
+       add             si,8
+       dec             cx
+       jne             L$7
+L$8:
+       ret
+L$9:
+       lodsb
+       and             byte ptr es:[di],al
+       inc             di
+       add             si,3
+       jcxz            L$8
+       jmp             L$7
+L$10:
+       shr             cx,1
+       jb              L$13
+L$11:
+       mov             al,byte ptr [si]
+       mov             ah,byte ptr 4[si]
+       or              word ptr es:[di],ax
+       inc             di
+       inc             di
+       add             si,8
+       dec             cx
+       jne             L$11
+L$12:
+       ret
+L$13:
+       lodsb
+       or              byte ptr es:[di],al
+       inc             di
+       add             si,3
+       jcxz            L$12
+       jmp             L$11
+L$14:
+       shr             cx,1
+       jb              L$17
+L$15:
+       mov             al,byte ptr [si]
+       mov             ah,byte ptr 4[si]
+       xor             word ptr es:[di],ax
+       inc             di
+       inc             di
+       add             si,8
+       dec             cx
+       jne             L$15
+L$16:
+       ret
+L$17:
+       lodsb
+       xor             byte ptr es:[di],al
+       inc             di
+       add             si,3
+       jcxz            L$16
+       jmp             L$15
+L$18:
+       mov             al,byte ptr [si]
+       cmp             al,ah
+       je              L$19
+       mov             byte ptr es:[di],al
+L$19:
+       inc             di
+       add             si,4
+       dec             cx
+       jne             L$18
+       ret
+L$20:
+       mov             al,byte ptr [si]
+       add             byte ptr es:[di],al
+       inc             di
+       add             si,4
+       dec             cx
+       jne             L$20
+       ret
+MXPUTIMAGE:
+       push            bp
+       mov             bp,sp
+       sub             sp,14H
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             bx,word ptr 0eH[bp]
+       mov             ax,word ptr 0cH[bp]
+       mov             cx,word ptr 0aH[bp]
+       mov             dx,word ptr 8[bp]
+       call            near ptr MX_TEXT:SUBCLIPIMAGE
+       jae             L$21
+       jmp             near ptr L$26
+L$21:
+       mov             word ptr 8[bp],dx
+       add             word ptr 10H[bp],si
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             di,bx
+       shr             di,1
+       shr             di,1
+       add             di,ax
+       mov             word ptr -0aH[bp],di
+       mov             es,word ptr cs:MX_VIDEOSEGMENT
+       and             bl,3
+       mov             byte ptr -10H[bp],bl
+       mov             bx,cx
+       shr             bx,1
+       shr             bx,1
+       and             cl,3
+       mov             al,8
+       shr             al,cl
+       mov             si,6
+L$22:
+       mov             word ptr -8[bp+si],bx
+       shr             al,1
+       adc             bx,0
+       dec             si
+       dec             si
+       jge             L$22
+       mov             cl,byte ptr -10H[bp]
+       mov             al,11H
+       shl             al,cl
+       mov             byte ptr -14H[bp],al
+       mov             bx,word ptr 6[bp]
+       mov             byte ptr -12H[bp],bh
+       xor             bh,bh
+       cmp             bl,5
+       jbe             L$23
+       xor             bl,bl
+L$23:
+       shl             bx,1
+       mov             ax,word ptr cs:L$1[bx]
+       mov             word ptr -0cH[bp],ax
+       cld
+       mov             byte ptr -0eH[bp],4
+       lea             bx,-8[bp]
+       mov             ds,word ptr 12H[bp]
+L$24:
+       cmp             word ptr ss:[bx],0
+       je              L$26
+       mov             si,word ptr 10H[bp]
+       mov             ah,byte ptr -14H[bp]
+       and             ah,0fH
+       mov             al,2
+       mov             dx,3c4H
+       out             dx,ax
+       mov             ah,byte ptr -10H[bp]
+       and             ah,3
+       mov             al,4
+       mov             dx,3ceH
+       out             dx,ax
+       mov             dx,word ptr 8[bp]
+       mov             di,word ptr -0aH[bp]
+L$25:
+       push            si
+       push            di
+       mov             cx,word ptr ss:[bx]
+       mov             ah,byte ptr -12H[bp]
+       call            word ptr -0cH[bp]
+       pop             di
+       pop             si
+       add             si,word ptr 0aH[bp]
+       add             di,word ptr cs:MX_BYTESPERLINE
+       dec             dx
+       jne             L$25
+       inc             bx
+       inc             bx
+       inc             byte ptr -10H[bp]
+       rol             byte ptr -14H[bp],1
+       adc             word ptr -0aH[bp],0
+       inc             word ptr 10H[bp]
+       dec             byte ptr -0eH[bp]
+       jne             L$24
+L$26:
+       xor             ax,ax
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0eH
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxpn.asm b/16/xw_/mxpn.asm
new file mode 100755 (executable)
index 0000000..e4f20b1
--- /dev/null
@@ -0,0 +1,34 @@
+               PUBLIC  MXPAN
+               EXTRN   MX_BYTESPERLINE:BYTE
+               EXTRN   MXWAITDISPLAY:BYTE
+               EXTRN   MXSTARTADDRESS:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXPAN:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       mov             ax,word ptr 6[bp]
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             dx,word ptr 8[bp]
+       shr             dx,1
+       shr             dx,1
+       add             ax,dx
+       push            ax
+       call            far ptr MXWAITDISPLAY
+       call            far ptr MXSTARTADDRESS
+       mov             dx,3daH
+       in              al,dx
+       mov             dx,3c0H
+       mov             al,33H
+       out             dx,al
+       mov             al,byte ptr 8[bp]
+       and             al,3
+       shl             al,1
+       out             dx,al
+       xor             ax,ax
+       mov             sp,bp
+       pop             bp
+       retf            4
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxpp.asm b/16/xw_/mxpp.asm
new file mode 100755 (executable)
index 0000000..42f7a6f
--- /dev/null
@@ -0,0 +1,84 @@
+               PUBLIC  MXGETPIXEL
+               PUBLIC  MXPUTPIXEL
+               EXTRN   MX_CLIPX1:BYTE
+               EXTRN   MX_CLIPX2:BYTE
+               EXTRN   MX_CLIPY1:BYTE
+               EXTRN   MX_CLIPY2:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+               EXTRN   MX_BYTESPERLINE:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXGETPIXEL:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       xor             ax,ax
+       mov             si,word ptr 8[bp]
+       cmp             si,word ptr cs:MX_CLIPX1
+       jl              L$1
+       cmp             si,word ptr cs:MX_CLIPX2
+       jg              L$1
+       mov             bx,word ptr 6[bp]
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jl              L$1
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jg              L$1
+       mov             al,4
+       mov             ah,byte ptr 8[bp]
+       and             ah,3
+       mov             dx,3ceH
+       out             dx,ax
+       mov             ds,word ptr cs:MX_VIDEOSEGMENT
+       mov             ax,bx
+       mul             word ptr cs:MX_BYTESPERLINE
+       shr             si,1
+       shr             si,1
+       add             si,ax
+       mov             al,byte ptr [si]
+       xor             ah,ah
+L$1:
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            4
+MXPUTPIXEL:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       mov             si,word ptr 0aH[bp]
+       cmp             si,word ptr cs:MX_CLIPX1
+       jl              L$2
+       cmp             si,word ptr cs:MX_CLIPX2
+       jg              L$2
+       mov             ax,word ptr 8[bp]
+       cmp             ax,word ptr cs:MX_CLIPY1
+       jl              L$2
+       cmp             ax,word ptr cs:MX_CLIPY2
+       jg              L$2
+       mov             ds,word ptr cs:MX_VIDEOSEGMENT
+       mul             word ptr cs:MX_BYTESPERLINE
+       shr             si,1
+       shr             si,1
+       add             si,ax
+       mov             cl,byte ptr 0aH[bp]
+       and             cl,3
+       mov             ax,102H
+       shl             ah,cl
+       mov             dx,3c4H
+       out             dx,ax
+       mov             al,byte ptr 6[bp]
+       mov             byte ptr [si],al
+L$2:
+       xor             ax,ax
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            6
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxra.asm b/16/xw_/mxra.asm
new file mode 100755 (executable)
index 0000000..a71b4a0
--- /dev/null
@@ -0,0 +1,17 @@
+               PUBLIC  MXROWADDRESS
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXROWADDRESS:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       mov             dx,3d4H
+       mov             al,13H
+       mov             ah,byte ptr 6[bp]
+       out             dx,ax
+       xor             ax,ax
+       mov             sp,bp
+       pop             bp
+       retf            2
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxrp.asm b/16/xw_/mxrp.asm
new file mode 100755 (executable)
index 0000000..03239ef
--- /dev/null
@@ -0,0 +1,72 @@
+               PUBLIC  MXROTATEPALETTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXROTATEPALETTE:
+       push            bp
+       mov             bp,sp
+       sub             sp,300H
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             bx,word ptr 8[bp]
+       add             bx,bx
+       add             bx,word ptr 8[bp]
+       lds             si,dword ptr 0aH[bp]
+       push            ss
+       pop             es
+       lea             di,-300H[bp]
+       cld
+       mov             ax,word ptr 6[bp]
+       mov             dx,ax
+       test            ax,ax
+       je              L$2
+       jl              L$1
+       add             ax,ax
+       add             dx,ax
+       sub             bx,dx
+       add             si,bx
+       push            si
+       mov             cx,dx
+       rep movsb
+       mov             es,word ptr 0cH[bp]
+       mov             di,si
+       dec             di
+       pop             si
+       dec             si
+       mov             cx,bx
+       std
+       rep movsb
+       push            ss
+       pop             ds
+       lea             si,-300H[bp]
+       les             di,dword ptr 0aH[bp]
+       mov             cx,dx
+       cld
+       rep movsb
+       jmp             L$2
+L$1:
+       add             ax,ax
+       add             dx,ax
+       neg             dx
+       sub             bx,dx
+       mov             cx,dx
+       rep movsb
+       les             di,dword ptr 0aH[bp]
+       mov             cx,bx
+       rep movsb
+       push            ss
+       pop             ds
+       lea             si,-300H[bp]
+       mov             cx,dx
+       rep movsb
+L$2:
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxsa.asm b/16/xw_/mxsa.asm
new file mode 100755 (executable)
index 0000000..642d2dd
--- /dev/null
@@ -0,0 +1,22 @@
+               PUBLIC  MXSTARTADDRESS
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXSTARTADDRESS:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       mov             bx,word ptr 6[bp]
+       mov             dx,3d4H
+       mov             al,0cH
+       mov             ah,bh
+       cli
+       out             dx,ax
+       mov             al,0dH
+       mov             ah,bl
+       out             dx,ax
+       sti
+       mov             sp,bp
+       pop             bp
+       retf            2
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxsc.asm b/16/xw_/mxsc.asm
new file mode 100755 (executable)
index 0000000..7d8bd47
--- /dev/null
@@ -0,0 +1,26 @@
+               PUBLIC  MXSETCOLOR
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXSETCOLOR:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       mov             ax,word ptr 0cH[bp]
+       mov             dx,3c8H
+       out             dx,al
+       inc             dx
+       mov             al,byte ptr 0aH[bp]
+       out             dx,al
+       mov             al,byte ptr 8[bp]
+       out             dx,al
+       mov             al,byte ptr 6[bp]
+       out             dx,al
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxsi.asm b/16/xw_/mxsi.asm
new file mode 100755 (executable)
index 0000000..c922353
--- /dev/null
@@ -0,0 +1,220 @@
+               PUBLIC  MXSTRETCHIMAGE
+               EXTRN   SUBCLIPBOX:BYTE
+               EXTRN   MX_BYTESPERLINE:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+    DW offset L$8
+    DW offset L$10
+    DW offset L$12
+    DW offset L$14
+    DW offset L$16
+    DW offset L$19
+MXSTRETCHIMAGE:
+       push            bp
+       mov             bp,sp
+       sub             sp,14H
+       push            ds
+       push            si
+       push            es
+       push            di
+       xor             dx,dx
+       mov             ax,word ptr 0eH[bp]
+       mov             bx,word ptr 0aH[bp]
+       div             bx
+       mov             word ptr -0aH[bp],ax
+       xor             ax,ax
+       div             bx
+       mov             word ptr -0cH[bp],ax
+       xor             dx,dx
+       mov             ax,word ptr 0cH[bp]
+       mov             bx,word ptr 8[bp]
+       div             bx
+       mov             word ptr -0eH[bp],ax
+       xor             ax,ax
+       div             bx
+       mov             word ptr -10H[bp],ax
+       mov             bx,word ptr 12H[bp]
+       mov             ax,word ptr 10H[bp]
+       mov             cx,word ptr 0aH[bp]
+       mov             dx,word ptr 8[bp]
+       call            near ptr MX_TEXT:SUBCLIPBOX
+       jae             L$2
+       jmp             near ptr L$7
+L$2:
+       mov             word ptr 0aH[bp],cx
+       mov             word ptr 8[bp],dx
+       sub             word ptr 12H[bp],bx
+       sub             word ptr 10H[bp],ax
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             di,bx
+       shr             di,1
+       shr             di,1
+       add             di,ax
+       mov             word ptr -2[bp],di
+       mov             es,word ptr cs:MX_VIDEOSEGMENT
+       and             bl,3
+       mov             byte ptr -6[bp],bl
+       mov             cl,bl
+       mov             al,11H
+       shl             al,cl
+       mov             byte ptr -14H[bp],al
+       mov             ax,word ptr 10H[bp]
+       test            ax,ax
+       je              L$3
+       mov             bx,ax
+       mul             word ptr -10H[bp]
+       mov             cx,dx
+       mov             ax,bx
+       mul             word ptr -0eH[bp]
+       add             ax,cx
+       mul             word ptr 0eH[bp]
+       add             word ptr 14H[bp],ax
+L$3:
+       mov             ax,word ptr 12H[bp]
+       test            ax,ax
+       je              L$4
+       mov             bx,ax
+       mul             word ptr -0cH[bp]
+       mov             cx,dx
+       mov             ax,bx
+       mul             word ptr -0aH[bp]
+       add             ax,cx
+       add             word ptr 14H[bp],ax
+L$4:
+       mov             ax,word ptr -0eH[bp]
+       mul             word ptr 0eH[bp]
+       mov             word ptr -0eH[bp],ax
+       mov             bx,word ptr 6[bp]
+       mov             byte ptr -8[bp],bh
+       xor             bh,bh
+       cmp             bl,5
+       jbe             L$5
+       xor             bl,bl
+L$5:
+       shl             bx,1
+       mov             ax,word ptr cs:L$1[bx]
+       mov             word ptr -4[bp],ax
+       mov             ds,word ptr 16H[bp]
+       xor             ax,ax
+       mov             word ptr -12H[bp],ax
+L$6:
+       mov             si,word ptr 14H[bp]
+       mov             ah,byte ptr -14H[bp]
+       and             ah,0fH
+       mov             al,2
+       mov             dx,3c4H
+       out             dx,ax
+       mov             ah,byte ptr -6[bp]
+       and             ah,3
+       mov             al,4
+       mov             dx,3ceH
+       out             dx,ax
+       mov             cx,word ptr 8[bp]
+       mov             di,word ptr -2[bp]
+       mov             ah,byte ptr -8[bp]
+       xor             bx,bx
+       mov             dx,word ptr cs:MX_BYTESPERLINE
+       call            word ptr -4[bp]
+       inc             byte ptr -6[bp]
+       rol             byte ptr -14H[bp],1
+       adc             word ptr -2[bp],0
+       mov             dx,word ptr -0cH[bp]
+       mov             ax,word ptr -0aH[bp]
+       add             word ptr -12H[bp],dx
+       adc             word ptr 14H[bp],ax
+       dec             word ptr 0aH[bp]
+       jne             L$6
+L$7:
+       xor             ax,ax
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            12H
+L$8:
+       mov             al,byte ptr [si]
+       mov             byte ptr es:[di],al
+       add             di,dx
+       dec             cx
+       je              L$9
+       add             si,word ptr -0eH[bp]
+       add             bx,word ptr -10H[bp]
+       jae             L$8
+       add             si,word ptr 0eH[bp]
+       jmp             L$8
+L$9:
+       ret
+L$10:
+       mov             al,byte ptr [si]
+       and             byte ptr es:[di],al
+       add             di,dx
+       dec             cx
+       je              L$11
+       add             si,word ptr -0eH[bp]
+       add             bx,word ptr -10H[bp]
+       jae             L$10
+       add             si,word ptr 0eH[bp]
+       jmp             L$10
+L$11:
+       ret
+L$12:
+       mov             al,byte ptr [si]
+       or              byte ptr es:[di],al
+       add             di,dx
+       dec             cx
+       je              L$13
+       add             si,word ptr -0eH[bp]
+       add             bx,word ptr -10H[bp]
+       jae             L$12
+       add             si,word ptr 0eH[bp]
+       jmp             L$12
+L$13:
+       ret
+L$14:
+       mov             al,byte ptr [si]
+       xor             byte ptr es:[di],al
+       add             di,dx
+       dec             cx
+       je              L$15
+       add             si,word ptr -0eH[bp]
+       add             bx,word ptr -10H[bp]
+       jae             L$14
+       add             si,word ptr 0eH[bp]
+       jmp             L$14
+L$15:
+       ret
+L$16:
+       mov             al,byte ptr [si]
+       cmp             al,ah
+       je              L$17
+       mov             byte ptr es:[di],al
+L$17:
+       add             di,dx
+       dec             cx
+       je              L$18
+       add             si,word ptr -0eH[bp]
+       add             bx,word ptr -10H[bp]
+       jae             L$16
+       add             si,word ptr 0eH[bp]
+       jmp             L$16
+L$18:
+       ret
+L$19:
+       mov             al,byte ptr [si]
+       add             byte ptr es:[di],al
+       add             di,dx
+       dec             cx
+       je              L$20
+       add             si,word ptr -0eH[bp]
+       add             bx,word ptr -10H[bp]
+       jae             L$19
+       add             si,word ptr 0eH[bp]
+       jmp             L$19
+L$20:
+       ret
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxsl.asm b/16/xw_/mxsl.asm
new file mode 100755 (executable)
index 0000000..109ce3b
--- /dev/null
@@ -0,0 +1,36 @@
+               PUBLIC  MXSTARTLINE
+               EXTRN   MX_BYTESPERLINE:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXSTARTLINE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       mov             ax,word ptr 6[bp]
+       mul             word ptr cs:MX_BYTESPERLINE
+       xchg            ax,bx
+       mov             dx,3daH
+L$1:
+       in              al,dx
+       test            al,8
+       jne             L$1
+       mov             dx,3d4H
+       mov             al,0cH
+       mov             ah,bh
+       cli
+       out             dx,ax
+       mov             al,0dH
+       mov             ah,bl
+       out             dx,ax
+       sti
+       mov             dx,3daH
+L$2:
+       in              al,dx
+       test            al,8
+       je              L$2
+       xor             ax,ax
+       mov             sp,bp
+       pop             bp
+       retf            2
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxsm.asm b/16/xw_/mxsm.asm
new file mode 100755 (executable)
index 0000000..96e746d
--- /dev/null
@@ -0,0 +1,449 @@
+               PUBLIC  MX_SCREENWIDTH
+               PUBLIC  MX_SCREENHEIGHT
+               PUBLIC  MX_BYTESPERLINE
+               PUBLIC  MXSETMODE
+               PUBLIC  MXCHANGEMODE
+               PUBLIC  MXGETASPECT
+               PUBLIC  MXGETSCREENSIZE
+               EXTRN   MX_CODESEGMENT:BYTE
+               EXTRN   MXSETSYSCLIPREGION:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MX_SCREENWIDTH:
+       add             byte ptr [bx+si],al
+MX_SCREENHEIGHT:
+       add             byte ptr [bx+si],al
+L$1:
+       add             byte ptr [bx+si],al
+L$2:
+       add             byte ptr [bx+si],al
+MX_BYTESPERLINE:
+       add             byte ptr [bx+si],al
+L$3:
+       or              word ptr 14H[bx+si],ax
+       add             byte ptr [bx],dl
+       jcxz            L$4
+L$4:
+    DB 0
+L$5:
+       or              word ptr 14H[bx+di],ax
+       add             byte ptr [bx],dl
+       jcxz            L$6
+L$6:
+    DB 0
+L$7:
+       add             byte ptr 1[bx],bl
+       dec             di
+       add             dl,byte ptr 3[bx+si]
+       add             byte ptr [si],54H
+       add             ax,1380H
+       sub             byte ptr [bx+si],al
+    DB 0
+L$8:
+       add             byte ptr 1[bp+di],ch
+       pop             cx
+       add             bl,byte ptr 3[bp+si]
+       mov             es,word ptr [si]
+       pop             si
+       add             ax,138aH
+       sub             ax,0
+       push            es
+       mov             di,1f07H
+       adc             byte ptr -7aefH[bp+di],al
+       adc             bl,byte ptr 15H[di]
+       arpl            word ptr ds:[0baH],dx
+    DB 0
+L$9:
+       push            es
+    DD ds:[7bfH]
+       pushf
+       adc             word ptr -70eeH[bp],cx
+       adc             ax,1696H
+       mov             cx,0
+L$10:
+       push            es
+       or              ax,3e07H
+       adc             dl,ch
+       adc             word ptr -20eeH[si],cx
+       adc             ax,16e7H
+       push            es
+       add             byte ptr [bx+si],al
+L$11:
+       add             byte ptr 1[si],dh
+       arpl            word ptr [bp+si],ax
+       add             dx,word ptr fs:6804H[bx]
+       add             ax,695H
+       xchg            byte ptr [bx],al
+       lock or         word ptr 0fH[bx+si],sp
+       xor             word ptr [bx+si],dx
+       pop             bx
+       adc             word ptr 5712H[di],cx
+       adc             si,word ptr [bp+si]
+       adc             al,0
+       adc             ax,1660H
+       adc             byte ptr [bx],0e3H
+       add             byte ptr [bx+si],al
+L$12:
+       arpl            word ptr ds:[500H],ax
+       add             byte ptr 1[bx+si],al
+       enter           1a00H,0
+    DW offset L$9
+    DW offset L$5
+       add             byte ptr [bx+si],al
+       xor             ax,word ptr [bp+di]
+L$13:
+       jcxz            L$14
+    DB 0
+L$14:
+       add             word ptr [bx+si],ax
+       inc             ax
+       add             ax,si
+       add             byte ptr [bp+si],bl
+       add             byte ptr [bp+si],bl
+    DW offset L$5
+       add             byte ptr [bx+si],al
+       xor             ax,word ptr [bp+di]
+L$15:
+       arpl            word ptr ds:[0a00H],ax
+       add             byte ptr 1[bx+si],al
+       nop
+       add             word ptr [bp+si],bx
+       add             byte ptr [bp+si],cl
+    DW offset L$3
+       add             byte ptr [bx+si],al
+       xor             ax,word ptr [bp+di]
+L$16:
+       jcxz            L$17
+    DB 0
+L$17:
+       add             al,byte ptr [bx+si]
+       inc             ax
+       add             ax,sp
+    DD L$18
+L$18:
+       add             byte ptr [bp+si],cl
+       add             byte ptr [bx+si],al
+       add             byte ptr [bp+di],dh
+    DB 3
+L$19:
+       sbb             ax,word ptr [eax]
+       adc             al,0
+       push            0c801H
+       add             byte ptr [bp+si],ch
+       add             byte ptr [bp+si],cl
+    DW offset L$5
+       add             byte ptr [bx+si],al
+       fadd            dword ptr [bp+si]
+L$20:
+       out             9,ax
+       add             byte ptr [bx+si],cl
+       add             byte ptr 1[bx+si],ch
+       lock add        byte ptr [bp+si],ch
+       add             byte ptr [bp+si],bl
+    DW offset L$5
+       add             byte ptr [bx+si],al
+       fadd            dword ptr [bp+si]
+L$21:
+       sbb             ax,word ptr [eax]
+       sub             byte ptr [bx+si],al
+       push            9001H
+       add             word ptr [bp+si],bp
+       add             byte ptr [bp+si],cl
+    DW offset L$3
+       add             byte ptr [bx+si],al
+       fadd            dword ptr [bp+si]
+L$22:
+       out             9,ax
+       add             byte ptr [bx+si],dl
+       add             byte ptr 1[bx+si],ch
+       loopnz          L$23
+    DW offset L$8
+L$23 equ $-1
+    DW offset L$10
+    DW offset L$3
+       add             byte ptr [bx+si],al
+       fadd            dword ptr [bp+si]
+L$24:
+       mov             word ptr ds:[0],ax
+       add             byte ptr [bx+si],al
+       inc             ax
+       add             word ptr 1a00H[bx],bp
+       add             byte ptr [bp+si],bh
+       add             byte ptr [bp+si],dl
+       add             byte ptr [bx+si],al
+       add             byte ptr [bp+di],dh
+    DB 3
+L$25:
+       mov             word ptr 0,ax
+       add             byte ptr [bx+si],al
+       inc             ax
+       add             word ptr 1a00H[bx],bp
+       add             byte ptr [bp+si],bh
+       add             byte ptr [bp+si],cl
+       add             byte ptr [bx+si],al
+       add             byte ptr [bp+di],dh
+    DB 3
+L$26:
+       cmpsw
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       push            0e001H
+       add             word ptr [bp+si],bp
+       add             byte ptr [bp+si],bh
+       add             byte ptr [bp+si],dl
+       add             byte ptr [bx+si],al
+       add             al,bl
+    DB 2
+L$27:
+       cmpsw
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       push            0e001H
+       add             word ptr [bp+si],bp
+       add             byte ptr [bp+si],bh
+       add             byte ptr [bp+si],cl
+       add             byte ptr [bx+si],al
+       add             al,bl
+    DB 2
+L$28:
+       out             1,ax
+       add             byte ptr [bp+si],al
+       add             byte ptr 5801H[bx+si],dl
+       add             ch,byte ptr [bp+si]
+       add             byte ptr [bx+si],al
+       pop             word ptr [bp+si]
+L$29:
+    DW offset L$24
+    DW offset L$12
+    DW offset L$13
+    DW offset L$25
+    DW offset L$15
+    DW offset L$16
+    DW offset L$26
+    DW offset L$19
+    DW offset L$20
+    DW offset L$27
+    DW offset L$21
+    DW offset L$22
+    DW offset L$28
+L$30:
+       mov             ax,3
+       int             10H
+       mov             word ptr MX_SCREENHEIGHT,0
+       mov             word ptr MX_BYTESPERLINE,0
+       ret
+MXSETMODE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       mov             si,word ptr 6[bp]
+       cmp             si,0dH
+       jbe             L$31
+       jmp             near ptr L$36
+L$31:
+       test            si,si
+       jne             L$32
+       call            near ptr L$30
+       jmp             near ptr L$36
+L$32:
+       dec             si
+       shl             si,1
+       mov             si,word ptr L$29[si]
+       cld
+       push            si
+       mov             ax,13H
+       int             10H
+       pop             si
+       mov             dx,3c4H
+       mov             ax,604H
+       out             dx,ax
+       mov             ax,100H
+       out             dx,ax
+       mov             dx,3c2H
+       lodsb
+       out             dx,al
+       mov             dx,3c4H
+       mov             ax,300H
+       out             dx,ax
+       mov             dx,3d4H
+       mov             al,11H
+       out             dx,al
+       inc             dx
+       in              al,dx
+       and             al,7fH
+       out             dx,al
+       lodsw
+       mov             word ptr L$1,ax
+       lodsw
+       mov             word ptr L$2,ax
+       lodsw
+       mov             word ptr MX_SCREENWIDTH,ax
+       shr             ax,1
+       shr             ax,1
+       mov             word ptr MX_BYTESPERLINE,ax
+       lodsw
+       mov             word ptr MX_SCREENHEIGHT,ax
+       mov             bx,si
+       mov             dx,3d4H
+L$33:
+       mov             si,word ptr [bx]
+       inc             bx
+       inc             bx
+       test            si,si
+       je              L$35
+L$34:
+       lodsw
+       test            ax,ax
+       je              L$33
+       out             dx,ax
+       jmp             L$34
+L$35:
+       push            word ptr MX_SCREENWIDTH
+       push            word ptr [bx]
+       push            cs
+       call            near ptr MX_TEXT:MXSETSYSCLIPREGION
+       mov             dx,3c4H
+       mov             ax,0f02H
+       out             dx,ax
+       mov             es,word ptr MX_TEXT:MX_VIDEOSEGMENT
+       xor             di,di
+       mov             cx,8000H
+       xor             ax,ax
+       rep stosw
+       mov             dx,3d4H
+       mov             al,11H
+       out             dx,al
+       inc             dx
+       in              al,dx
+       or              al,80H
+       out             dx,al
+L$36:
+       xor             ax,ax
+       mov             ax,word ptr MX_SCREENWIDTH
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            2
+MXCHANGEMODE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       mov             si,word ptr 6[bp]
+       cmp             si,0dH
+       ja              L$40
+       test            si,si
+       je              L$40
+       dec             si
+       shl             si,1
+       mov             si,word ptr L$29[si]
+       cld
+       mov             dx,3c4H
+       mov             ax,604H
+       out             dx,ax
+       mov             ax,100H
+       out             dx,ax
+       mov             dx,3c2H
+       lodsb
+       out             dx,al
+       mov             dx,3c4H
+       mov             ax,300H
+       out             dx,ax
+       mov             dx,3d4H
+       mov             al,11H
+       out             dx,al
+       inc             dx
+       in              al,dx
+       and             al,7fH
+       out             dx,al
+       lodsw
+       mov             word ptr L$1,ax
+       lodsw
+       mov             word ptr L$2,ax
+       lodsw
+       mov             word ptr MX_SCREENWIDTH,ax
+       lodsw
+       mov             word ptr MX_SCREENHEIGHT,ax
+       mov             bx,si
+       mov             dx,3d4H
+L$37:
+       mov             si,word ptr [bx]
+       inc             bx
+       inc             bx
+       test            si,si
+       je              L$39
+L$38:
+       lodsw
+       test            ax,ax
+       je              L$37
+       cmp             al,13H
+       je              L$38
+       out             dx,ax
+       jmp             L$38
+L$39:
+       mov             dx,3d4H
+       mov             al,11H
+       out             dx,al
+       inc             dx
+       in              al,dx
+       or              al,80H
+       out             dx,al
+L$40:
+       xor             ax,ax
+       mov             ax,word ptr MX_SCREENWIDTH
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            2
+MXGETASPECT:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       lds             si,dword ptr 0aH[bp]
+       mov             ax,word ptr cs:L$1
+       mov             word ptr [si],ax
+       lds             si,dword ptr 6[bp]
+       mov             ax,word ptr cs:L$2
+       mov             word ptr [si],ax
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+MXGETSCREENSIZE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       lds             si,dword ptr 0aH[bp]
+       mov             ax,word ptr cs:MX_SCREENWIDTH
+       mov             word ptr [si],ax
+       lds             si,dword ptr 6[bp]
+       mov             ax,word ptr cs:MX_SCREENHEIGHT
+       mov             word ptr [si],ax
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxsp.asm b/16/xw_/mxsp.asm
new file mode 100755 (executable)
index 0000000..3385a6c
--- /dev/null
@@ -0,0 +1,33 @@
+               PUBLIC  MXSETPALETTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXSETPALETTE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       lds             si,dword ptr 0aH[bp]
+       mov             cx,word ptr 6[bp]
+       mov             ax,word ptr 8[bp]
+       mov             dx,3c8H
+       out             dx,al
+       inc             dx
+       cld
+       cli
+L$1:
+       lodsb
+       out             dx,al
+       lodsb
+       out             dx,al
+       lodsb
+       out             dx,al
+       loop            L$1
+       sti
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxss.asm b/16/xw_/mxss.asm
new file mode 100755 (executable)
index 0000000..558584c
--- /dev/null
@@ -0,0 +1,44 @@
+               PUBLIC  MXSPLITSCREEN
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXSPLITSCREEN:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       mov             ax,word ptr 6[bp]
+       shl             ax,1
+       mov             bh,ah
+       mov             bl,ah
+       and             bx,201H
+       mov             cl,4
+       shl             bx,cl
+       shl             bh,1
+       mov             dx,3d4H
+       mov             ah,al
+       mov             al,18H
+       out             dx,ax
+       mov             al,7
+       out             dx,al
+       inc             dx
+       in              al,dx
+       dec             dx
+       mov             ah,al
+       and             ah,0efH
+       or              ah,bl
+       mov             al,7
+       out             dx,ax
+       mov             al,9
+       out             dx,al
+       inc             dx
+       in              al,dx
+       dec             dx
+       mov             ah,al
+       and             ah,0bfH
+       or              ah,bh
+       mov             al,9
+       out             dx,ax
+       mov             sp,bp
+       pop             bp
+       retf            2
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxtl.asm b/16/xw_/mxtl.asm
new file mode 100755 (executable)
index 0000000..3f791b4
--- /dev/null
@@ -0,0 +1,122 @@
+               PUBLIC  MXPUTTILE
+               PUBLIC  MXTRANSPUTTILE
+               EXTRN   MX_BYTESPERLINE:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXPUTTILE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             ax,word ptr 0aH[bp]
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             di,word ptr 0cH[bp]
+       shr             di,1
+       shr             di,1
+       add             di,ax
+       mov             es,word ptr cs:MX_VIDEOSEGMENT
+       lds             si,dword ptr 0eH[bp]
+       shr             word ptr 8[bp],1
+       shr             word ptr 8[bp],1
+       mov             cl,byte ptr 0cH[bp]
+       and             cl,3
+       mov             ah,11H
+       shl             ah,cl
+       mov             word ptr 0aH[bp],4
+       mov             bx,word ptr cs:MX_BYTESPERLINE
+       sub             bx,word ptr 8[bp]
+L$1:
+       mov             al,2
+       mov             dx,3c4H
+       out             dx,ax
+       mov             word ptr 0cH[bp],di
+       mov             dx,word ptr 6[bp]
+L$2:
+       mov             cx,word ptr 8[bp]
+       shr             cx,1
+       rep movsw
+       rcl             cx,1
+       rep movsb
+       add             di,bx
+       dec             dx
+       jne             L$2
+       mov             di,word ptr 0cH[bp]
+       rol             ah,1
+       adc             di,0
+       dec             word ptr 0aH[bp]
+       jne             L$1
+       xor             ax,ax
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0cH
+MXTRANSPUTTILE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             ax,word ptr 0aH[bp]
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             di,word ptr 0cH[bp]
+       shr             di,1
+       shr             di,1
+       add             di,ax
+       mov             es,word ptr cs:MX_VIDEOSEGMENT
+       lds             si,dword ptr 0eH[bp]
+       shr             word ptr 8[bp],1
+       shr             word ptr 8[bp],1
+       mov             cl,byte ptr 0cH[bp]
+       and             cl,3
+       mov             ah,11H
+       shl             ah,cl
+       mov             word ptr 0aH[bp],4
+       mov             bx,word ptr cs:MX_BYTESPERLINE
+       sub             bx,word ptr 8[bp]
+L$3:
+       mov             al,2
+       mov             dx,3c4H
+       out             dx,ax
+       mov             word ptr 0cH[bp],di
+       mov             dx,word ptr 6[bp]
+L$4:
+       mov             cx,word ptr 8[bp]
+       jcxz            L$7
+L$5:
+       mov             al,byte ptr [si]
+       test            al,al
+       je              L$6
+       mov             byte ptr es:[di],al
+L$6:
+       inc             si
+       inc             di
+       dec             cx
+       jne             L$5
+L$7:
+       add             di,bx
+       dec             dx
+       jne             L$4
+       mov             di,word ptr 0cH[bp]
+       rol             ah,1
+       adc             di,0
+       dec             word ptr 0aH[bp]
+       jne             L$3
+       xor             ax,ax
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0cH
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxvs.asm b/16/xw_/mxvs.asm
new file mode 100755 (executable)
index 0000000..c4728ff
--- /dev/null
@@ -0,0 +1,68 @@
+               PUBLIC  MXSETVIRTUALSCREEN
+               PUBLIC  MXGETVIRTUALSCREEN
+               EXTRN   MX_CODESEGMENT:BYTE
+               EXTRN   MX_BYTESPERLINE:BYTE
+               EXTRN   MXROWADDRESS:BYTE
+               EXTRN   MXSETSYSCLIPREGION:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+       add             byte ptr [bx+si],al
+L$2:
+       add             byte ptr [bx+si],al
+MXSETVIRTUALSCREEN:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       mov             ax,1
+       cmp             word ptr 8[bp],140H
+       jb              L$3
+       push            ax
+       mov             dx,4
+       xor             ax,ax
+       div             word ptr 8[bp]
+       cmp             word ptr 6[bp],ax
+       pop             ax
+       ja              L$3
+       mov             ax,word ptr 8[bp]
+       and             ax,0fff8H
+       mov             word ptr L$1,ax
+       shr             ax,1
+       shr             ax,1
+       mov             word ptr MX_TEXT:MX_BYTESPERLINE,ax
+       shr             ax,1
+       push            ax
+       call            far ptr MXROWADDRESS
+       mov             ax,word ptr 6[bp]
+       mov             word ptr L$2,ax
+       push            word ptr 8[bp]
+       push            word ptr 6[bp]
+       call            far ptr MXSETSYSCLIPREGION
+       xor             ax,ax
+L$3:
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            4
+MXGETVIRTUALSCREEN:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       mov             ax,word ptr cs:L$1
+       lds             si,dword ptr 0aH[bp]
+       mov             word ptr [si],ax
+       mov             ax,word ptr cs:L$2
+       lds             si,dword ptr 6[bp]
+       mov             word ptr [si],ax
+       xor             ax,ax
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxwd.asm b/16/xw_/mxwd.asm
new file mode 100755 (executable)
index 0000000..c0d19aa
--- /dev/null
@@ -0,0 +1,12 @@
+               PUBLIC  MXWAITDISPLAY
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXWAITDISPLAY:
+       mov             dx,3daH
+L$1:
+       in              al,dx
+       test            al,8
+       jne             L$1
+       retf
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxwm.asm b/16/xw_/mxwm.asm
new file mode 100755 (executable)
index 0000000..7dc66ac
--- /dev/null
@@ -0,0 +1,18 @@
+               PUBLIC  MXWRITEMODE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXWRITEMODE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       mov             dx,3ceH
+       mov             ah,byte ptr 6[bp]
+       and             ah,3
+       or              ah,40H
+       mov             al,5
+       out             dx,ax
+       mov             sp,bp
+       pop             bp
+       retf            2
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxwp.asm b/16/xw_/mxwp.asm
new file mode 100755 (executable)
index 0000000..e03c404
--- /dev/null
@@ -0,0 +1,30 @@
+               PUBLIC  MXWRITEPLANE
+               PUBLIC  MXREADPLANE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXWRITEPLANE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       mov             ah,byte ptr 6[bp]
+       and             ah,0fH
+       mov             al,2
+       mov             dx,3c4H
+       out             dx,ax
+       mov             sp,bp
+       pop             bp
+       retf            2
+MXREADPLANE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       mov             al,4
+       mov             ah,byte ptr 6[bp]
+       and             ah,3
+       mov             dx,3ceH
+       out             dx,ax
+       mov             sp,bp
+       pop             bp
+       retf            2
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/mxwr.asm b/16/xw_/mxwr.asm
new file mode 100755 (executable)
index 0000000..0d228d8
--- /dev/null
@@ -0,0 +1,12 @@
+               PUBLIC  MXWAITRETRACE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXWAITRETRACE:
+       mov             dx,3daH
+L$1:
+       in              al,dx
+       test            al,8
+       je              L$1
+       retf
+MX_TEXT                ENDS
+               END
diff --git a/16/xw_/readme.txt b/16/xw_/readme.txt
new file mode 100755 (executable)
index 0000000..306e8b9
--- /dev/null
@@ -0,0 +1,8 @@
+ModeX - A graphical library for DOS programs\r
+Copyright (c) 1993-1994 Alessandro Scotti\r
+http://www.ascotti.org/\r
+\r
+Please look at the above site in the "Art of..." and\r
+then in the "Old programs" section for more information.\r
+\r
+\r
diff --git a/16/xw_/xw.bat b/16/xw_/xw.bat
new file mode 100755 (executable)
index 0000000..1fd2439
--- /dev/null
@@ -0,0 +1,39 @@
+@echo off\r
+wdis -a MXBB.OBJ > mxbb.asm\r
+wdis -a MXCC.OBJ > mxcc.asm\r
+wdis -a MXCG.OBJ > mxcg.asm\r
+wdis -a MXCL.OBJ > mxcl.asm\r
+wdis -a MXCR.OBJ > mxcl.asm\r
+wdis -a MXFB.OBJ > mxfb.asm\r
+wdis -a MXFP.OBJ > mxfp.asm\r
+wdis -a MXGC.OBJ > mxgc.asm\r
+wdis -a MXGI.OBJ > mxgi.asm\r
+wdis -a MXGM.OBJ > mxgm.asm\r
+wdis -a MXGP.OBJ > mxgp.asm\r
+wdis -a MXGV.OBJ > mxgv.asm\r
+wdis -a MXHL.OBJ > mxhl.asm\r
+wdis -a MXIT.OBJ > mxit.asm\r
+wdis -a MXLL.OBJ > mxll.asm\r
+wdis -a MXLN.OBJ > mxln.asm\r
+wdis -a MXOT.OBJ > mxot.asm\r
+wdis -a MXPB.OBJ > mxpb.asm\r
+wdis -a MXPF.OBJ > mxpf.asm\r
+wdis -a MXPG.OBJ > mxpg.asm\r
+wdis -a MXPI.OBJ > mxpi.asm\r
+wdis -a MXPN.OBJ > mxpn.asm\r
+wdis -a MXPP.OBJ > mxpp.asm\r
+wdis -a MXRA.OBJ > mxra.asm\r
+wdis -a MXRP.OBJ > mxrp.asm\r
+wdis -a MXSA.OBJ > mxsa.asm\r
+wdis -a MXSC.OBJ > mxsc.asm\r
+wdis -a MXSI.OBJ > mxsi.asm\r
+wdis -a MXSL.OBJ > mxsl.asm\r
+wdis -a MXSM.OBJ > mxsm.asm\r
+wdis -a MXSP.OBJ > mxsp.asm\r
+wdis -a MXSS.OBJ > mxss.asm\r
+wdis -a MXTL.OBJ > mxtl.asm\r
+wdis -a MXVS.OBJ > mxvs.asm\r
+wdis -a MXWD.OBJ > mxwd.asm\r
+wdis -a MXWM.OBJ > mxwm.asm\r
+wdis -a MXWP.OBJ > mxwp.asm\r
+wdis -a MXWR.OBJ > mxwr.asm\r
diff --git a/16/xw__/default.fnt b/16/xw__/default.fnt
new file mode 100755 (executable)
index 0000000..12eb22c
--- /dev/null
@@ -0,0 +1,260 @@
+;\r
+; MODEX library default font\r
+; Copyright (c) 1993-1994 by Alessandro Scotti\r
+;\r
+  DB    000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h  ; #0\r
+  DB   07Eh, 081h, 0A5h, 081h, 0A5h, 099h, 081h, 07Eh  ; #1\r
+  DB   07Eh, 0FFh, 0DBh, 0FFh, 0DBh, 0E7h, 0FFh, 07Eh  ; #2\r
+  DB   06Ch, 0FEh, 0FEh, 0FEh, 07Ch, 038h, 010h, 000h  ; #3\r
+  DB   010h, 038h, 07Ch, 0FEh, 07Ch, 038h, 010h, 000h  ; #4\r
+  DB   010h, 038h, 010h, 054h, 0FEh, 054h, 010h, 0FEh  ; #5\r
+  DB   010h, 038h, 07Ch, 0FEh, 0FEh, 07Ch, 010h, 0FEh  ; #6\r
+  DB   000h, 018h, 03Ch, 07Eh, 07Eh, 03Ch, 018h, 000h  ; #7\r
+  DB   0FFh, 0E7h, 0C3h, 081h, 081h, 0C3h, 0E7h, 0FFh  ; #8\r
+  DB   000h, 03Ch, 066h, 042h, 042h, 066h, 03Ch, 000h  ; #9\r
+  DB   0FFh, 0C3h, 099h, 0BDh, 0BDh, 099h, 0C3h, 0FFh  ; #10\r
+  DB   007h, 003h, 005h, 078h, 084h, 084h, 084h, 078h  ; #11\r
+  DB   07Ch, 082h, 082h, 082h, 07Ch, 010h, 038h, 010h  ; #12\r
+  DB   01Ch, 010h, 01Ch, 010h, 010h, 010h, 030h, 030h  ; #13\r
+  DB   03Eh, 022h, 03Eh, 022h, 022h, 026h, 066h, 060h  ; #14\r
+  DB   099h, 05Ah, 03Ch, 0E7h, 0E7h, 03Ch, 05Ah, 099h  ; #15\r
+  DB   000h, 010h, 030h, 070h, 0F0h, 070h, 030h, 010h  ; #16\r
+  DB   000h, 080h, 0C0h, 0E0h, 0F0h, 0E0h, 0C0h, 080h  ; #17\r
+  DB   010h, 038h, 054h, 010h, 010h, 054h, 038h, 010h  ; #18\r
+  DB   048h, 048h, 048h, 048h, 048h, 000h, 048h, 000h  ; #19\r
+  DB   07Eh, 092h, 092h, 072h, 012h, 012h, 012h, 000h  ; #20\r
+  DB   03Ch, 022h, 018h, 024h, 024h, 018h, 044h, 03Ch  ; #21\r
+  DB   000h, 000h, 000h, 000h, 000h, 03Eh, 03Eh, 000h  ; #22\r
+  DB   038h, 054h, 010h, 010h, 010h, 054h, 038h, 0FEh  ; #23\r
+  DB   000h, 010h, 038h, 054h, 010h, 010h, 010h, 000h  ; #24\r
+  DB   000h, 010h, 010h, 010h, 054h, 038h, 010h, 000h  ; #25\r
+  DB   000h, 008h, 004h, 0FEh, 004h, 008h, 000h, 000h  ; #26\r
+  DB   000h, 020h, 040h, 0FEh, 040h, 020h, 000h, 000h  ; #27\r
+  DB   000h, 000h, 080h, 080h, 080h, 0FCh, 000h, 000h  ; #28\r
+  DB   000h, 024h, 042h, 0FFh, 042h, 024h, 000h, 000h  ; #29\r
+  DB   000h, 000h, 010h, 038h, 07Ch, 0FEh, 000h, 000h  ; #30\r
+  DB   000h, 000h, 0FEh, 07Ch, 038h, 010h, 000h, 000h  ; #31\r
+  DB   000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h  ;  \r
+  DB   010h, 010h, 010h, 010h, 010h, 000h, 010h, 000h  ; !\r
+  DB   000h, 024h, 024h, 000h, 000h, 000h, 000h, 000h  ; "\r
+  DB   024h, 024h, 07Eh, 024h, 07Eh, 024h, 024h, 000h  ; #\r
+  DB   038h, 054h, 050h, 038h, 014h, 054h, 038h, 010h  ; $\r
+  DB   000h, 002h, 044h, 008h, 010h, 020h, 042h, 000h  ; %\r
+  DB   038h, 044h, 038h, 060h, 094h, 088h, 074h, 000h  ; &\r
+  DB   020h, 020h, 040h, 000h, 000h, 000h, 000h, 000h  ; '\r
+  DB   010h, 020h, 040h, 040h, 040h, 020h, 010h, 000h  ; (\r
+  DB   040h, 020h, 010h, 010h, 010h, 020h, 040h, 000h  ; )\r
+  DB   000h, 024h, 018h, 07Eh, 018h, 024h, 000h, 000h  ; *\r
+  DB   000h, 010h, 010h, 07Ch, 010h, 010h, 000h, 000h  ; +\r
+  DB   000h, 000h, 000h, 000h, 000h, 010h, 010h, 020h  ; ,\r
+  DB   000h, 000h, 000h, 0FCh, 000h, 000h, 000h, 000h  ; -\r
+  DB   000h, 000h, 000h, 000h, 000h, 000h, 010h, 000h  ; .\r
+  DB   000h, 004h, 008h, 010h, 020h, 040h, 080h, 000h  ; /\r
+  DB   07Ch, 0C6h, 08Ah, 092h, 0A2h, 0C6h, 07Ch, 000h  ; 0\r
+  DB   010h, 030h, 010h, 010h, 010h, 010h, 038h, 000h  ; 1\r
+  DB   078h, 084h, 004h, 018h, 060h, 080h, 0FCh, 000h  ; 2\r
+  DB   078h, 084h, 004h, 038h, 004h, 084h, 078h, 000h  ; 3\r
+  DB   01Ch, 024h, 044h, 084h, 0FEh, 004h, 00Eh, 000h  ; 4\r
+  DB   0FCh, 080h, 0F8h, 004h, 004h, 084h, 078h, 000h  ; 5\r
+  DB   078h, 084h, 080h, 0F8h, 084h, 084h, 078h, 000h  ; 6\r
+  DB   0FCh, 004h, 004h, 008h, 010h, 020h, 020h, 000h  ; 7\r
+  DB   078h, 084h, 084h, 078h, 084h, 084h, 078h, 000h  ; 8\r
+  DB   078h, 084h, 084h, 07Ch, 004h, 084h, 078h, 000h  ; 9\r
+  DB   000h, 000h, 010h, 000h, 000h, 000h, 010h, 000h  ; :\r
+  DB   000h, 000h, 010h, 000h, 000h, 010h, 010h, 020h  ; ;\r
+  DB   008h, 010h, 020h, 040h, 020h, 010h, 008h, 000h  ; <\r
+  DB   000h, 000h, 0FCh, 000h, 000h, 0FCh, 000h, 000h  ; =\r
+  DB   040h, 020h, 010h, 008h, 010h, 020h, 040h, 000h  ; >\r
+  DB   078h, 084h, 004h, 008h, 010h, 000h, 010h, 000h  ; ?\r
+  DB   07Ch, 082h, 0BAh, 0A6h, 0BEh, 080h, 07Ch, 000h  ; @\r
+  DB   078h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h  ; A\r
+  DB   0F8h, 084h, 084h, 0F8h, 084h, 084h, 0F8h, 000h  ; B\r
+  DB   078h, 084h, 080h, 080h, 080h, 084h, 078h, 000h  ; C\r
+  DB   0F0h, 088h, 084h, 084h, 084h, 088h, 0F0h, 000h  ; D\r
+  DB   0FCh, 080h, 080h, 0F0h, 080h, 080h, 0FCh, 000h  ; E\r
+  DB   0FCh, 080h, 080h, 0F0h, 080h, 080h, 080h, 000h  ; F\r
+  DB   078h, 084h, 080h, 09Ch, 084h, 084h, 078h, 000h  ; G\r
+  DB   084h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h  ; H\r
+  DB   038h, 010h, 010h, 010h, 010h, 010h, 038h, 000h  ; I\r
+  DB   01Ch, 008h, 008h, 008h, 088h, 088h, 070h, 000h  ; J\r
+  DB   084h, 088h, 090h, 0E0h, 090h, 088h, 084h, 000h  ; K\r
+  DB   080h, 080h, 080h, 080h, 080h, 080h, 0FCh, 000h  ; L\r
+  DB   0C6h, 0AAh, 092h, 082h, 082h, 082h, 082h, 000h  ; M\r
+  DB   082h, 0C2h, 0A2h, 092h, 08Ah, 086h, 082h, 000h  ; N\r
+  DB   078h, 084h, 084h, 084h, 084h, 084h, 078h, 000h  ; O\r
+  DB   0F8h, 084h, 084h, 0F8h, 080h, 080h, 080h, 000h  ; P\r
+  DB   078h, 084h, 084h, 084h, 094h, 088h, 076h, 000h  ; Q\r
+  DB   0F8h, 084h, 084h, 0F8h, 090h, 088h, 084h, 000h  ; R\r
+  DB   078h, 084h, 080h, 078h, 004h, 084h, 078h, 000h  ; S\r
+  DB   0FEh, 010h, 010h, 010h, 010h, 010h, 010h, 000h  ; T\r
+  DB   084h, 084h, 084h, 084h, 084h, 084h, 078h, 000h  ; U\r
+  DB   084h, 084h, 084h, 084h, 084h, 048h, 030h, 000h  ; V\r
+  DB   082h, 082h, 082h, 082h, 092h, 0AAh, 0C6h, 000h  ; W\r
+  DB   082h, 044h, 028h, 010h, 028h, 044h, 082h, 000h  ; X\r
+  DB   044h, 044h, 044h, 038h, 010h, 010h, 010h, 000h  ; Y\r
+  DB   0FEh, 004h, 008h, 010h, 020h, 040h, 0FEh, 000h  ; Z\r
+  DB   078h, 040h, 040h, 040h, 040h, 040h, 078h, 000h  ; [\r
+  DB   000h, 080h, 040h, 020h, 010h, 008h, 004h, 000h  ; \\r
+  DB   078h, 008h, 008h, 008h, 008h, 008h, 078h, 000h  ; ]\r
+  DB   010h, 028h, 044h, 082h, 000h, 000h, 000h, 000h  ; ^\r
+  DB   000h, 000h, 000h, 000h, 000h, 000h, 000h, 0FFh  ; _\r
+  DB   020h, 020h, 010h, 000h, 000h, 000h, 000h, 000h  ; `\r
+  DB   000h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; a\r
+  DB   000h, 040h, 040h, 078h, 044h, 044h, 078h, 000h  ; b\r
+  DB   000h, 000h, 03Ch, 040h, 040h, 040h, 03Ch, 000h  ; c\r
+  DB   000h, 004h, 004h, 03Ch, 044h, 044h, 03Ch, 000h  ; d\r
+  DB   000h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h  ; e\r
+  DB   000h, 00Ch, 010h, 03Ch, 010h, 010h, 010h, 000h  ; f\r
+  DB   000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 038h  ; g\r
+  DB   000h, 040h, 040h, 078h, 044h, 044h, 044h, 000h  ; h\r
+  DB   000h, 010h, 000h, 010h, 010h, 010h, 010h, 000h  ; i\r
+  DB   000h, 004h, 000h, 004h, 004h, 004h, 044h, 038h  ; j\r
+  DB   000h, 040h, 040h, 050h, 060h, 050h, 048h, 000h  ; k\r
+  DB   000h, 030h, 010h, 010h, 010h, 010h, 010h, 000h  ; l\r
+  DB   000h, 000h, 068h, 054h, 054h, 044h, 044h, 000h  ; m\r
+  DB   000h, 000h, 078h, 044h, 044h, 044h, 044h, 000h  ; n\r
+  DB   000h, 000h, 038h, 044h, 044h, 044h, 038h, 000h  ; o\r
+  DB   000h, 000h, 078h, 044h, 044h, 078h, 040h, 040h  ; p\r
+  DB   000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 004h  ; q\r
+  DB   000h, 000h, 05Ch, 060h, 040h, 040h, 040h, 000h  ; r\r
+  DB   000h, 000h, 038h, 040h, 07Ch, 004h, 07Ch, 000h  ; s\r
+  DB   000h, 010h, 038h, 010h, 010h, 010h, 018h, 000h  ; t\r
+  DB   000h, 000h, 044h, 044h, 044h, 044h, 038h, 000h  ; u\r
+  DB   000h, 000h, 044h, 044h, 044h, 028h, 010h, 000h  ; v\r
+  DB   000h, 000h, 044h, 044h, 054h, 054h, 06Ch, 000h  ; w\r
+  DB   000h, 000h, 044h, 028h, 010h, 028h, 044h, 000h  ; x\r
+  DB   000h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch  ; y\r
+  DB   000h, 000h, 07Ch, 004h, 038h, 040h, 07Ch, 000h  ; z\r
+  DB   000h, 008h, 010h, 010h, 030h, 010h, 010h, 008h  ; {\r
+  DB   000h, 010h, 010h, 010h, 000h, 010h, 010h, 010h  ; |\r
+  DB   000h, 020h, 010h, 010h, 018h, 010h, 010h, 020h  ; }\r
+  DB   064h, 098h, 000h, 000h, 000h, 000h, 000h, 000h  ; ~\r
+  DB   000h, 010h, 028h, 044h, 082h, 082h, 0FEh, 000h  ; \7f\r
+  DB   07Ch, 080h, 080h, 080h, 080h, 07Ch, 004h, 07Ch  ; #128\r
+  DB   000h, 028h, 000h, 044h, 044h, 044h, 038h, 000h  ; #129\r
+  DB   03Ch, 000h, 07Ch, 044h, 07Ch, 040h, 07Ch, 000h  ; #130\r
+  DB   07Eh, 081h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #131\r
+  DB   024h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #132\r
+  DB   078h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #133\r
+  DB   018h, 018h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #134\r
+  DB   000h, 000h, 078h, 080h, 080h, 078h, 008h, 038h  ; #135\r
+  DB   07Ch, 082h, 038h, 044h, 07Ch, 040h, 03Ch, 000h  ; #136\r
+  DB   048h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h  ; #137\r
+  DB   078h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h  ; #138\r
+  DB   000h, 028h, 000h, 010h, 010h, 010h, 010h, 000h  ; #139\r
+  DB   010h, 028h, 000h, 010h, 010h, 010h, 010h, 000h  ; #140\r
+  DB   000h, 030h, 000h, 010h, 010h, 010h, 010h, 000h  ; #141\r
+  DB   048h, 000h, 078h, 084h, 0FCh, 084h, 084h, 000h  ; #142\r
+  DB   030h, 030h, 078h, 084h, 0FCh, 084h, 084h, 000h  ; #143\r
+  DB   038h, 000h, 0FCh, 080h, 0F0h, 080h, 0FCh, 000h  ; #144\r
+  DB   000h, 000h, 07Eh, 008h, 07Eh, 048h, 07Eh, 000h  ; #145\r
+  DB   07Eh, 090h, 090h, 0FCh, 090h, 090h, 09Eh, 000h  ; #146\r
+  DB   07Ch, 082h, 038h, 044h, 044h, 044h, 038h, 000h  ; #147\r
+  DB   028h, 000h, 038h, 044h, 044h, 044h, 038h, 000h  ; #148\r
+  DB   070h, 000h, 038h, 044h, 044h, 044h, 038h, 000h  ; #149\r
+  DB   038h, 044h, 000h, 044h, 044h, 044h, 038h, 000h  ; #150\r
+  DB   070h, 000h, 044h, 044h, 044h, 044h, 038h, 000h  ; #151\r
+  DB   028h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch  ; #152\r
+  DB   048h, 000h, 078h, 084h, 084h, 084h, 078h, 000h  ; #153\r
+  DB   048h, 000h, 084h, 084h, 084h, 084h, 078h, 000h  ; #154\r
+  DB   000h, 010h, 038h, 040h, 040h, 040h, 038h, 010h  ; #155\r
+  DB   038h, 044h, 040h, 0E0h, 040h, 040h, 082h, 0FCh  ; #156\r
+  DB   044h, 07Ch, 010h, 07Ch, 010h, 07Ch, 010h, 000h  ; #157\r
+  DB   0F0h, 088h, 08Ah, 0F7h, 082h, 082h, 082h, 000h  ; #158\r
+  DB   00Ch, 012h, 010h, 018h, 030h, 010h, 090h, 060h  ; #159\r
+  DB   03Ch, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h  ; #160\r
+  DB   000h, 018h, 000h, 010h, 010h, 010h, 010h, 000h  ; #161\r
+  DB   01Ch, 000h, 038h, 044h, 044h, 044h, 038h, 000h  ; #162\r
+  DB   01Ch, 000h, 044h, 044h, 044h, 044h, 038h, 000h  ; #163\r
+  DB   07Ch, 000h, 078h, 044h, 044h, 044h, 044h, 000h  ; #164\r
+  DB   07Ch, 000h, 044h, 064h, 054h, 04Ch, 044h, 000h  ; #165\r
+  DB   018h, 024h, 024h, 01Eh, 000h, 03Eh, 000h, 000h  ; #166\r
+  DB   01Ch, 022h, 022h, 01Ch, 000h, 03Eh, 000h, 000h  ; #167\r
+  DB   010h, 000h, 010h, 020h, 040h, 042h, 03Ch, 000h  ; #168\r
+  DB   000h, 000h, 000h, 0FCh, 080h, 080h, 000h, 000h  ; #169\r
+  DB   000h, 000h, 000h, 0FCh, 004h, 004h, 000h, 000h  ; #170\r
+  DB   040h, 044h, 048h, 057h, 021h, 047h, 004h, 007h  ; #171\r
+  DB   040h, 044h, 048h, 052h, 026h, 04Ah, 01Fh, 002h  ; #172\r
+  DB   010h, 000h, 010h, 010h, 010h, 010h, 010h, 000h  ; #173\r
+  DB   000h, 024h, 048h, 090h, 048h, 024h, 000h, 000h  ; #174\r
+  DB   000h, 048h, 024h, 012h, 024h, 048h, 000h, 000h  ; #175\r
+  DB   022h, 088h, 022h, 088h, 022h, 088h, 022h, 088h  ; #176\r
+  DB   055h, 0AAh, 055h, 0AAh, 055h, 0AAh, 055h, 0AAh  ; #177\r
+  DB   0DBh, 077h, 0DBh, 0EEh, 0DBh, 077h, 0DBh, 0EEh  ; #178\r
+  DB   018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h  ; #179\r
+  DB   018h, 018h, 018h, 018h, 0F8h, 018h, 018h, 018h  ; #180\r
+  DB   018h, 018h, 0F8h, 018h, 0F8h, 018h, 018h, 018h  ; #181\r
+  DB   036h, 036h, 036h, 036h, 0F6h, 036h, 036h, 036h  ; #182\r
+  DB   000h, 000h, 000h, 000h, 0FEh, 036h, 036h, 036h  ; #183\r
+  DB   000h, 000h, 0F8h, 018h, 0F8h, 018h, 018h, 018h  ; #184\r
+  DB   036h, 036h, 0F6h, 006h, 0F6h, 036h, 036h, 036h  ; #185\r
+  DB   036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h  ; #186\r
+  DB   000h, 000h, 0FEh, 006h, 0F6h, 036h, 036h, 036h  ; #187\r
+  DB   036h, 036h, 0F6h, 006h, 0FEh, 000h, 000h, 000h  ; #188\r
+  DB   036h, 036h, 036h, 036h, 0FEh, 000h, 000h, 000h  ; #189\r
+  DB   018h, 018h, 0F8h, 018h, 0F8h, 000h, 000h, 000h  ; #190\r
+  DB   000h, 000h, 000h, 000h, 0F8h, 018h, 018h, 018h  ; #191\r
+  DB   018h, 018h, 018h, 018h, 01Fh, 000h, 000h, 000h  ; #192\r
+  DB   018h, 018h, 018h, 018h, 0FFh, 000h, 000h, 000h  ; #193\r
+  DB   000h, 000h, 000h, 000h, 0FFh, 018h, 018h, 018h  ; #194\r
+  DB   018h, 018h, 018h, 018h, 01Fh, 018h, 018h, 018h  ; #195\r
+  DB   000h, 000h, 000h, 000h, 0FFh, 000h, 000h, 000h  ; #196\r
+  DB   018h, 018h, 018h, 018h, 0FFh, 018h, 018h, 018h  ; #197\r
+  DB   018h, 018h, 01Fh, 018h, 01Fh, 018h, 018h, 018h  ; #198\r
+  DB   036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h  ; #199\r
+  DB   036h, 036h, 037h, 030h, 03Fh, 000h, 000h, 000h  ; #200\r
+  DB   000h, 000h, 03Fh, 030h, 037h, 036h, 036h, 036h  ; #201\r
+  DB   036h, 036h, 0F7h, 000h, 0FFh, 000h, 000h, 000h  ; #202\r
+  DB   000h, 000h, 0FFh, 000h, 0F7h, 036h, 036h, 036h  ; #203\r
+  DB   036h, 036h, 037h, 030h, 037h, 036h, 036h, 036h  ; #204\r
+  DB   000h, 000h, 0FFh, 000h, 0FFh, 000h, 000h, 000h  ; #205\r
+  DB   036h, 036h, 0F7h, 000h, 0F7h, 036h, 036h, 036h  ; #206\r
+  DB   018h, 018h, 0FFh, 000h, 0FFh, 000h, 000h, 000h  ; #207\r
+  DB   036h, 036h, 036h, 036h, 0FFh, 000h, 000h, 000h  ; #208\r
+  DB   000h, 000h, 0FFh, 000h, 0FFh, 018h, 018h, 018h  ; #209\r
+  DB   000h, 000h, 000h, 000h, 0FFh, 036h, 036h, 036h  ; #210\r
+  DB   036h, 036h, 036h, 036h, 03Fh, 000h, 000h, 000h  ; #211\r
+  DB   018h, 018h, 01Fh, 018h, 01Fh, 000h, 000h, 000h  ; #212\r
+  DB   000h, 000h, 01Fh, 018h, 01Fh, 018h, 018h, 018h  ; #213\r
+  DB   000h, 000h, 000h, 000h, 03Fh, 036h, 036h, 036h  ; #214\r
+  DB   036h, 036h, 036h, 036h, 0FFh, 036h, 036h, 036h  ; #215\r
+  DB   018h, 018h, 0FFh, 018h, 0FFh, 018h, 018h, 018h  ; #216\r
+  DB   018h, 018h, 018h, 018h, 0F8h, 000h, 000h, 000h  ; #217\r
+  DB   000h, 000h, 000h, 000h, 01Fh, 018h, 018h, 018h  ; #218\r
+  DB   0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh  ; #219\r
+  DB   000h, 000h, 000h, 000h, 0FFh, 0FFh, 0FFh, 0FFh  ; #220\r
+  DB   0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h  ; #221\r
+  DB   00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh  ; #222\r
+  DB   0FFh, 0FFh, 0FFh, 0FFh, 000h, 000h, 000h, 000h  ; #223\r
+  DB   000h, 000h, 062h, 094h, 088h, 094h, 062h, 000h  ; #224\r
+  DB   000h, 0F0h, 088h, 0F0h, 088h, 088h, 0F0h, 080h  ; #225\r
+  DB   000h, 0F8h, 088h, 080h, 080h, 080h, 080h, 000h  ; #226\r
+  DB   000h, 0FCh, 048h, 048h, 048h, 048h, 048h, 000h  ; #227\r
+  DB   0FCh, 084h, 040h, 020h, 040h, 084h, 0FCh, 000h  ; #228\r
+  DB   03Ch, 040h, 038h, 044h, 044h, 044h, 038h, 000h  ; #229\r
+  DB   000h, 000h, 044h, 044h, 044h, 078h, 040h, 040h  ; #230\r
+  DB   000h, 036h, 048h, 008h, 008h, 008h, 008h, 000h  ; #231\r
+  DB   038h, 010h, 038h, 044h, 044h, 038h, 010h, 038h  ; #232\r
+  DB   078h, 084h, 084h, 0FCh, 084h, 084h, 078h, 000h  ; #233\r
+  DB   078h, 084h, 084h, 084h, 048h, 048h, 0CCh, 000h  ; #234\r
+  DB   078h, 004h, 038h, 044h, 044h, 044h, 038h, 000h  ; #235\r
+  DB   000h, 000h, 06Ch, 092h, 092h, 06Ch, 000h, 000h  ; #236\r
+  DB   000h, 000h, 03Ah, 044h, 05Ah, 022h, 05Ch, 000h  ; #237\r
+  DB   018h, 020h, 040h, 078h, 040h, 020h, 018h, 000h  ; #238\r
+  DB   078h, 084h, 084h, 084h, 084h, 084h, 084h, 000h  ; #239\r
+  DB   000h, 0FCh, 000h, 0FCh, 000h, 0FCh, 000h, 000h  ; #240\r
+  DB   020h, 020h, 0F8h, 020h, 020h, 000h, 0F8h, 000h  ; #241\r
+  DB   020h, 010h, 008h, 010h, 020h, 000h, 07Ch, 000h  ; #242\r
+  DB   008h, 010h, 020h, 010h, 008h, 000h, 07Ch, 000h  ; #243\r
+  DB   00Ch, 012h, 010h, 010h, 010h, 010h, 010h, 010h  ; #244\r
+  DB   010h, 010h, 010h, 010h, 010h, 010h, 090h, 060h  ; #245\r
+  DB   000h, 010h, 000h, 07Ch, 000h, 010h, 000h, 000h  ; #246\r
+  DB   000h, 032h, 04Ch, 000h, 032h, 04Ch, 000h, 000h  ; #247\r
+  DB   038h, 044h, 044h, 038h, 000h, 000h, 000h, 000h  ; #248\r
+  DB   000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h  ; #249\r
+  DB   000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h  ; #250\r
+  DB   00Eh, 008h, 008h, 008h, 048h, 028h, 018h, 008h  ; #251\r
+  DB   038h, 024h, 024h, 024h, 024h, 000h, 000h, 000h  ; #252\r
+  DB   03Ch, 004h, 03Ch, 020h, 03Ch, 000h, 000h, 000h  ; #253\r
+  DB   000h, 000h, 03Ch, 03Ch, 03Ch, 03Ch, 000h, 000h  ; #254\r
+  DB   000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h  ; #255\r
diff --git a/16/xw__/makefile b/16/xw__/makefile
new file mode 100755 (executable)
index 0000000..cfe1523
--- /dev/null
@@ -0,0 +1,132 @@
+#\r
+# MODEX library makefile (for Borland MAKE)\r
+# Copyright (c) 1993,1994 by Alessandro Scotti\r
+#\r
+!ifdef __LINUX__\r
+REMOVECOMMAND=rm -f\r
+COPYCOMMAND=cp -f\r
+DIRSEP=/\r
+OBJ=o\r
+!else\r
+REMOVECOMMAND=del\r
+COPYCOMMAND=copy /y\r
+DIRSEP=\\r
+OBJ=obj\r
+!endif\r
+LIBINCS = modex.def\r
+\r
+LIBOBJS = mxbb.$(OBJ) mxcc.$(OBJ) mxcg.$(OBJ) mxcl.$(OBJ) mxcr.$(OBJ) mxfb.$(OBJ) mxgc.$(OBJ) mxgi.$(OBJ) mxgm.$(OBJ) mxgp.$(OBJ) mxgv.$(OBJ) mxhl.$(OBJ) mxit.$(OBJ) mxll.$(OBJ) mxln.$(OBJ) mxot.$(OBJ) mxpb.$(OBJ) mxpf.$(OBJ) mxpg.$(OBJ) mxpi.$(OBJ) mxpn.$(OBJ) mxpp.$(OBJ) mxra.$(OBJ) mxrp.$(OBJ) mxsa.$(OBJ) mxsc.$(OBJ) mxsi.$(OBJ) mxsl.$(OBJ) mxsm.$(OBJ) mxsp.$(OBJ) mxss.$(OBJ) mxtl.$(OBJ) mxvs.$(OBJ) mxwd.$(OBJ) mxwm.$(OBJ) mxwp.$(OBJ) mxwr.$(OBJ)\r
+#mxfp.$(OBJ) \r
+#\r
+# ASM compiler\r
+#\r
+ASMC =wasm\r
+ASMO =-mh -0\r
+\r
+#\r
+# PAS compiler\r
+#\r
+#PASC = tpc\r
+#PASO = /m -$D- -$L- -$S-\r
+\r
+#\r
+# LIB maker, uses response file\r
+#\r
+LIBC = wlib\r
+\r
+# .asm.obj:\r
+#              $(ASMC) $(ASMO) $<\r
+\r
+mxbb.$(OBJ): mxbb.asm\r
+       $(ASMC) $(ASMO) mxbb.asm\r
+mxcc.$(OBJ): mxcc.asm\r
+       $(ASMC) $(ASMO) mxcc.asm\r
+mxcg.$(OBJ): mxcg.asm\r
+       $(ASMC) $(ASMO) mxcg.asm\r
+mxcl.$(OBJ): mxcl.asm\r
+       $(ASMC) $(ASMO) mxcl.asm\r
+mxcr.$(OBJ): mxcr.asm\r
+       $(ASMC) $(ASMO) mxcr.asm\r
+mxfb.$(OBJ): mxfb.asm\r
+       $(ASMC) $(ASMO) mxfb.asm\r
+mxfp.$(OBJ): mxfp.asm\r
+       $(ASMC) $(ASMO) mxfp.asm\r
+mxgc.$(OBJ): mxgc.asm\r
+       $(ASMC) $(ASMO) mxgc.asm\r
+mxgi.$(OBJ): mxgi.asm\r
+       $(ASMC) $(ASMO) mxgi.asm\r
+mxgm.$(OBJ): mxgm.asm\r
+       $(ASMC) $(ASMO) mxgm.asm\r
+mxgp.$(OBJ): mxgp.asm\r
+       $(ASMC) $(ASMO) mxgp.asm\r
+mxgv.$(OBJ): mxgv.asm\r
+       $(ASMC) $(ASMO) mxgv.asm\r
+mxhl.$(OBJ): mxhl.asm\r
+       $(ASMC) $(ASMO) mxhl.asm\r
+mxit.$(OBJ): mxit.asm\r
+       $(ASMC) $(ASMO) mxit.asm\r
+mxll.$(OBJ): mxll.asm\r
+       $(ASMC) $(ASMO) mxll.asm\r
+mxln.$(OBJ): mxln.asm\r
+       $(ASMC) $(ASMO) mxln.asm\r
+mxot.$(OBJ): mxot.asm\r
+       $(ASMC) $(ASMO) mxot.asm\r
+mxpb.$(OBJ): mxpb.asm\r
+       $(ASMC) $(ASMO) mxpb.asm\r
+mxpf.$(OBJ): mxpf.asm\r
+       $(ASMC) $(ASMO) mxpf.asm\r
+mxpg.$(OBJ): mxpg.asm\r
+       $(ASMC) $(ASMO) mxpg.asm\r
+mxpi.$(OBJ): mxpi.asm\r
+       $(ASMC) $(ASMO) mxpi.asm\r
+mxpn.$(OBJ): mxpn.asm\r
+       $(ASMC) $(ASMO) mxpn.asm\r
+mxpp.$(OBJ): mxpp.asm\r
+       $(ASMC) $(ASMO) mxpp.asm\r
+mxra.$(OBJ): mxra.asm\r
+       $(ASMC) $(ASMO) mxra.asm\r
+mxrp.$(OBJ): mxrp.asm\r
+       $(ASMC) $(ASMO) mxrp.asm\r
+mxsa.$(OBJ): mxsa.asm\r
+       $(ASMC) $(ASMO) mxsa.asm\r
+mxsc.$(OBJ): mxsc.asm\r
+       $(ASMC) $(ASMO) mxsc.asm\r
+mxsi.$(OBJ): mxsi.asm\r
+       $(ASMC) $(ASMO) mxsi.asm\r
+mxsl.$(OBJ): mxsl.asm\r
+       $(ASMC) $(ASMO) mxsl.asm\r
+mxsm.$(OBJ): mxsm.asm\r
+       $(ASMC) $(ASMO) mxsm.asm\r
+mxsp.$(OBJ): mxsp.asm\r
+       $(ASMC) $(ASMO) mxsp.asm\r
+mxss.$(OBJ): mxss.asm\r
+       $(ASMC) $(ASMO) mxss.asm\r
+mxtl.$(OBJ): mxtl.asm\r
+       $(ASMC) $(ASMO) mxtl.asm\r
+mxvs.$(OBJ): mxvs.asm\r
+       $(ASMC) $(ASMO) mxvs.asm\r
+mxwd.$(OBJ): mxwd.asm\r
+       $(ASMC) $(ASMO) mxwd.asm\r
+mxwm.$(OBJ): mxwm.asm\r
+       $(ASMC) $(ASMO) mxwm.asm\r
+mxwp.$(OBJ): mxwp.asm\r
+       $(ASMC) $(ASMO) mxwp.asm\r
+mxwr.$(OBJ): mxwr.asm\r
+       $(ASMC) $(ASMO) mxwr.asm\r
+\r
+all: $(LIBOBJS) modex.lib\r
+# modex.tpu modex.tpp\r
+\r
+#modex.tpu: $(LIBOBJS) modex.pas\r
+#        $(PASC) $(PASO) modex\r
+#        copy modex.tpu ..\r
+#        copy modex.pas ..\r
+\r
+#modex.tpp: $(LIBOBJS) modex.pas\r
+#        $(PASC) /cp $(PASO) modex\r
+#        copy modex.tpp ..\r
+\r
+modex.lib: modex.lbr $(LIBOBJS)\r
+       $(LIBC) modex.lib @modex.lbr\r
+\r
+$(LIBOBJS):   modex.def\r
diff --git a/16/xw__/makefile.bcc b/16/xw__/makefile.bcc
new file mode 100755 (executable)
index 0000000..d3ad8b7
--- /dev/null
@@ -0,0 +1,81 @@
+#\r
+# MODEX library makefile (for Borland MAKE)\r
+# Copyright (c) 1993,1994 by Alessandro Scotti\r
+#\r
+LIBINCS = MODEX.DEF\r
+\r
+LIBOBJS = MXBB.OBJ \\r
+          MXCC.OBJ \\r
+          MXCG.OBJ \\r
+          MXCL.OBJ \\r
+          MXCR.OBJ \\r
+          MXFB.OBJ \\r
+          MXFP.OBJ \\r
+          MXGC.OBJ \\r
+          MXGI.OBJ \\r
+          MXGM.OBJ \\r
+          MXGP.OBJ \\r
+          MXGV.OBJ \\r
+          MXHL.OBJ \\r
+          MXIT.OBJ \\r
+          MXLL.OBJ \\r
+          MXLN.OBJ \\r
+          MXOT.OBJ \\r
+          MXPB.OBJ \\r
+          MXPF.OBJ \\r
+          MXPG.OBJ \\r
+          MXPI.OBJ \\r
+          MXPN.OBJ \\r
+          MXPP.OBJ \\r
+          MXRA.OBJ \\r
+          MXRP.OBJ \\r
+          MXSA.OBJ \\r
+          MXSC.OBJ \\r
+          MXSI.OBJ \\r
+          MXSL.OBJ \\r
+          MXSM.OBJ \\r
+          MXSP.OBJ \\r
+          MXSS.OBJ \\r
+          MXTL.OBJ \\r
+          MXVS.OBJ \\r
+          MXWD.OBJ \\r
+          MXWM.OBJ \\r
+          MXWP.OBJ \\r
+          MXWR.OBJ\r
+\r
+#\r
+# ASM compiler\r
+#\r
+ASMC = tasm\r
+ASMO = /m5 /p\r
+\r
+#\r
+# PAS compiler\r
+#\r
+PASC = tpc\r
+PASO = /m -$D- -$L- -$S-\r
+\r
+#\r
+# LIB maker, uses response file\r
+#\r
+LIBC = tlib\r
+\r
+.asm.obj:\r
+        $(ASMC) $(ASMO) $<\r
+\r
+target: modex.lib
+# modex.tpu modex.tpp\r
+\r
+#modex.tpu: $(LIBOBJS) modex.pas\r
+#        $(PASC) $(PASO) modex\r
+#        copy modex.tpu ..\r
+#        copy modex.pas ..\r
+\r
+#modex.tpp: $(LIBOBJS) modex.pas\r
+#        $(PASC) /cp $(PASO) modex\r
+#        copy modex.tpp ..\r
+\r
+modex.lib: modex.lbr $(LIBOBJS)\r
+        $(LIBC) modex.lib @modex.lbr\r
+\r
+$(LIBOBJS):   modex.def\r
diff --git a/16/xw__/modex.bak b/16/xw__/modex.bak
new file mode 100755 (executable)
index 0000000..560a1c6
Binary files /dev/null and b/16/xw__/modex.bak differ
diff --git a/16/xw__/modex.def b/16/xw__/modex.def
new file mode 100755 (executable)
index 0000000..7977a4a
--- /dev/null
@@ -0,0 +1,163 @@
+;------------------------------------------------------------\r
+;\r
+; MODEX.DEF - Include file\r
+; Copyright (c) 1993-1994 by Alessandro Scotti\r
+;\r
+;JUMPS\r
+;LOCALS\r
+\r
+TRUE            EQU     1       ; Boolean constants\r
+FALSE           EQU     0\r
+\r
+USE286  = FALSE                  ; TRUE enables 80286 instructions\r
+USE386  = FALSE                  ; TRUE enables 80386 (and 80286) instructions\r
+\r
+IF USE286 EQ TRUE\r
+        P286\r
+ENDIF\r
+\r
+IF USE386 EQ TRUE\r
+        P386\r
+        USE286  = TRUE\r
+ENDIF\r
+\r
+MXVERSION       EQU     0128h   ; Library version (1.40)\r
+\r
+;------------------------------------------------------------\r
+;\r
+; VGA definitions\r
+;\r
+MISC    EQU     3C2h            ; Miscellaneous output\r
+TS      EQU     3C4h            ; Timing Sequencer index register\r
+GDC     EQU     3CEh            ; Graphics Data Controller index register\r
+CRTC    EQU     3D4h            ; CRTC index register\r
+STATUS  EQU     3DAh            ; Input Status register one\r
+\r
+;------------------------------------------------------------\r
+;\r
+; Raster operators\r
+;\r
+OP_SET          EQU     0\r
+OP_MOVE         EQU     0       ; Same as OP_SET\r
+OP_AND          EQU     1\r
+OP_OR           EQU     2\r
+OP_XOR          EQU     3\r
+OP_TRANS        EQU     4\r
+OP_ADD          EQU     5       ; Must be last op\r
+\r
+;------------------------------------------------------------\r
+;\r
+; Polygon fill functions\r
+;\r
+POLYSCANBUFSIZE EQU     4*1024\r
+\r
+;------------------------------------------------------------\r
+; Macro to push registers, variables or flags onto the stack\r
+; Usage: .push "loc16"[,"loc16"...]\r
+; where "loc16" is a 16-bit register, a word-sized variable or the\r
+; keyword "FLAGS".\r
+; Exmpl: .push ax, flags, var1\r
+;        .pop  ax, flags, var1\r
+;\r
+.push   MACRO   r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10\r
+    IFNB <r10>\r
+        .ERROR <.PUSH has more than 10 arguments>\r
+    ENDIF\r
+    IRP $reg, <r0, r1, r2, r3, r4, r5, r6, r7, r8, r9>\r
+        IFB <$reg>                      ;; Is argument blank?\r
+            EXITM                       ;; Yes, exit\r
+        ELSEIFIDNI <$reg>, <FLAGS>      ;; Is argument the keyword "FLAGS"?\r
+            pushf                       ;; Yes, push flags\r
+        ELSE\r
+            push    $reg                ;; Push argument\r
+        ENDIF\r
+    ENDM\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+; Macro to pop registers, variables or flags from the stack\r
+; Usage: .pop "loc16"[,"loc16"...]\r
+; where "loc16" is a 16-bit register, a word-sized variable or the\r
+; keyword "FLAGS".\r
+; Exmpl: .push ax, flags, var1\r
+;        .pop  ax, flags, var1\r
+;\r
+.pop    MACRO   r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10\r
+    IFNB <r10>\r
+        .ERROR <.POP has more than 10 arguments>\r
+    ENDIF\r
+    IRP $reg, <r9, r8, r7, r6, r5, r4, r3, r2, r1, r0>\r
+        IFNB <$reg>                     ;; Is argument non-blank?\r
+            IFIDNI <$reg>, <FLAGS>      ;; Yes, is it the keyword "FLAGS"?\r
+                popf                    ;; Yes, pop flags\r
+            ELSE\r
+                pop     $reg            ;; Pop argument\r
+            ENDIF\r
+        ENDIF\r
+    ENDM\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+.enter  MACRO   localsize\r
+    IF USE286 EQ TRUE\r
+        enter   localsize, 0\r
+    ELSE\r
+        push    bp\r
+        mov     bp, sp\r
+        sub     sp, localsize\r
+    ENDIF\r
+ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.leave  MACRO   argsize\r
+;    IF USE286 EQ TRUE\r
+;        leave\r
+;    ELSE\r
+;        mov     sp, bp\r
+;        pop     bp\r
+;    ENDIF\r
+;    IFNB <argspace>\r
+;        ret     argsize\r
+;    ELSE\r
+;        ret\r
+;    ENDIF\r
+;ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.shr    MACRO   arg, count\r
+;    IF USE286 EQ TRUE\r
+;        shr     arg, count\r
+;    ELSE\r
+;        $temp = count\r
+;        WHILE $temp GT 0\r
+;            shr arg, 1\r
+;            $temp = $temp-1\r
+;        ENDM\r
+;    ENDIF\r
+;ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.shl    MACRO   arg, count\r
+;    IF USE286 EQ TRUE\r
+;        shl     arg, count\r
+;    ELSE\r
+;        $temp = count\r
+;        WHILE $temp GT 0\r
+;            shl arg, 1\r
+;            $temp = $temp-1\r
+;        ENDM\r
+;    ENDIF\r
+;ENDM\r
+\r
+;------------------------------------------------------------\r
+;\r
+;.chk386 MACRO   name, jump\r
+;    IF USE386 EQ FALSE\r
+;        .OUT    "Warning: ", <name>, " needs a 386 or better to run!"\r
+;        jmp     @@jump\r
+;    ENDIF\r
+;ENDM\r
diff --git a/16/xw__/modex.h b/16/xw__/modex.h
new file mode 100755 (executable)
index 0000000..2c1f1eb
--- /dev/null
@@ -0,0 +1,153 @@
+/*\r
+    MODEX.H - C/C++ include file for the MODEX library\r
+    Copyright (c) 1994 Alessandro Scotti\r
+*/\r
+\r
+#ifndef _MODEX_H_               // Avoid nested inclusions\r
+#define _MODEX_H_\r
+\r
+//\r
+// Video modes\r
+//\r
+#define MX_TEXT     0           // 80x25 text\r
+#define MX_320x175  1           // 320x175x256\r
+#define MX_320x200  2           // 320x200x256, 4 pages, aspect 6:5\r
+#define MX_320x240  3           // 320x240x256, 3 pages, aspect 1:1\r
+#define MX_320x350  4           // 320x350x256\r
+#define MX_320x400  5           // 320x400x256, 2 pages\r
+#define MX_320x480  6           // 320x480x256, 1 page\r
+#define MX_360x175  7           // 360x175x256\r
+#define MX_360x200  8           // 360x200x256, 3 pages\r
+#define MX_360x240  9           // 360x240x256, 2 pages\r
+#define MX_360x350  10          // 360x350x256\r
+#define MX_360x400  11          // 360x400x256, 1 page\r
+#define MX_360x480  12          // 360x480x256, 1 page\r
+#define MX_400x600  13          // 400x600x256, 1 page\r
+\r
+//\r
+// Fade effects\r
+//\r
+#define MX_FADEIN   0\r
+#define MX_FADEOUT  1\r
+\r
+//\r
+// Raster ops\r
+//\r
+#define OP_SET      0           // No operator\r
+#define OP_AND      1           // And\r
+#define OP_OR       2           // Or\r
+#define OP_XOR      3           // Xor\r
+#define OP_TRANS    4           // Transparent\r
+#define OP_ADD      5           // Additive\r
+#define OP_MOVE     0           // Alias for OP_SET\r
+\r
+//\r
+// Temporary definitions\r
+//\r
+#define MXBYTE      unsigned char\r
+#define MXBOOL      short int\r
+#define MXSINT      short int\r
+#define MXUINT      unsigned short int\r
+#define MXAPI       far pascal\r
+#define MXPTR       void far *\r
+\r
+// Functions\r
+\r
+#ifdef __cplusplus                      // Avoid C++ name mangling\r
+extern "C" {\r
+#endif\r
+\r
+//\r
+// Initialization\r
+//\r
+MXSINT  MXAPI mxInit( void );             // Returns 0 if successful\r
+void    MXAPI mxTerm( void );\r
+MXUINT  MXAPI mxGetVersion( void );\r
+//\r
+// Mode setting\r
+//\r
+void    MXAPI mxChangeMode( MXUINT mode );\r
+void    MXAPI mxSetMode( MXUINT mode );\r
+void    MXAPI mxGetAspect( MXUINT far *aspectx, MXUINT far *aspecty );\r
+void    MXAPI mxGetScreenSize( MXUINT far *width, MXUINT far *height );\r
+//\r
+// Hardware support\r
+//\r
+void    MXAPI mxWriteMode( MXBYTE wm );\r
+void    MXAPI mxSplitScreen( MXUINT line );\r
+void    MXAPI mxStartAddress( MXUINT sa );\r
+void    MXAPI mxStartLine( MXUINT sl );\r
+void    MXAPI mxWaitDisplay( void );\r
+void    MXAPI mxWaitRetrace( void );\r
+void    MXAPI mxWritePlane( MXBYTE wp );\r
+void    MXAPI mxReadPlane( MXBYTE rp );\r
+void    MXAPI mxRowAddress( MXBYTE ra );\r
+//\r
+// Virtual screen\r
+//\r
+void    MXAPI mxGetVirtualScreen( MXUINT far *width, MXUINT far *height );\r
+void    MXAPI mxSetVirtualScreen( MXUINT width, MXUINT height );\r
+void    MXAPI mxPan( MXUINT x, MXUINT y );\r
+//\r
+// Clipping\r
+//\r
+MXBOOL  MXAPI mxGetClip( void );\r
+MXBOOL  MXAPI mxGetClipRegion( MXSINT far *x, MXSINT far *y, MXSINT far *w, MXSINT far *h );\r
+MXBOOL  MXAPI mxSetClip( MXBOOL );\r
+void    MXAPI mxSetClipRegion( MXUINT x, MXUINT y, MXUINT width, MXUINT height );\r
+//\r
+// Graphics\r
+//\r
+void    MXAPI mxBitBlt( MXSINT sx, MXSINT sy, MXUINT width, MXUINT height, MXSINT dx, MXSINT dy );\r
+void    MXAPI mxFillBox( MXSINT x, MXSINT y, MXUINT width, MXUINT height, MXUINT color, MXUINT op );\r
+MXBYTE  MXAPI mxGetPixel( MXSINT x, MXSINT y );\r
+void    MXAPI mxPutPixel( MXSINT x, MXSINT y, MXBYTE color );\r
+void    MXAPI mxLine( MXSINT x1, MXSINT y1, MXSINT x2, MXSINT y2, MXUINT color, MXUINT op );\r
+void    MXAPI mxGetImage( MXPTR img, MXSINT x, MXSINT y, MXUINT width, MXUINT height );\r
+void    MXAPI mxPutImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT op );\r
+void    MXAPI mxPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT width, MXUINT height );\r
+void    MXAPI mxTransPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT w, MXUINT h );\r
+void    MXAPI mxCircle( MXSINT x, MXSINT y, MXUINT radius, MXBYTE color );\r
+void    MXAPI mxStretchImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT neww, MXUINT newh, MXUINT op );\r
+//\r
+// Palette\r
+//\r
+void    MXAPI mxColorToGray( MXPTR source, MXPTR dest, MXUINT count );\r
+void    MXAPI mxGammaCorrect( MXPTR source, MXPTR dest, MXUINT count );\r
+void    MXAPI mxGetColor( MXUINT index, MXSINT far *r, MXSINT far *g, MXSINT far *b );\r
+void    MXAPI mxSetColor( MXUINT index, MXSINT red, MXSINT green, MXSINT blue );\r
+void    MXAPI mxGetPalette( MXPTR palette, MXUINT index, MXUINT count );\r
+void    MXAPI mxSetPalette( MXPTR palette, MXUINT index, MXUINT count );\r
+void    MXAPI mxFadePalette( MXPTR, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT );\r
+void    MXAPI mxRotatePalette( MXPTR palette, MXUINT count, MXSINT step );\r
+//\r
+// Text\r
+//\r
+MXSINT  MXAPI mxSetFont( MXPTR font, MXUINT charwidth, MXUINT charheight );\r
+void    MXAPI mxSetTextColor( MXUINT color, MXUINT op );\r
+void    MXAPI mxGetTextStep( MXSINT far *deltax, MXSINT far *deltay );\r
+void    MXAPI mxSetTextStep( MXSINT deltax, MXSINT deltay );\r
+void    MXAPI mxOutChar( MXSINT x, MXSINT y, char c );\r
+void    MXAPI mxOutText( MXSINT x, MXSINT y, char far *sz );\r
+//\r
+// Convex polygons\r
+//\r
+void    MXAPI mxFillPoly( MXUINT, MXPTR, MXPTR, MXUINT, MXUINT );\r
+void    MXAPI mxGouraudPoly( MXUINT, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT );\r
+void    MXAPI mxTexturePoly( MXUINT, MXPTR, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+//\r
+// Remove temporary defines\r
+//\r
+#undef  MXBYTE\r
+#undef  MXBOOL\r
+#undef  MXSINT\r
+#undef  MXUINT\r
+#undef  MXPTR\r
+#undef  MXAPI\r
+\r
+#endif  // _MODEX_H_\r
diff --git a/16/xw__/modex.lbr b/16/xw__/modex.lbr
new file mode 100755 (executable)
index 0000000..93fc780
--- /dev/null
@@ -0,0 +1,39 @@
++-MXBB.OBJ &\r
++-MXCC.OBJ &\r
++-MXCG.OBJ &\r
++-MXCL.OBJ &\r
++-MXCR.OBJ &\r
++-MXFB.OBJ &\r
++-MXFP.OBJ &\r
++-MXGC.OBJ &\r
++-MXGI.OBJ &\r
++-MXGM.OBJ &\r
++-MXGP.OBJ &\r
++-MXGV.OBJ &\r
++-MXHL.OBJ &\r
++-MXIT.OBJ &\r
++-MXLL.OBJ &\r
++-MXLN.OBJ &\r
++-MXOT.OBJ &\r
++-MXPB.OBJ &\r
++-MXPF.OBJ &\r
++-MXPG.OBJ &\r
++-MXPI.OBJ &\r
++-MXPN.OBJ &\r
++-MXPP.OBJ &\r
++-MXPT.OBJ &\r
++-MXRA.OBJ &\r
++-MXRP.OBJ &\r
++-MXSA.OBJ &\r
++-MXSC.OBJ &\r
++-MXSI.OBJ &\r
++-MXSL.OBJ &\r
++-MXSM.OBJ &\r
++-MXSP.OBJ &\r
++-MXSS.OBJ &\r
++-MXTL.OBJ &\r
++-MXVS.OBJ &\r
++-MXWD.OBJ &\r
++-MXWM.OBJ &\r
++-MXWP.OBJ &\r
++-MXWR.OBJ\r
diff --git a/16/xw__/modex.pas b/16/xw__/modex.pas
new file mode 100755 (executable)
index 0000000..7d9d26e
--- /dev/null
@@ -0,0 +1,194 @@
+(*\r
+   Turbo Pascal interface to the MODEX library\r
+   Copyright (c) 1993,1994 by Alessandro Scotti\r
+*)\r
+unit ModeX;\r
+interface\r
+\r
+const\r
+  (* Video modes *)\r
+  MX_TEXT       = 0;\r
+  MX_320x175    = 1;\r
+  MX_320x200    = 2;\r
+  MX_320x240    = 3;\r
+  MX_320x350    = 4;\r
+  MX_320x400    = 5;\r
+  MX_320x480    = 6;\r
+  MX_360x175    = 7;\r
+  MX_360x200    = 8;\r
+  MX_360x240    = 9;\r
+  MX_360x350    = 10;\r
+  MX_360x400    = 11;\r
+  MX_360x480    = 12;\r
+  MX_400x600    = 13;\r
+\r
+  (* Fade effects *)\r
+  MX_FADEIN     = 0;\r
+  MX_FADEOUT    = 1;\r
+\r
+  (* Raster ops *)\r
+  OP_SET        = 0;\r
+  OP_AND        = 1;\r
+  OP_OR         = 2;\r
+  OP_XOR        = 3;\r
+  OP_TRANS      = 4;\r
+  OP_ADD        = 5;\r
+  OP_MOVE       = 0;                    (* Alias for OP_SET *)\r
+\r
+procedure mxBitBlt( SX, SY: integer; Width, Height: word; DX, DY: integer );\r
+procedure mxCircle( CX, CY: integer; Radius: word; Color: byte );\r
+procedure mxChangeMode( Mode: word );\r
+procedure mxColorToGray( ColorPalette, GrayPalette: pointer; Count: word );\r
+procedure mxFadePalette( Palette: pointer; Cmd, Start, Count, R, G, B: word );\r
+procedure mxFillBox( X, Y: integer; Width, Height: word; Color: byte; Op: word );\r
+procedure mxGammaCorrect( ColorPalette, GammaPalette: pointer; Count: word );\r
+procedure mxGetAspect( var AspectX, AspectY: word );\r
+function  mxGetClipRegion( var X1, Y1, Width, Height: word ): boolean;\r
+function  mxGetClip: boolean;\r
+procedure mxGetImage( Image: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxGetPalette( Palette: pointer; Start, Count: word );\r
+function  mxGetPixel( X, Y: word ): byte;\r
+procedure mxGetScreenSize( var Width, Height: word );\r
+procedure mxGetTextStep( var DeltaX, DeltaY: integer );\r
+function  mxGetVersion: word;\r
+procedure mxGetVirtualScreen( var Width, Height: word );\r
+procedure mxInit;\r
+procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word );\r
+procedure mxOutChar( X, Y: integer; C: char );\r
+procedure mxOutText( X, Y: integer; S: pointer );\r
+procedure mxPan( X, Y: word );\r
+procedure mxPutImage( Image: pointer; X, Y: integer; Width, Height, Op: word );\r
+procedure mxPutPixel( X, Y: word; C: byte );\r
+procedure mxPutTile( Tile: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxReadPlane( Plane: byte );\r
+procedure mxRotatePalette( Palette: pointer; Count: word; Step: integer );\r
+procedure mxRowAddress( RowAddress: byte );\r
+function  mxSetClip( Clip: boolean ): boolean;\r
+procedure mxSetClipRegion( X1, Y1, Width, Height: word );\r
+procedure mxSetColor( Index, R, G, B: word );\r
+procedure mxSetFont( Font: pointer; Width, Height: word );\r
+procedure mxSetMode( Mode: word );\r
+procedure mxSetPalette( Palette: pointer; Start, Count: word );\r
+procedure mxSetTextColor( Color, Op: word );\r
+procedure mxSetTextStep( DeltaX, DeltaY: integer );\r
+procedure mxSetVirtualScreen( Width, Height: word );\r
+procedure mxStretchImage( Image: pointer; X, Y: integer; Width, Height, NewWidth, NewHeight, Op: word );\r
+procedure mxSplitScreen( Line: word );\r
+procedure mxStartAddress( StartAddress: word );\r
+procedure mxStartLine( Line: word );\r
+procedure mxTerm;\r
+procedure mxTransPutTile( Tile: pointer; X, Y: integer; Width, Height: word );\r
+procedure mxWaitDisplay;\r
+procedure mxWaitRetrace;\r
+procedure mxWriteMode( Mode: byte );\r
+procedure mxWritePlane( Plane: byte );\r
+\r
+procedure mxFillPoly( Count: word; var Map, Points; Color: word );\r
+procedure mxGouraudPoly( Count: word; var Map, Points, Colors; BaseColor: word );\r
+procedure mxTexturePoly( Count: word; var Map, Points, ImgPoints, Texture; Width: word );\r
+\r
+procedure mxOutStr( X, Y: integer; S: string );\r
+\r
+implementation\r
+\r
+procedure mxBitBlt;                                             external;\r
+procedure mxChangeMode( Mode: word );                           external;\r
+procedure mxCircle;                                             external;\r
+procedure mxColorToGray;                                        external;\r
+procedure mxFadePalette;                                        external;\r
+procedure mxFillBox;                                            external;\r
+procedure mxGammaCorrect;                                       external;\r
+procedure mxGetAspect( var AspectX, AspectY: word );            external;\r
+function  mxGetClipRegion;                                      external;\r
+function  mxGetClip: boolean;                                   external;\r
+procedure mxGetImage;                                           external;\r
+procedure mxGetPalette( Palette: pointer; Start, Count: word ); external;\r
+function  mxGetPixel( X, Y: word ): byte;                       external;\r
+procedure mxGetScreenSize( var Width, Height: word );           external;\r
+procedure mxGetTextStep( var DeltaX, DeltaY: integer );         external;\r
+function  mxGetVersion: word;                                   external;\r
+procedure mxGetVirtualScreen( var Width, Height: word );        external;\r
+procedure mxInit;                                               external;\r
+procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word );   external;\r
+procedure mxOutChar( X, Y: integer; C: char );                  external;\r
+procedure mxOutText( X, Y: integer; S: pointer );               external;\r
+procedure mxPan( X, Y: word );                                  external;\r
+procedure mxPutImage;                                           external;\r
+procedure mxPutPixel( X, Y: word; C: byte );                    external;\r
+procedure mxPutTile;                                            external;\r
+procedure mxReadPlane( Plane: byte );                           external;\r
+procedure mxRotatePalette;                                      external;\r
+procedure mxRowAddress( RowAddress: byte );                     external;\r
+function  mxSetClip( Clip: boolean ): boolean;                  external;\r
+procedure mxSetClipRegion( X1, Y1, Width, Height: word );       external;\r
+procedure mxSetColor( Index, R, G, B: word );                   external;\r
+procedure mxSetFont( Font: pointer; Width, Height: word );      external;\r
+procedure mxSetMode( Mode: word );                              external;\r
+procedure mxSetPalette( Palette: pointer; Start, Count: word ); external;\r
+procedure mxSetTextColor( Color, Op: word );                    external;\r
+procedure mxSetTextStep( DeltaX, DeltaY: integer );             external;\r
+procedure mxSetVirtualScreen( Width, Height: word );            external;\r
+procedure mxSplitScreen( Line: word );                          external;\r
+procedure mxStartAddress( StartAddress: word );                 external;\r
+procedure mxStartLine;                                          external;\r
+procedure mxStretchImage;                                       external;\r
+procedure mxTerm;                                               external;\r
+procedure mxTransPutTile;                                       external;\r
+procedure mxWaitDisplay;                                        external;\r
+procedure mxWaitRetrace;                                        external;\r
+procedure mxWriteMode( Mode: byte );                            external;\r
+procedure mxWritePlane( Plane: byte );                          external;\r
+\r
+procedure mxFillPoly;                                           external;\r
+procedure mxGouraudPoly;                                        external;\r
+procedure mxTexturePoly;                                        external;\r
+{$L MXPB}\r
+{$L MXPF}\r
+{$L MXPG}\r
+{$L MXPT}\r
+\r
+{$L MXBB}\r
+{$L MXCC}\r
+{$L MXCG}\r
+{$L MXCL}\r
+{$L MXCR}\r
+{$L MXFB}\r
+{$L MXFP}\r
+{$L MXGI}\r
+{$L MXGM}\r
+{$L MXGP}\r
+{$L MXGV}\r
+{$L MXHL}\r
+{$L MXIT}\r
+{$L MXLN}\r
+{$L MXOT}\r
+{$L MXPI}\r
+{$L MXPN}\r
+{$L MXPP}\r
+{$L MXRA}\r
+{$L MXRP}\r
+{$L MXSA}\r
+{$L MXSC}\r
+{$L MXSI}\r
+{$L MXSL}\r
+{$L MXSM}\r
+{$L MXSP}\r
+{$L MXSS}\r
+{$L MXTL}\r
+{$L MXVS}\r
+{$L MXWD}\r
+{$L MXWM}\r
+{$L MXWP}\r
+{$L MXWR}\r
+\r
+(*\r
+   Prints a Turbo Pascal string.\r
+   Note: BP 7.0 supports ASCIIZ strings (PChar type).\r
+*)\r
+procedure mxOutStr;\r
+begin\r
+  S := S + #0;\r
+  mxOutText( X, Y, @S[1] );\r
+end;\r
+\r
+end.\r
diff --git a/16/xw__/modex/DEMO01.EXE b/16/xw__/modex/DEMO01.EXE
new file mode 100755 (executable)
index 0000000..28caff8
Binary files /dev/null and b/16/xw__/modex/DEMO01.EXE differ
diff --git a/16/xw__/modex/DEMO01.PAS b/16/xw__/modex/DEMO01.PAS
new file mode 100755 (executable)
index 0000000..c684acd
--- /dev/null
@@ -0,0 +1,126 @@
+(*\r
+    DEMO01 - Sprites, page flipping and palette rotation\r
+    Copyright (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+  MAX_SPRITE = 100;\r
+type\r
+  (* Sprite structure *)\r
+  TSprite = record\r
+    X, Y : integer;                        (* Sprite coordinates *)\r
+    DX,DY: integer;                        (* Deltas for sprite movement *)\r
+    W, H : integer;                        (* Sprite width and height *)\r
+    Image: array[ 1..16, 1..16 ] of byte;  (* Sprite image data *)\r
+  end;\r
+  (* RGB color structure *)\r
+  TRgb    = record\r
+    R, G, B: byte;\r
+  end;\r
+var\r
+  S      : array[ 1..MAX_SPRITE ] of TSprite;   (* An array of sprites *)\r
+  Palette: array[ byte ] of TRgb;               (* Palette *)\r
+  Page   : word;                                (* Page offset *)\r
+  I      : word;\r
+\r
+(* Initializes a sprite structure *)\r
+procedure sxInit( var S: TSprite );\r
+var\r
+  I: word;\r
+begin\r
+  S.X := Random( 320 );  (* Initialize position with random values *)\r
+  S.Y := Random( 240 );\r
+  S.DX := Random( 7 )-3; (* Initialize speed with random values *)\r
+  S.DY := Random( 7 )-3;\r
+  S.W := 16;             (* Size is fixed in this program *)\r
+  S.H := 16;\r
+  (* The image is a square with a hole inside *)\r
+  FillChar( S.Image, SizeOf(S.Image), Random(15)+1 );\r
+  for I:=5 to 12 do FillChar( S.Image[ I, 5 ], 8, 0 );\r
+end;\r
+\r
+(* Moves a sprite *)\r
+procedure sxMove( var S: TSprite );\r
+begin\r
+  Inc( S.X, S.DX );     (* Get new position *)\r
+  Inc( S.Y, S.DY );\r
+  (* Check sprite position, change delta if needed *)\r
+  if( S.X > 320 ) then begin\r
+    S.X := 320;\r
+    S.DX := -S.DX;\r
+  end;\r
+  if( S.X < -16 ) then begin\r
+    S.X := -16;\r
+    S.DX := -S.DX;\r
+  end;\r
+  if( S.Y > 240 ) then begin\r
+    S.Y := 240;\r
+    S.DY := -S.DY;\r
+  end;\r
+  if( S.Y < -16 ) then begin\r
+    S.Y := -16;\r
+    S.DY := -S.DY;\r
+  end;\r
+  (* Draw the sprite, note the Page offset added to the *)\r
+  (* Y coordinate of the image *)\r
+  mxPutImage( @S.Image, S.X, Page+S.Y, S.W, S.H, OP_TRANS );\r
+end;\r
+\r
+begin\r
+  (* Initialize library *)\r
+  mxInit;\r
+\r
+  (* Enter graphics mode *)\r
+  mxSetMode( MX_320x240 );\r
+\r
+  (* Print initialization message *)\r
+  mxSetTextColor( 15, OP_TRANS );\r
+  mxOutStr( 4, 4, 'Initializing...' );\r
+\r
+  (* Initialize sprites *)\r
+  for I:=1 to MAX_SPRITE do sxInit( S[I] );\r
+\r
+  (* Draw background *)\r
+  for I:=1 to 192 do begin\r
+    mxCircle( 160, 480+120, I, I+63 );\r
+    mxCircle( 161, 480+120, I, I+63 );\r
+  end;\r
+\r
+  (* Compute and set palette *)\r
+  for I:=1 to 192 do with Palette[I+63] do begin\r
+    R := 0;\r
+    G := 0;\r
+    B := 0;\r
+    if( I < 64 ) then\r
+      R := I shr 1+31\r
+    else if( I < 128 ) then\r
+      G := (I-64) shr 1+31\r
+    else\r
+      B := (I-128) shr 1+31;\r
+  end;\r
+  mxSetPalette( @Palette[64], 64, 192 );\r
+\r
+  (* Main loop *)\r
+  Page := 240;\r
+  while( not KeyPressed ) do begin\r
+    (* Set clip region to current page *)\r
+    mxSetClipRegion( 0, Page, 320, 240 );\r
+    mxSetClip( TRUE );\r
+    (* Restore background *)\r
+    mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+    (* Draw sprites *)\r
+    for I:=1 to MAX_SPRITE do sxMove( S[I] );\r
+    (* Print message *)\r
+    mxOutStr( 4, Page+4, 'Some sprites moving...' );\r
+    (* Flip page *)\r
+    mxStartLine( Page );\r
+    Page := 240-Page;\r
+    (* Animate palette *)\r
+    mxSetPalette( @Palette[64], 64, 192 );\r
+    mxRotatePalette( @Palette[64], 192, 3 );\r
+  end;\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw__/modex/DEMO02.EXE b/16/xw__/modex/DEMO02.EXE
new file mode 100755 (executable)
index 0000000..14e7dc7
Binary files /dev/null and b/16/xw__/modex/DEMO02.EXE differ
diff --git a/16/xw__/modex/DEMO02.PAS b/16/xw__/modex/DEMO02.PAS
new file mode 100755 (executable)
index 0000000..6b4fb6f
--- /dev/null
@@ -0,0 +1,125 @@
+(*\r
+    DEMO02 - Texture mapping and palette rotation\r
+    (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Plasma, Threed;\r
+\r
+const\r
+  LSIZE = 85;\r
+  Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+type\r
+  T2DPoint = record\r
+    X, Y: integer;\r
+  end;\r
+  TTexture = record\r
+    Desc   : array[ 0..3 ] of T2DPoint;\r
+    Width  : word;\r
+    Data   : array[ 1..64*64 ] of byte;\r
+  end;\r
+  TQuad = record\r
+    VtxCnt : word;\r
+    Vtx    : array[ 0..3 ] of word;\r
+    Texture: word;\r
+  end;\r
+var\r
+  Vtx   : array[ 0..7 ] of TPoint;\r
+  XVtx  : array[ 0..7 ] of TPoint;\r
+  VVtx  : array[ 0..7 ] of T2DPoint;\r
+  Face  : array[ 0..5 ] of TQuad;\r
+  Txts  : array[ 0..5 ] of TTexture;\r
+  Nrm   : array[ 0..5 ] of TPoint;\r
+  XNrm  : array[ 0..5 ] of TPoint;\r
+  Page  : word;\r
+  Palette: array[ byte ] of record R, G, B: byte; end;\r
+\r
+(* Make a 64x64 plasma to be used as texture *)\r
+procedure MakeTexture( Idx: word );\r
+var\r
+  I: word;\r
+begin\r
+  mxFillBox( 0, 0, 64, 64, 0, OP_SET );\r
+  MakePlasma( 0, 0, 64, 64, 96, Random(192)+1, Random(192)+1, Random(192)+1 );\r
+  mxGetImage( @Txts[Idx].Data, 0, 0, 64, 64 );\r
+  (* Texture vertexes are 8:8 fixed, add $80 (0.5) for best results *)\r
+  with Txts[Idx] do begin\r
+    Desc[0].X := $80; Desc[0].Y := $80;\r
+    Desc[1].X := $80; Desc[1].Y := $3F80;\r
+    Desc[2].X := $3F80; Desc[2].Y := $3F80;\r
+    Desc[3].X := $3F80; Desc[3].Y := $80;\r
+    Width := 64;\r
+  end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+  I: integer;\r
+begin\r
+  (* Build vertexes for a cube *)\r
+  with Vtx[0] do begin X:=-LSIZE; Y:=-LSIZE; Z:=-LSIZE; end;\r
+  with Vtx[1] do begin X:=+LSIZE; Y:=-LSIZE; Z:=-LSIZE; end;\r
+  with Vtx[2] do begin X:=-LSIZE; Y:=+LSIZE; Z:=-LSIZE; end;\r
+  with Vtx[3] do begin X:=+LSIZE; Y:=+LSIZE; Z:=-LSIZE; end;\r
+  with Vtx[4] do begin X:=-LSIZE; Y:=-LSIZE; Z:=+LSIZE; end;\r
+  with Vtx[5] do begin X:=+LSIZE; Y:=-LSIZE; Z:=+LSIZE; end;\r
+  with Vtx[6] do begin X:=-LSIZE; Y:=+LSIZE; Z:=+LSIZE; end;\r
+  with Vtx[7] do begin X:=+LSIZE; Y:=+LSIZE; Z:=+LSIZE; end;\r
+  for I:=0 to 7 do begin          (* Make points 16:16 fixed *)\r
+    Vtx[I].X := Vtx[I].X*$10000;\r
+    Vtx[I].Y := Vtx[I].Y*$10000;\r
+    Vtx[I].Z := Vtx[I].Z*$10000;\r
+  end;\r
+  (* Build faces *)\r
+  with Face[0] do begin Vtx[0]:=0; Vtx[1]:=2; Vtx[2]:=3; Vtx[3]:=1; end;\r
+  with Face[1] do begin Vtx[0]:=4; Vtx[1]:=5; Vtx[2]:=7; Vtx[3]:=6; end;\r
+  with Face[2] do begin Vtx[0]:=0; Vtx[1]:=1; Vtx[2]:=5; Vtx[3]:=4; end;\r
+  with Face[3] do begin Vtx[0]:=1; Vtx[1]:=3; Vtx[2]:=7; Vtx[3]:=5; end;\r
+  with Face[4] do begin Vtx[0]:=2; Vtx[1]:=0; Vtx[2]:=4; Vtx[3]:=6; end;\r
+  with Face[5] do begin Vtx[0]:=7; Vtx[1]:=3; Vtx[2]:=2; Vtx[3]:=6; end;\r
+  for I:=0 to 5 do Face[I].Texture := I;\r
+  (* Build textures and palette *)\r
+  Randomize;\r
+  FillChar( Palette, SizeOf(Palette), 0 );\r
+  MakePlasmaPalette( Palette, PAL_RGB );\r
+  mxSetPalette( @Palette, 0, 193 );\r
+  for I:=0 to 5 do MakeTexture( I );\r
+end;\r
+\r
+var\r
+  AX, AY, AZ: byte;\r
+  I: word;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;          (* Start with hidden page *)\r
+\r
+  AX := 0;\r
+  AY := 0;\r
+  AZ := 0;\r
+  (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+  tdSetTranslation( Trans );\r
+  tdSetPerspective( 400*$10000, $10000, $10000 );\r
+  (* Main loop, all magic here! *)\r
+  while( not KeyPressed ) do begin\r
+    tdSetRotation( AX, AY, AZ );                (* Set new angles *)\r
+    tdTransform( Vtx, XVtx, 8 );                (* 3D transform points *)\r
+    tdTransformToImage( XVtx, VVtx, 8, 160, 120+Page );\r
+    Inc( AX, 1 );                               (* Bump angles *)\r
+    Inc( AY, 1 );\r
+    Inc( AZ, 2 );\r
+    mxSetClipRegion( 0, Page, 320, 240 );       (* Set clip to new page *)\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+    mxRotatePalette( @Palette[1], 192, 3 );     (* Rotate palette *)\r
+    (* Draw cube: backface culling is straighforward in this case, so *)\r
+    (* it can be handled by the polygon filling procedure *)\r
+    for I:=0 to 5 do\r
+      mxTexturePoly( 4, Face[I].Vtx, VVtx, Txts[I].Desc, Txts[I].Data, Txts[I].Width );\r
+    mxStartLine( Page );                        (* Flip pages *)\r
+    mxSetPalette( @Palette[1], 1, 192 );        (* Set new palette *)\r
+    Page := 240-Page;\r
+  end;\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw__/modex/DEMO03.EXE b/16/xw__/modex/DEMO03.EXE
new file mode 100755 (executable)
index 0000000..c646c4b
Binary files /dev/null and b/16/xw__/modex/DEMO03.EXE differ
diff --git a/16/xw__/modex/DEMO03.PAS b/16/xw__/modex/DEMO03.PAS
new file mode 100755 (executable)
index 0000000..01d10f4
--- /dev/null
@@ -0,0 +1,152 @@
+(*\r
+    DEMO03 - Simple star animation, morphs between a cube and a sphere\r
+    (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+const\r
+  MAXVTX = 1000;        (* Number of points *)\r
+  EDGE = 70;            (* Length of cube edge *)\r
+  RADIUS = 90;          (* Radius of sphere *)\r
+  WAITCOUNT = 192;      (* Frames to wait for non-morphing shapes *)\r
+  MS = 32;              (* Number of steps for morphing *)\r
+  Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+  InitMorph1: array[ 0..3 ] of integer = ( 0, MS, 0, 0 );\r
+  InitMorph2: array[ 0..3 ] of integer = ( 0, 0, 0, MS );\r
+  InitDelta1: array[ 0..3 ] of integer = ( 0, -1, 0, +1 );\r
+  InitDelta2: array[ 0..3 ] of integer = ( 0, +1, 0, -1 );\r
+type\r
+  T2DPoint = record\r
+    X, Y: integer;\r
+  end;\r
+  T3DPointArray = array[ 0..MAXVTX-1 ] of TPoint;\r
+  P3DPointArray = ^T3DPointArray;\r
+var\r
+  CubeVtx, SphereVtx, Vtx, XVtx: P3DPointArray;\r
+  VVtx  : array[ 0..MAXVTX-1 ] of T2DPoint;\r
+  Page  : word;\r
+  Status, Count, Delta1, Delta2, Morph1, Morph2: integer;\r
+\r
+procedure Swap( var A, B: longint );\r
+var\r
+  L: longint;\r
+begin\r
+  L := A; A := B; B := L;\r
+end;\r
+\r
+function Toggle( A: longint ): longint;\r
+begin\r
+  Toggle := A;\r
+  if( Random(2) = 0 ) then Toggle := -A;\r
+end;\r
+\r
+procedure Init;\r
+label Retry;\r
+var\r
+  I: integer;\r
+begin\r
+  New( CubeVtx );\r
+  New( SphereVtx );\r
+  New( Vtx );\r
+  New( XVtx );\r
+  (* Build vertexes (yes, I know this piece of code is terrible) *)\r
+  Randomize;\r
+  for I:=0 to MAXVTX-1 do begin\r
+    with CubeVtx^[I] do begin\r
+      (* Build cube *)\r
+      X := (longint(Random(2*EDGE))-EDGE)*$10000;\r
+      Y := (longint(Random(2*EDGE))-EDGE)*$10000;\r
+      Z := Toggle( EDGE*$10000 );\r
+      case Random(3) of\r
+        0: Swap( X, Z );\r
+        1: Swap( Y, Z );\r
+      end;\r
+    end;\r
+    with SphereVtx^[I] do begin\r
+      (* Build sphere *)\r
+Retry:\r
+      X := (longint(Random(2*RADIUS))-RADIUS);\r
+      Y := (longint(Random(2*RADIUS))-RADIUS);\r
+      if( X*X+Y*Y > RADIUS*RADIUS ) then goto Retry;\r
+      Z := Toggle( Round( Sqrt( Abs( RADIUS*RADIUS-X*X-Y*Y ) ) ) );\r
+      case Random(3) of\r
+        0: Swap( X, Z );\r
+        1: Swap( Y, Z );\r
+      end;\r
+      X := X * $10000; Y := Y * $10000; Z := Z * $10000;\r
+    end;\r
+  end;\r
+  (* Initialize morphing *)\r
+  Move( CubeVtx^, Vtx^, SizeOf(Vtx^) );\r
+  Status := 0;\r
+  Count := WAITCOUNT;\r
+end;\r
+\r
+procedure Morph;\r
+var\r
+  I: integer;\r
+begin\r
+  (* Fully unoptimized, slowest loop I could think of! *)\r
+  for I:=0 to MAXVTX-1 do begin\r
+    Vtx^[I].X := ((CubeVtx^[I].X * Morph1)+(SphereVtx^[I].X * Morph2)) div MS;\r
+    Vtx^[I].Y := ((CubeVtx^[I].Y * Morph1)+(SphereVtx^[I].Y * Morph2)) div MS;\r
+    Vtx^[I].Z := ((CubeVtx^[I].Z * Morph1)+(SphereVtx^[I].Z * Morph2)) div MS;\r
+  end;\r
+end;\r
+\r
+var\r
+  AX, AY, AZ: byte;\r
+  I: word;\r
+  C: char;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;          (* Start with hidden page *)\r
+\r
+  AX := 0;\r
+  AY := 0;\r
+  AZ := 0;\r
+  (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+  tdSetTranslation( Trans );\r
+  tdSetPerspective( 400*$10000, $10000, $10000 );\r
+  C := #0;\r
+  repeat\r
+    tdSetRotation( AX, AY, AZ );                (* Set new angles *)\r
+    tdTransform( Vtx^, XVtx^, MAXVTX );         (* 3D transform points *)\r
+    tdTransformToImage( XVtx^, VVtx, MAXVTX, 160, 120+Page );\r
+    Inc( AX, 1 );                               (* Bump angles *)\r
+    Inc( AY, 1 );\r
+    Inc( AZ, 2 );\r
+    mxSetClipRegion( 0, Page, 320, 240 );       (* Set clip to new page *)\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+    (* Draw points *)\r
+    for I:=0 to MAXVTX-1 do\r
+      mxPutPixel( VVtx[I].X, VVtx[I].Y, 128 + XVtx^[I].Z shr 18 );\r
+    mxStartLine( Page );                        (* Flip pages *)\r
+    Page := 240-Page;\r
+    (* Morph *)\r
+    if( Odd(Status) ) then begin\r
+      Morph;\r
+      Inc( Morph1, Delta1 );\r
+      Inc( Morph2, Delta2 );\r
+      if( Morph1 < 0 )or( Morph2 < 0 ) then Inc( Status );\r
+      if( Status = 4 ) then Status := 0;\r
+    end\r
+    else begin\r
+      Dec( Count );\r
+      if( Count < 0 ) then begin\r
+        Inc( Status );\r
+        Count :=  WAITCOUNT;\r
+        Morph1 := InitMorph1[Status];\r
+        Morph2 := InitMorph2[Status];\r
+        Delta1 := InitDelta1[Status];\r
+        Delta2 := InitDelta2[Status];\r
+      end;\r
+    end;\r
+  until( KeyPressed );\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw__/modex/DEMO04.DAT b/16/xw__/modex/DEMO04.DAT
new file mode 100755 (executable)
index 0000000..72aaad0
Binary files /dev/null and b/16/xw__/modex/DEMO04.DAT differ
diff --git a/16/xw__/modex/DEMO04.EXE b/16/xw__/modex/DEMO04.EXE
new file mode 100755 (executable)
index 0000000..1fec5e8
Binary files /dev/null and b/16/xw__/modex/DEMO04.EXE differ
diff --git a/16/xw__/modex/DEMO04.PAS b/16/xw__/modex/DEMO04.PAS
new file mode 100755 (executable)
index 0000000..1a94631
--- /dev/null
@@ -0,0 +1,198 @@
+(*\r
+    DEMO04 - Multiple textures and triple buffering (3 pages)\r
+    (c) 1994 by Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+const\r
+  MAXVTX = 256;\r
+  MAXCUB = 2;\r
+  MAXTXT = 2;\r
+  Trans : TPoint = ( X:0; Y:0; Z:0 );\r
+  TxtSunDial: array[ 0..7 ] of word = (\r
+    $7F80,$0080, $0080,$0080, $0080,$7E80, $7F80,$7E80 );\r
+  TxtSapphire : array[ 0..7 ] of word = (\r
+    $0080,$0080, $0080,$1F80, $1F80,$1F80, $1F80,$0080 );\r
+  TxtMarble: array[ 0..7 ] of word = (\r
+    $0080,$8080, $0080,$FD80, $7F80,$FD80, $7F80,$8080 );\r
+type\r
+  T2DPoint = record\r
+    X, Y: integer;\r
+  end;\r
+  TTexture = record\r
+    Desc   : array[ 0..3 ] of record X, Y: word end;\r
+    Width  : word;\r
+    Data   : pointer;\r
+  end;\r
+  TQuad = record\r
+    Vtx    : array[ 0..3 ] of word;\r
+    Texture: word;\r
+  end;\r
+  TCube    = record\r
+    Face   : array[ 0..5 ] of TQuad;\r
+    Base   : integer;\r
+  end;\r
+var\r
+  Vtx, XVtx: array[ 0..MAXVTX ] of TPoint;\r
+  VVtx     : array[ 0..MAXVTX ] of T2DPoint;\r
+  Cube     : array[ 0..MAXCUB ] of TCube;\r
+  ZList    : array[ 0..MAXCUB ] of integer;\r
+  VtxCnt   : word;\r
+  Txts     : array[ 0..MAXTXT ] of TTexture;\r
+  Page     : word;\r
+  Palette  : array[ byte ] of record R, G, B: byte; end;\r
+  TxtDat1, TxtDat2: pointer;\r
+\r
+(* Add a new entry to the vertex array *)\r
+procedure AddVtx( PX, PY, PZ: longint );\r
+begin\r
+  with Vtx[VtxCnt] do begin X:=PX*$10000; Y:=PY*$10000; Z:=PZ*$10000; end;\r
+  Inc( VtxCnt );\r
+end;\r
+\r
+procedure MakeCube( var C: TCube; X1,Y1,Z1, X2,Y2,Z2, TX,TY,TZ, Texture: integer );\r
+const\r
+  FaceIdx: array[ 0..23 ] of integer = (\r
+    0,1,2,3, 0,4,5,1, 1,5,6,2, 2,6,7,3, 3,7,4,0, 6,5,4,7 );\r
+var\r
+  I, VC: integer;\r
+begin\r
+  VC := VtxCnt;\r
+  C.Base := VC;\r
+  AddVtx( X1+TX, Y1+TY, Z1+TZ );\r
+  AddVtx( X2+TX, Y1+TY, Z1+TZ );\r
+  AddVtx( X2+TX, Y2+TY, Z1+TZ );\r
+  AddVtx( X1+TX, Y2+TY, Z1+TZ );\r
+  AddVtx( X1+TX, Y1+TY, Z2+TZ );\r
+  AddVtx( X2+TX, Y1+TY, Z2+TZ );\r
+  AddVtx( X2+TX, Y2+TY, Z2+TZ );\r
+  AddVtx( X1+TX, Y2+TY, Z2+TZ );\r
+  for I:=0 to 23 do C.Face[I shr 2].Vtx[I and 3] := VC+FaceIdx[I];\r
+  for I:=0 to 5 do C.Face[I].Texture := Texture;\r
+end;\r
+\r
+procedure MakeTexture( Idx: integer; var VtxData );\r
+var\r
+  P: ^word;\r
+  I: integer;\r
+begin\r
+  P := @VtxData;\r
+  with Txts[Idx] do begin\r
+    for I:=0 to 3 do begin\r
+      Desc[I].X := P^; Inc( P );\r
+      Desc[I].Y := P^; Inc( P );\r
+    end;\r
+    Width := 129;\r
+    Data := TxtDat1;\r
+  end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+  I: integer;\r
+  V: integer;\r
+  F: file;\r
+  P: array[ 1..768 ] of byte;\r
+begin\r
+  (* Initialize objects *)\r
+  VtxCnt := 0;\r
+  MakeCube( Cube[0], -64,-64,8, 64,64,-8, 0,0,0, 1 );   (* Sundial *)\r
+  Cube[0].Face[0].Texture := 0;\r
+  V := VtxCnt;\r
+  MakeCube( Cube[1], -16,-16,16, 16,16,-16, 0,0,0, 2 ); (* Sapphire *)\r
+  tdSetTranslation( Trans );\r
+  tdSetRotation( 32, 32, 00 );\r
+  tdRotate( Vtx[V], XVtx[V], 8 );       (* Got to rotate this cube *)\r
+  for I:=V to V+7 do begin\r
+    Vtx[I].X := XVtx[I].X;\r
+    Vtx[I].Y := XVtx[I].Y;\r
+    Vtx[I].Z := XVtx[I].Z + 100*$10000;\r
+  end;\r
+  MakeCube( Cube[2], -64,-4,48, 64,4,-48, 0,68,56, 1 ); (* Marble *)\r
+  (* Load texture and palette *)\r
+  Assign( F, 'DEMO04.DAT' );\r
+  Reset( F, 1 );\r
+  BlockRead( F, P, SizeOf(P) );\r
+  mxSetPalette( @P, 0, 256 );\r
+  GetMem( TxtDat1, 63*1024 );\r
+  BlockRead( F, TxtDat1^, 129*286 );\r
+  Close( F );\r
+  TxtDat2 := Ptr( Seg(TxtDat1^), Ofs(TxtDat1^)+129*254 );\r
+  (* Init textures *)\r
+  MakeTexture( 0, TxtSundial );\r
+  MakeTexture( 1, TxtMarble );\r
+  MakeTexture( 2, TxtSapphire );\r
+  Txts[2].Data := TxtDat2;\r
+end;\r
+\r
+(* Sort procedure, not worth optimizing with only a few objects *)\r
+procedure SortObjects;\r
+var\r
+  I, J, K: integer;\r
+  ZMax: array[ 0..MAXCUB ] of longint;\r
+  ZI: integer;\r
+  L: longint;\r
+begin\r
+  for I:=0 to MAXCUB do begin\r
+    L := XVtx[Cube[I].Base].Z;\r
+    for J:=1 to 7 do\r
+      if( L > XVtx[Cube[I].Base+J].Z ) then L := XVtx[Cube[I].Base+J].Z;\r
+    ZMax[I] := L;\r
+    ZList[I] := I;\r
+  end;\r
+  for I:=0 to MAXCUB-1 do begin\r
+    ZI := I;\r
+    for J:=I+1 to MAXCUB do\r
+      if( ZMax[ZList[J]] > ZMax[ZList[ZI]] ) then ZI := J;\r
+    if( ZI <> I ) then begin\r
+      K := ZList[I];\r
+      ZList[I] := ZList[ZI];\r
+      ZList[ZI] := K;\r
+    end;\r
+  end;\r
+end;\r
+\r
+var\r
+  AX, AY, AZ: byte;\r
+  I, J, K: word;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;          (* Start with hidden page *)\r
+\r
+  (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+  AX := 0; AY := 0; AZ := 0;\r
+  tdSetTranslation( Trans );\r
+  tdSetPerspective( 600*$10000, $10000, $10000 );\r
+  (* Main loop, all magic here! *)\r
+  while( not KeyPressed ) do begin\r
+    tdSetRotation( AX, AY, AZ );                (* Set new angles *)\r
+    tdTransform( Vtx, XVtx, VtxCnt );           (* 3D transform points *)\r
+    tdTransformToImage( XVtx, VVtx, VtxCnt, 160, 120+Page );\r
+    Inc( AX, 1 );                               (* Bump angles *)\r
+    Inc( AY, 2 );\r
+    Inc( AZ, 1 );\r
+    mxSetClipRegion( 0, Page, 320, 240 );       (* Set clip to new page *)\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+    (* Draw objects *)\r
+    SortObjects;\r
+    for I:=0 to MAXCUB do with Cube[ZList[I]] do begin\r
+      for J:=0 to 5 do begin\r
+        K := Face[J].Texture;\r
+        mxTexturePoly( 4, Face[J].Vtx, VVtx, Txts[K].Desc, Txts[K].Data^, Txts[K].Width );\r
+      end;\r
+    end;\r
+    (* Flip page: at 320x240 the Start Address Register Low is always zero *)\r
+    case Page of\r
+      0  : begin PortW[$3D4] := $000C; Page := 240; end;\r
+      240: begin PortW[$3D4] := $4B0C; Page := 480; end;\r
+      480: begin PortW[$3D4] := $960C; Page := 0; end;\r
+    end;\r
+    mxWaitRetrace; (* If the frame rate seems low, try to remove this line *)\r
+  end;\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw__/modex/DEMO05.EXE b/16/xw__/modex/DEMO05.EXE
new file mode 100755 (executable)
index 0000000..21a7c20
Binary files /dev/null and b/16/xw__/modex/DEMO05.EXE differ
diff --git a/16/xw__/modex/DEMO05.PAS b/16/xw__/modex/DEMO05.PAS
new file mode 100755 (executable)
index 0000000..819c5cf
--- /dev/null
@@ -0,0 +1,131 @@
+(*\r
+   DEMO05 - A Gouraud-shaded rotating torus\r
+   (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex, Threed;\r
+\r
+(* Define ALTPAL for alternate palette *)\r
+{$define ALTPAL}\r
+\r
+const\r
+  MAXVTX1 = 15; RADIUS1 = 70;   (* MAXVTX1+1 must be multiple of 4 *)\r
+  MAXVTX2 = 15; RADIUS2 = 30;\r
+  MAXVTX  = (MAXVTX1+1)*(MAXVTX2+1)-1;\r
+  MAXFACE = MAXVTX;\r
+  Trans : TPoint = ( X:0; Y:0; Z:0 );           (* Object translation *)\r
+  Light : TPoint = ( X:0; Y:0; Z:-63*$10000 );  (* Light direction *)\r
+type\r
+  TQuad   = record\r
+    QVtx  : array[ 0..3 ] of integer;\r
+  end;\r
+var\r
+  Vtx, XVtx : array[ 0..MAXVTX ] of TPoint;     (* Points *)\r
+  VVtx      : array[ 0..MAXVTX ] of record X, Y: integer end;\r
+  Face      : array[ 0..MAXFACE ] of TQuad;     (* Polys *)\r
+  Culled    : array[ 0..MAXFACE ] of integer;\r
+  GNrm,XGNrm: array[ 0..MAXVTX ] of TVector;    (* Gouraud normals *)\r
+  VtxLight  : array[ 0..MAXVTX ] of integer;    (* Points brightness *)\r
+  Page      : word;\r
+\r
+function GetVtx( I1, I2: integer ): integer;\r
+begin\r
+  GetVtx := (I1 mod (MAXVTX1+1))*(MAXVTX2+1) + I2 mod (MAXVTX2+1);\r
+end;\r
+\r
+procedure Init;\r
+var\r
+  R, N, X, Y, Z: real;\r
+  I, J, K, V: integer;\r
+begin\r
+  (* Build vertexes *)\r
+  for I:=0 to MAXVTX1 do begin\r
+    K := (I + (MAXVTX1+1) shr 2) mod (MAXVTX1+1);\r
+    R := RADIUS1 + RADIUS2*Cos( 2*K*Pi / (MAXVTX1+1) );\r
+    for J:=0 to MAXVTX2 do begin\r
+      V := I*(MAXVTX2+1)+J;                     (* Index of current vertex *)\r
+      (* Compute coordinates of current vertex *)\r
+      X := R*Cos(2*J*Pi / (MAXVTX2+1));         (* Get coordinates *)\r
+      Y := R*Sin(2*J*Pi / (MAXVTX2+1));\r
+      Z := RADIUS2*Sin(2*K*Pi / (MAXVTX1+1));\r
+      Vtx[V].X := Round( X )*$10000;            (* Save coordinates *)\r
+      Vtx[V].Y := Round( Y )*$10000;\r
+      Vtx[V].Z := Round( Z )*$10000;\r
+      (* Compute direction of Gouraud normal thru current vertex *)\r
+      X := X - RADIUS1*Cos(2*J*Pi / (MAXVTX2+1));\r
+      Y := Y - RADIUS1*Sin(2*J*Pi / (MAXVTX2+1));\r
+      N := Sqrt( X*X + Y*Y + Z*Z );             (* Get vector length *)\r
+      GNrm[V].X := Trunc( X*$10000/N );         (* Save normal vector *)\r
+      GNrm[V].Y := Trunc( Y*$10000/N );\r
+      GNrm[V].Z := Trunc( Z*$10000/N );\r
+    end;\r
+  end;\r
+  (* Generate faces so that depth-sorting is not needed: there are still *)\r
+  (* some *very* little errors, but this is the best I could devise *)\r
+  J := 0;\r
+  K := 0;\r
+  for I:=0 to MAXFACE do with Face[I] do begin\r
+    QVtx[0] := GetVtx( J, K );\r
+    QVtx[1] := GetVtx( J, K+1 );\r
+    QVtx[2] := GetVtx( J+1, K+1 );\r
+    QVtx[3] := GetVtx( J+1, K );\r
+    Inc( K );\r
+    if( K > MAXVTX2 ) then begin\r
+      K := 0;\r
+      Inc( J );\r
+    end;\r
+  end;\r
+{$ifndef ALTPAL}\r
+  for I:=0 to 63 do mxSetColor( I+64, 0, 0, I );     (* Blue palette *)\r
+{$else}\r
+  for I:=0 to 31 do mxSetColor(I+64, 0, I shl 1, 0); (* Green neon palette *)\r
+  for I:=32 to 63 do mxSetColor ( I+64, (I-32) shl 1, 63, (I-32) shl 1 );\r
+{$endif}\r
+end;\r
+\r
+var\r
+  AX, AY, AZ: byte;\r
+  I: word;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;          (* Start with hidden page *)\r
+\r
+  AX := 0;\r
+  AY := 0;\r
+  AZ := 0;\r
+  (* Init 3D transforms, perspective is intentionally exaggerated *)\r
+  tdSetTranslation( Trans );\r
+  tdSetLight( Light );\r
+  tdSetPerspective( 400*$10000, $10000, $10000 );\r
+  (* Main loop, all magic here! *)\r
+  while( not KeyPressed ) do begin\r
+    tdSetRotation( AX, AY, AZ );                (* Set new angles *)\r
+    tdTransform( Vtx, XVtx, MAXVTX+1 );         (* 3D transform points *)\r
+    tdTransformToImage( XVtx, VVtx, MAXVTX+1, 160, 120+Page );\r
+    tdRotate( GNrm, XGNrm, MAXVTX+1 );          (* Rotate Gouraud normals *)\r
+    tdTransformLight( XGNrm, VtxLight, MAXVTX+1 );\r
+    (* Backplane culling is not really needed here! *)\r
+    FillChar( Culled, SizeOf(Culled), 0 );\r
+    tdBackPlaneCull( Face, XVtx, Culled, MAXFACE+1, SizeOf(TQuad) );\r
+    Inc( AX, 1 );                               (* Bump angles *)\r
+    Inc( AY, 2 );\r
+    Inc( AZ, 3 );\r
+    mxSetClipRegion( 0, Page, 320, 240 );       (* Set clip to new page *)\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *)\r
+    (* Draw polygons *)\r
+    for I:=0 to MAXFACE do with Face[I] do\r
+      if( Culled[I] >= 0 ) then mxGouraudPoly( 4, QVtx, VVtx, VtxLight, 64 );\r
+    (* Flip page: at 320x240 the Start Address Register Low is always zero *)\r
+    case Page of\r
+      0  : begin PortW[$3D4] := $000C; Page := 240; end;\r
+      240: begin PortW[$3D4] := $4B0C; Page := 480; end;\r
+      480: begin PortW[$3D4] := $960C; Page := 0; end;\r
+    end;\r
+    mxWaitRetrace; (* Uncomment this instruction if screen flickers *)\r
+  end;\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw__/modex/DEMO06.DAT b/16/xw__/modex/DEMO06.DAT
new file mode 100755 (executable)
index 0000000..1ac2c2b
Binary files /dev/null and b/16/xw__/modex/DEMO06.DAT differ
diff --git a/16/xw__/modex/DEMO06.EXE b/16/xw__/modex/DEMO06.EXE
new file mode 100755 (executable)
index 0000000..f1308e8
Binary files /dev/null and b/16/xw__/modex/DEMO06.EXE differ
diff --git a/16/xw__/modex/DEMO06.PAS b/16/xw__/modex/DEMO06.PAS
new file mode 100755 (executable)
index 0000000..f26af06
--- /dev/null
@@ -0,0 +1,135 @@
+(*\r
+    DEMO06 - Magnifying glass\r
+    (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+  R = 40;               (* Lens radius *)\r
+  K : real = 1.8;       (* Magnifying factor, less makes a stronger lens *)\r
+type\r
+  TLine   = array[ 0..319 ] of byte;\r
+  PLine   = ^TLine;\r
+  TScreen = array[ 0..239 ] of PLine;\r
+var\r
+  VScreen: TScreen;                             (* Virtual screen *)\r
+  BallX  : array[ 0..R, 0..R ] of integer;\r
+  BallY  : array[ 0..R, 0..R ] of integer;\r
+  Sprite : array[ -R..R, -R..R ] of byte;\r
+  Page   : word;\r
+\r
+(* Returns "lens-view" coordinates of X,Y *)\r
+procedure GetCoords( var X, Y: integer );\r
+var\r
+  LR, Z, SinA, SinB, TgB, Q: real;\r
+begin\r
+  LR := Sqrt( X*X + Y*Y );\r
+  if( LR = 0 ) then Exit;\r
+  if( LR < R ) then begin\r
+    Z := Sqrt( R*R - LR*LR );\r
+    SinA := LR / R;\r
+    SinB := SinA / K;\r
+    TgB := SinB / Sqrt( 1-SinB*SinB );\r
+    Q := LR - TgB*Z;\r
+    X := Round( X * ( Q/LR ) );\r
+    Y := Round( Y * ( Q/LR ) );\r
+  end;\r
+end;\r
+\r
+procedure Init;\r
+var\r
+  F      : file;\r
+  Palette: array[ 0..767 ] of record R, G, B: byte; end;\r
+  X, Y,\r
+  X2, Y2 : integer;\r
+begin\r
+  (* Load background image *)\r
+  Assign( F, 'demo06.dat' );\r
+  Reset( F, 1 );\r
+  BlockRead( F, Palette, 768 );\r
+  mxSetPalette( @Palette, 0, 256 );\r
+  for Y:=0 to 239 do begin\r
+    New( VScreen[Y] );\r
+    BlockRead( F, VScreen[Y]^, 320 );\r
+    mxPutImage( VScreen[Y], 0, 480+Y, 320, 1, OP_MOVE );\r
+  end;\r
+  Close( F );\r
+  (* Build lens *)\r
+  for X:=0 to R do begin\r
+    for Y:=0 to R do begin\r
+      X2 := X;\r
+      Y2 := Y;\r
+      GetCoords( X2, Y2 );\r
+      BallX[X, Y] := X2;\r
+      BallY[X, Y] := Y2;\r
+    end;\r
+  end;\r
+end;\r
+\r
+procedure PutLens( OX, OY: integer );\r
+var\r
+  X, Y: integer;\r
+begin\r
+  for X:=0 to R do begin\r
+    for Y:=0 to R do begin\r
+      Sprite[Y][X] := VScreen[ OY+BallY[X,Y] ]^[ OX+BallX[X,Y] ];\r
+      Sprite[Y][-X] := VScreen[ OY+BallY[X,Y] ]^[ OX-BallX[X,Y] ];\r
+      Sprite[-Y][X] := VScreen[ OY-BallY[X,Y] ]^[ OX+BallX[X,Y] ];\r
+      Sprite[-Y][-X] := VScreen[ OY-BallY[X,Y] ]^[ OX-BallX[X,Y] ];\r
+    end;\r
+  end;\r
+  (* Draw the sprite *)\r
+  mxPutImage( @Sprite, OX-R, OY-R+Page, 2*R+1, 2*R+1, OP_MOVE );\r
+end;\r
+\r
+function Delta: integer;\r
+begin\r
+  Delta := Random(3)+2;\r
+end;\r
+\r
+procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer );\r
+begin\r
+  if( Cond ) then begin\r
+    Coord := NewCoord;\r
+    DeltaC := Sign*Delta;\r
+  end;\r
+end;\r
+\r
+var\r
+  X, Y, DX, DY: integer;\r
+  C: char;\r
+begin\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  Init;\r
+  Page := 240;\r
+  X := R;\r
+  Y := R;\r
+  Randomize;\r
+  DX := Delta;\r
+  DY := Delta;\r
+\r
+  (* Main loop *)\r
+  repeat\r
+    (* Update video *)\r
+    mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+    PutLens( X, Y );\r
+    mxCircle( X, Page+Y, R, 0 );\r
+    (* Update lens coordinates *)\r
+    Inc( X, DX );\r
+    Check( X+R >= 319, X, DX, 319-R, -1 );\r
+    Check( X <= R, X, DX, R, +1 );\r
+    Inc( Y, DY );\r
+    Check( Y+R >= 239, Y, DY, 239-R, -1 );\r
+    Check( Y <= R, Y, DY, R, +1 );\r
+    (* Flip pages: double buffering, avoid wait for display *)\r
+    case Page of\r
+      0  : begin PortW[$3D4] := $000C; Page := 240; end;\r
+      240: begin PortW[$3D4] := $4B0C; Page := 0; end;\r
+    end;\r
+    mxWaitRetrace; (* Wait for hidden page to show *)\r
+  until( KeyPressed );\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw__/modex/DEMO07.EXE b/16/xw__/modex/DEMO07.EXE
new file mode 100755 (executable)
index 0000000..8a40116
Binary files /dev/null and b/16/xw__/modex/DEMO07.EXE differ
diff --git a/16/xw__/modex/DEMO07.PAS b/16/xw__/modex/DEMO07.PAS
new file mode 100755 (executable)
index 0000000..04fff79
--- /dev/null
@@ -0,0 +1,68 @@
+(*\r
+    DEMO07 - Hardware scrolling\r
+    Copyright (c) 1994 Alessandro Scotti\r
+*)\r
+uses Crt, Modex;\r
+\r
+const\r
+  (* Change this if scrolling seems jerky (this simple program does *)\r
+  (* not handle vertical retrace/display very well) *)\r
+  STEPS = 5;\r
+\r
+procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer );\r
+begin\r
+  if( Cond ) then begin\r
+    Coord := NewCoord;\r
+    DeltaC := Sign*(Random(3)+2);\r
+  end;\r
+end;\r
+\r
+var\r
+  I, X, Y, DX, DY: integer;\r
+begin\r
+  (* Initialize library and graphics mode *)\r
+  mxInit;\r
+  mxSetMode( MX_320x200 );\r
+  (* Set a 640x400 virtual screen *)\r
+  mxSetVirtualScreen( 640, 400 );\r
+  mxSetClip( TRUE );\r
+\r
+  X := 0;\r
+  Y := 0;\r
+  DX := 1;\r
+  DY := 1;\r
+\r
+  (* Main loop: draw lines, circles, points and rectangles in separate *)\r
+  (* 320x200 windows, while smoothly panning virtual screen *)\r
+  while( not KeyPressed ) do begin\r
+    (* Points *)\r
+    mxSetClipRegion( 0, 0, 320, 200 );\r
+    for I:=1 to STEPS do\r
+      mxPutPixel( Random(320), Random(200), Random(16) );\r
+    (* Lines *)\r
+    mxSetClipRegion( 0, 200, 320, 200 );\r
+    for I:=1 to STEPS do\r
+      mxLine( Random(320), Random(200)+200, Random(320), Random(200)+200, Random(16), OP_SET );\r
+    (* Circles *)\r
+    mxSetClipRegion( 320, 0, 320, 200 );\r
+    for I:=1 to STEPS do\r
+      mxCircle( Random(320)+320, Random(200), Random(100), Random(16) );\r
+    (* Boxes *)\r
+    mxSetClipRegion( 320, 200, 320, 200 );\r
+    for I:=1 to STEPS do\r
+      mxFillBox( Random(320)+320, Random(200)+200, Random(100)+1, Random(100)+1, Random(16), OP_SET );\r
+    (* Pan *)\r
+    Inc( X, DX );\r
+    Check( X+320 >= 639, X, DX, 319, -1 );\r
+    Check( X < 0, X, DX, 0, +1 );\r
+    Inc( Y, DY );\r
+    Check( Y+200 >= 399, Y, DY, 199, -1 );\r
+    Check( Y < 0, Y, DY, 0, +1 );\r
+    mxPan( X, Y );\r
+    mxWaitRetrace;\r
+  end;\r
+\r
+  (* Shutdown *)\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw__/modex/MATH.INC b/16/xw__/modex/MATH.INC
new file mode 100755 (executable)
index 0000000..742af41
--- /dev/null
@@ -0,0 +1,34 @@
+;\r
+; MATH.INC - Include file for THREED.ASM\r
+;\r
+\r
+; 3-dimensional point, coordinates in fixed format (16:16)\r
+;\r
+TPOINT  STRUC\r
+        X       DD      ?\r
+        Y       DD      ?\r
+        Z       DD      ?\r
+TPOINT  ENDS\r
+\r
+; 2-dimensional point, coordinates in integer format\r
+;\r
+TIMAGEPOINT     STRUC\r
+        IX      DW      ?\r
+        IY      DW      ?\r
+TIMAGEPOINT     ENDS\r
+\r
+; Fixed-point divide: EAX = EAX / arg\r
+;\r
+.xdiv   MACRO   arg\r
+        xor     edx, edx\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    arg\r
+ENDM\r
+\r
+; Fixed-point multiply: EAX = EAX * arg\r
+;\r
+.xmul   MACRO   arg\r
+        imul    arg\r
+        shrd    eax, edx, 16\r
+ENDM\r
diff --git a/16/xw__/modex/PLASMA.PAS b/16/xw__/modex/PLASMA.PAS
new file mode 100755 (executable)
index 0000000..237e292
--- /dev/null
@@ -0,0 +1,103 @@
+unit Plasma;\r
+interface\r
+\r
+const\r
+  PAL_RGB       = 0;\r
+  PAL_CLOUDS    = 1;\r
+  PAL_LANDSCAPE = 2;\r
+\r
+procedure MakePlasma( X, Y: integer; W, H: word; C1, C2, C3, C4: byte );\r
+procedure MakePlasmaPalette( var Palette; What: word );\r
+\r
+implementation uses Modex;\r
+\r
+procedure NewColor( XA, YA, X, Y, XB, YB: integer );\r
+var\r
+  Color: longint;\r
+begin\r
+  Color := Abs( XA-XB )+Abs( YA-YB );\r
+  Color := Random( Color shl 1 )-Color;\r
+  Color := (Color+mxGetPixel( XA, YA )+mxGetPixel( XB, YB )+1) shr 1;\r
+  if( Color < 1 ) then Color := 1;\r
+  if( Color > 192 ) then Color := 192;\r
+  if( mxGetPixel( X, Y ) = 0 ) then\r
+    mxPutPixel( X, Y, Lo(Color) );\r
+end;\r
+\r
+procedure Divide( X1, Y1, X2, Y2: integer );\r
+var\r
+  X, Y, Color: integer;\r
+begin\r
+  if not( (X2-X1<2)and(Y2-Y1<2) ) then begin\r
+    X := (X1+X2) shr 1;\r
+    Y := (Y1+Y2) shr 1;\r
+    NewColor( X1, Y1, X, Y1, X2, Y1 );\r
+    NewColor( X2, Y1, X2, Y, X2, Y2 );\r
+    NewColor( X1, Y2, X, Y2, X2, Y2 );\r
+    NewColor( X1, Y1, X1, Y, X1, Y2 );\r
+    Color := (mxGetPixel( X1, Y1 )+mxGetPixel( X2, Y1 )+\r
+              mxGetPixel( X2, Y2 )+mxGetPixel( X1, Y2 )) shr 2;\r
+    mxPutPixel( X, Y, Color );\r
+    Divide( X1, Y1, X, Y );\r
+    Divide( X, Y1, X2, Y );\r
+    Divide( X, Y, X2, Y2 );\r
+    Divide( X1, Y, X, Y2 );\r
+  end;\r
+end;\r
+\r
+procedure MakePlasma;\r
+begin\r
+  Dec( W );\r
+  Dec( H );\r
+  mxPutPixel( X, Y, C1 );\r
+  mxPutPixel( X, Y+H, C2 );\r
+  mxPutPixel( X+W, Y+H, C3 );\r
+  mxPutPixel( X+W, Y, C4 );\r
+  Divide( X, Y, X+W, Y+H );\r
+end;\r
+\r
+procedure MakePlasmaPalette;\r
+type\r
+  TPal = array[ byte ] of record R, G, B: byte end;\r
+var\r
+  I: word;\r
+begin\r
+  FillChar( TPal(Palette)[1], 192*3, 0 );\r
+  case What of\r
+    PAL_CLOUDS:\r
+      for I:=1 to 192 do begin\r
+        TPal(Palette)[I].R := Abs( I-96 )*63 div 96;\r
+        TPal(Palette)[I].G := Abs( I-96 )*63 div 96;\r
+        TPal(Palette)[I].B := 63;\r
+      end;\r
+    PAL_LANDSCAPE:\r
+      begin\r
+        for I:=0 to 31 do begin\r
+          TPal(Palette)[I+1].R := I;\r
+          TPal(Palette)[I+1].G := I;\r
+          TPal(Palette)[I+1].B := I + I shr 1+15;\r
+        end;\r
+        for I:=32 to 63 do begin\r
+          TPal(Palette)[I+1].R := 0;\r
+          TPal(Palette)[I+1].G := I;\r
+          TPal(Palette)[I+1].B := 0;\r
+        end;\r
+        for I:=64 to 191 do begin\r
+          TPal(Palette)[I+1].R := (I-64) div 3 + 15;\r
+          TPal(Palette)[I+1].G := (I-64) div 3 + 15;\r
+          TPal(Palette)[I+1].B := (I-64) div 3 + 15;\r
+        end;\r
+      end;\r
+    else\r
+      for I:=1 to 64 do begin\r
+        TPal(Palette)[I].G := I-1;\r
+        TPal(Palette)[I].B := 64-I;\r
+        TPal(Palette)[I+64].R := I-1;\r
+        TPal(Palette)[I+64].G := 64-I;\r
+        TPal(Palette)[I+128].B := I-1;\r
+        TPal(Palette)[I+128].R := 64-I;\r
+      end;\r
+  end;\r
+end;\r
+\r
+end.
\ No newline at end of file
diff --git a/16/xw__/modex/QIX2.EXE b/16/xw__/modex/QIX2.EXE
new file mode 100755 (executable)
index 0000000..a10d7db
Binary files /dev/null and b/16/xw__/modex/QIX2.EXE differ
diff --git a/16/xw__/modex/QIX2.PAS b/16/xw__/modex/QIX2.PAS
new file mode 100755 (executable)
index 0000000..d1b5979
--- /dev/null
@@ -0,0 +1,210 @@
+{$E-,N+}\r
+uses Crt, Modex;\r
+\r
+const\r
+  DEFVERT = 12;         (* Vertex count *)\r
+  DEFREPL = 3;          (* Repetition count *)\r
+  DEFQIXS = 2;          (* Qixs *)\r
+  FADESPEED = 48;\r
+type\r
+  TPoint = record\r
+    X, Y : integer;\r
+  end;\r
+  TRGB = record\r
+    R, G, B: byte;\r
+  end;\r
+  TQix = record\r
+    Color: integer;\r
+    Vert : array[ 0..DEFVERT-1, 0..DEFREPL-1 ] of TPoint;\r
+    Delta: array[ 0..DEFVERT-1 ] of TPoint;\r
+  end;\r
+var\r
+  Page : integer;\r
+  MaxX,\r
+  MaxY : word;\r
+  Qix  : array[ 0..DEFQIXS-1 ] of TQix;\r
+  Pal  : array[ byte ] of TRGB;\r
+\r
+type\r
+  TReal = double;\r
+  TRPoint = record\r
+    X, Y: TReal;\r
+  end;\r
+  TMatrix = array[ 0..3, 0..3 ] of TReal;\r
+var\r
+  M: TMatrix;\r
+  G: array[ 0..DEFVERT-1 ] of TRPoint;\r
+  C: array[ 0..DEFVERT-1 ] of TRPoint;\r
+\r
+procedure BumpPal( Idx, DR, DG, DB, Steps: integer );\r
+var\r
+  I: integer;\r
+begin\r
+  for I:=1 to Steps do begin\r
+    Pal[Idx+1].R := Pal[Idx].R + DR;\r
+    Pal[Idx+1].G := Pal[Idx].G + DG;\r
+    Pal[Idx+1].B := Pal[Idx].B + DB;\r
+    Inc( Idx );\r
+  end;\r
+end;\r
+\r
+procedure InitPalette;\r
+begin\r
+  with Pal[0] do begin R:=0; G:=0; B:=0; end;\r
+  with Pal[1] do begin R:=0; G:=0; B:=62; end;\r
+  BumpPal( 1,   0, 2, -2,  31 );\r
+  BumpPal( 32,  2, -2, 0,  31 );\r
+  BumpPal( 63,  -2, 2, 2,  31 );\r
+  BumpPal( 94,  2, 0, -2,  31 );\r
+  BumpPal( 125, -2, -2, 2, 31 );\r
+end;\r
+\r
+procedure Init( var Qix: TQix; Color: integer );\r
+var\r
+  I: integer;\r
+begin\r
+  FillChar( Qix.Vert, SizeOf(Qix.Vert), 0 );\r
+  for I:=0 to DEFVERT-1 do begin\r
+    Qix.Vert[I, DEFREPL-1].X := Random( MaxX );\r
+    Qix.Vert[I, DEFREPL-1].Y := Random( MaxY );\r
+    Qix.Delta[I].X := Random(5)+1;\r
+    Qix.Delta[I].Y := Random(5)+1;\r
+  end;\r
+  Qix.Color := Color;\r
+\r
+  (* Initialize matrix (Catmull-Rom) *)\r
+  M[0,0] := -1/2; M[0,1] := 3/2; M[0,2] := -3/2; M[0,3] := 1/2;\r
+  M[1,0] := 1; M[1,1] := -5/2; M[1,2] := 2; M[1,3] := -1/2;\r
+  M[2,0] := -1/2; M[2,1] := 0; M[2,2] := 1/2; M[2,3] := 0;\r
+  M[3,0] := 0; M[3,1] := 1; M[3,2] := 0; M[3,3] := 0;\r
+end;\r
+\r
+procedure mxBezier( var Qix: TQix; I0, Idx, N: integer );\r
+var\r
+  I, J: integer;\r
+  T, T2, T3: TReal;\r
+  X0, Y0, X, Y: TReal;\r
+  Delta: TReal;\r
+begin\r
+  (* Compute coefficients *)\r
+  for I:=0 to 3 do begin\r
+    C[I].X := 0;\r
+    for J:=0 to 3 do C[I].X := C[I].X + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].X;\r
+    C[I].Y := 0;\r
+    for J:=0 to 3 do C[I].Y := C[I].Y + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].Y;\r
+  end;\r
+  X0 := C[3].X;\r
+  Y0 := C[3].Y;\r
+  Delta := 1 / N;\r
+  T := 0;\r
+  for I:=1 to N do begin\r
+    T := T + Delta;\r
+    T2 := T*T;\r
+    T3 := T*T2;\r
+    X := C[0].X*T3 + C[1].X*T2 + C[2].X*T + C[3].X;\r
+    Y := C[0].Y*T3 + C[1].Y*T2 + C[2].Y*T + C[3].Y;\r
+    mxLine( Round(X0), Page+Round(Y0), Round(X), Page+Round(Y), Qix.Color, OP_SET );\r
+    X0 := X;\r
+    Y0 := Y;\r
+  end;\r
+end;\r
+\r
+procedure Plot( var Qix: TQix; Idx: integer );\r
+var\r
+  I, J: integer;\r
+begin\r
+  for I:=0 to DEFVERT-1 do begin\r
+    mxBezier( Qix, I, Idx, 12 );\r
+  end;\r
+end;\r
+\r
+procedure Update( var Qix: TQix; Idx: integer );\r
+var\r
+  I: integer;\r
+begin\r
+  for I:=0 to DEFVERT-1 do with Qix do begin\r
+    Inc( Vert[I,Idx].X, Delta[I].X );\r
+    if( Vert[I,Idx].X < 0 ) then begin\r
+      Vert[I,Idx].X := 0;\r
+      Delta[I].X := Random( 5 )+1;\r
+    end;\r
+    if( Vert[I,Idx].X > MaxX ) then begin\r
+      Vert[I,Idx].X := MaxX;\r
+      Delta[I].X := -Random( 5 )-1;\r
+    end;\r
+    Inc( Vert[I,Idx].Y, Delta[I].Y );\r
+    if( Vert[I,Idx].Y < 0 ) then begin\r
+      Vert[I,Idx].Y := 0;\r
+      Delta[I].Y := Random( 5 )+1;\r
+    end;\r
+    if( Vert[I,Idx].Y > MaxY ) then begin\r
+      Vert[I,Idx].Y := MaxY;\r
+      Delta[I].Y := -Random( 5 )-1;\r
+    end;\r
+  end;\r
+end;\r
+\r
+procedure Copy( var Qix: TQix; Dest, Src: integer );\r
+var\r
+  I: integer;\r
+begin\r
+  for I:=0 to DEFVERT-1 do with Qix do begin\r
+    Vert[I,Dest].X := Vert[I,Src].X;\r
+    Vert[I,Dest].Y := Vert[I,Src].Y;\r
+  end;\r
+end;\r
+\r
+procedure AnimateQix;\r
+var\r
+  Q, Idx, I, J, P, Count: integer;\r
+begin\r
+  Count := 0;\r
+  P := DEFREPL-1;\r
+  I := 0;\r
+  J := 1;\r
+  repeat\r
+    mxSetClipRegion( 0, Page, MaxX+1, MaxY+1 );\r
+    mxSetClip( TRUE );\r
+    mxFillBox( 0, Page, MaxX+1, MaxY+1, 0, OP_SET );\r
+    for Q:=0 to DEFQIXS-1 do begin\r
+      Copy( Qix[Q], I, P );\r
+      Update( Qix[Q], I );\r
+      for Idx:=0 to DEFREPL-1 do begin\r
+        Plot( Qix[Q], Idx );\r
+      end;\r
+    end;\r
+    I := (I+1) mod DEFREPL;\r
+    J := (J+1) mod DEFREPL;\r
+    P := (P+1) mod DEFREPL;\r
+    Inc( Count );\r
+    mxStartLine( Page );\r
+    if( Count >= FADESPEED ) then begin\r
+      for Q:=0 to DEFQIXS-1 do begin\r
+        Inc( Qix[Q].Color );\r
+        if( Qix[Q].Color > 156 ) then\r
+          Qix[Q].Color := 1;\r
+      end;\r
+      Count := 0;\r
+    end;\r
+    Page := 240-Page;\r
+  until( KeyPressed );\r
+end;\r
+\r
+var\r
+  I: integer;\r
+begin\r
+  Randomize;\r
+  mxInit;\r
+  mxSetMode( MX_320x240 );\r
+  mxGetScreenSize( MaxX, MaxY );\r
+  for I:=0 to DEFQIXS-1 do\r
+    Init( Qix[I], (I*(155 div DEFQIXS)) mod 155 + 1 );\r
+  InitPalette;\r
+  mxSetPalette( @Pal, 0, 157 );\r
+  Page := 240;\r
+  Dec( MaxX );\r
+  Dec( MaxY );\r
+  AnimateQix;\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw__/modex/README.TXT b/16/xw__/modex/README.TXT
new file mode 100755 (executable)
index 0000000..306e8b9
--- /dev/null
@@ -0,0 +1,8 @@
+ModeX - A graphical library for DOS programs\r
+Copyright (c) 1993-1994 Alessandro Scotti\r
+http://www.ascotti.org/\r
+\r
+Please look at the above site in the "Art of..." and\r
+then in the "Old programs" section for more information.\r
+\r
+\r
diff --git a/16/xw__/modex/SINCOS.INC b/16/xw__/modex/SINCOS.INC
new file mode 100755 (executable)
index 0000000..6986eee
--- /dev/null
@@ -0,0 +1,518 @@
+;\r
+; SINCOS.INC - Sin/cos tables for THREED.ASM\r
+;\r
+\r
+tblSin  LABEL DWORD\r
+  DD    0\r
+  DD    411733\r
+  DD    823219\r
+  DD    1234209\r
+  DD    1644455\r
+  DD    2053710\r
+  DD    2461729\r
+  DD    2868265\r
+  DD    3273072\r
+  DD    3675909\r
+  DD    4076531\r
+  DD    4474698\r
+  DD    4870169\r
+  DD    5262706\r
+  DD    5652074\r
+  DD    6038037\r
+  DD    6420363\r
+  DD    6798821\r
+  DD    7173184\r
+  DD    7543226\r
+  DD    7908725\r
+  DD    8269459\r
+  DD    8625213\r
+  DD    8975771\r
+  DD    9320922\r
+  DD    9660458\r
+  DD    9994176\r
+  DD    10321873\r
+  DD    10643353\r
+  DD    10958422\r
+  DD    11266890\r
+  DD    11568571\r
+  DD    11863283\r
+  DD    12150850\r
+  DD    12431097\r
+  DD    12703856\r
+  DD    12968963\r
+  DD    13226258\r
+  DD    13475586\r
+  DD    13716797\r
+  DD    13949745\r
+  DD    14174291\r
+  DD    14390298\r
+  DD    14597637\r
+  DD    14796184\r
+  DD    14985817\r
+  DD    15166424\r
+  DD    15337895\r
+  DD    15500126\r
+  DD    15653022\r
+  DD    15796488\r
+  DD    15930439\r
+  DD    16054795\r
+  DD    16169479\r
+  DD    16274424\r
+  DD    16369565\r
+  DD    16454846\r
+  DD    16530216\r
+  DD    16595628\r
+  DD    16651044\r
+  DD    16696429\r
+  DD    16731757\r
+  DD    16757007\r
+  DD    16772163\r
+  DD    16777216\r
+  DD    16772163\r
+  DD    16757007\r
+  DD    16731757\r
+  DD    16696429\r
+  DD    16651044\r
+  DD    16595628\r
+  DD    16530216\r
+  DD    16454846\r
+  DD    16369565\r
+  DD    16274424\r
+  DD    16169479\r
+  DD    16054795\r
+  DD    15930439\r
+  DD    15796488\r
+  DD    15653022\r
+  DD    15500126\r
+  DD    15337895\r
+  DD    15166424\r
+  DD    14985817\r
+  DD    14796184\r
+  DD    14597637\r
+  DD    14390298\r
+  DD    14174291\r
+  DD    13949745\r
+  DD    13716797\r
+  DD    13475586\r
+  DD    13226258\r
+  DD    12968963\r
+  DD    12703856\r
+  DD    12431097\r
+  DD    12150850\r
+  DD    11863283\r
+  DD    11568571\r
+  DD    11266890\r
+  DD    10958422\r
+  DD    10643353\r
+  DD    10321873\r
+  DD    9994176\r
+  DD    9660458\r
+  DD    9320922\r
+  DD    8975771\r
+  DD    8625213\r
+  DD    8269459\r
+  DD    7908725\r
+  DD    7543226\r
+  DD    7173184\r
+  DD    6798821\r
+  DD    6420363\r
+  DD    6038037\r
+  DD    5652074\r
+  DD    5262706\r
+  DD    4870169\r
+  DD    4474698\r
+  DD    4076531\r
+  DD    3675909\r
+  DD    3273072\r
+  DD    2868265\r
+  DD    2461729\r
+  DD    2053710\r
+  DD    1644455\r
+  DD    1234209\r
+  DD    823219\r
+  DD    411733\r
+  DD    0\r
+  DD    -411733\r
+  DD    -823219\r
+  DD    -1234209\r
+  DD    -1644455\r
+  DD    -2053710\r
+  DD    -2461729\r
+  DD    -2868265\r
+  DD    -3273072\r
+  DD    -3675909\r
+  DD    -4076531\r
+  DD    -4474698\r
+  DD    -4870169\r
+  DD    -5262706\r
+  DD    -5652074\r
+  DD    -6038037\r
+  DD    -6420363\r
+  DD    -6798821\r
+  DD    -7173184\r
+  DD    -7543226\r
+  DD    -7908725\r
+  DD    -8269459\r
+  DD    -8625213\r
+  DD    -8975771\r
+  DD    -9320922\r
+  DD    -9660458\r
+  DD    -9994176\r
+  DD    -10321873\r
+  DD    -10643353\r
+  DD    -10958422\r
+  DD    -11266890\r
+  DD    -11568571\r
+  DD    -11863283\r
+  DD    -12150850\r
+  DD    -12431097\r
+  DD    -12703856\r
+  DD    -12968963\r
+  DD    -13226258\r
+  DD    -13475586\r
+  DD    -13716797\r
+  DD    -13949745\r
+  DD    -14174291\r
+  DD    -14390298\r
+  DD    -14597637\r
+  DD    -14796184\r
+  DD    -14985817\r
+  DD    -15166424\r
+  DD    -15337895\r
+  DD    -15500126\r
+  DD    -15653022\r
+  DD    -15796488\r
+  DD    -15930439\r
+  DD    -16054795\r
+  DD    -16169479\r
+  DD    -16274424\r
+  DD    -16369565\r
+  DD    -16454846\r
+  DD    -16530216\r
+  DD    -16595628\r
+  DD    -16651044\r
+  DD    -16696429\r
+  DD    -16731757\r
+  DD    -16757007\r
+  DD    -16772163\r
+  DD    -16777216\r
+  DD    -16772163\r
+  DD    -16757007\r
+  DD    -16731757\r
+  DD    -16696429\r
+  DD    -16651044\r
+  DD    -16595628\r
+  DD    -16530216\r
+  DD    -16454846\r
+  DD    -16369565\r
+  DD    -16274424\r
+  DD    -16169479\r
+  DD    -16054795\r
+  DD    -15930439\r
+  DD    -15796488\r
+  DD    -15653022\r
+  DD    -15500126\r
+  DD    -15337895\r
+  DD    -15166424\r
+  DD    -14985817\r
+  DD    -14796184\r
+  DD    -14597637\r
+  DD    -14390298\r
+  DD    -14174291\r
+  DD    -13949745\r
+  DD    -13716797\r
+  DD    -13475586\r
+  DD    -13226258\r
+  DD    -12968963\r
+  DD    -12703856\r
+  DD    -12431097\r
+  DD    -12150850\r
+  DD    -11863283\r
+  DD    -11568571\r
+  DD    -11266890\r
+  DD    -10958422\r
+  DD    -10643353\r
+  DD    -10321873\r
+  DD    -9994176\r
+  DD    -9660458\r
+  DD    -9320922\r
+  DD    -8975771\r
+  DD    -8625213\r
+  DD    -8269459\r
+  DD    -7908725\r
+  DD    -7543226\r
+  DD    -7173184\r
+  DD    -6798821\r
+  DD    -6420363\r
+  DD    -6038037\r
+  DD    -5652074\r
+  DD    -5262706\r
+  DD    -4870169\r
+  DD    -4474698\r
+  DD    -4076531\r
+  DD    -3675909\r
+  DD    -3273072\r
+  DD    -2868265\r
+  DD    -2461729\r
+  DD    -2053710\r
+  DD    -1644455\r
+  DD    -1234209\r
+  DD    -823219\r
+  DD    -411733\r
+tblCos  LABEL DWORD\r
+  DD    16777216\r
+  DD    16772163\r
+  DD    16757007\r
+  DD    16731757\r
+  DD    16696429\r
+  DD    16651044\r
+  DD    16595628\r
+  DD    16530216\r
+  DD    16454846\r
+  DD    16369565\r
+  DD    16274424\r
+  DD    16169479\r
+  DD    16054795\r
+  DD    15930439\r
+  DD    15796488\r
+  DD    15653022\r
+  DD    15500126\r
+  DD    15337895\r
+  DD    15166424\r
+  DD    14985817\r
+  DD    14796184\r
+  DD    14597637\r
+  DD    14390298\r
+  DD    14174291\r
+  DD    13949745\r
+  DD    13716797\r
+  DD    13475586\r
+  DD    13226258\r
+  DD    12968963\r
+  DD    12703856\r
+  DD    12431097\r
+  DD    12150850\r
+  DD    11863283\r
+  DD    11568571\r
+  DD    11266890\r
+  DD    10958422\r
+  DD    10643353\r
+  DD    10321873\r
+  DD    9994176\r
+  DD    9660458\r
+  DD    9320922\r
+  DD    8975771\r
+  DD    8625213\r
+  DD    8269459\r
+  DD    7908725\r
+  DD    7543226\r
+  DD    7173184\r
+  DD    6798821\r
+  DD    6420363\r
+  DD    6038037\r
+  DD    5652074\r
+  DD    5262706\r
+  DD    4870169\r
+  DD    4474698\r
+  DD    4076531\r
+  DD    3675909\r
+  DD    3273072\r
+  DD    2868265\r
+  DD    2461729\r
+  DD    2053710\r
+  DD    1644455\r
+  DD    1234209\r
+  DD    823219\r
+  DD    411733\r
+  DD    0\r
+  DD    -411733\r
+  DD    -823219\r
+  DD    -1234209\r
+  DD    -1644455\r
+  DD    -2053710\r
+  DD    -2461729\r
+  DD    -2868265\r
+  DD    -3273072\r
+  DD    -3675909\r
+  DD    -4076531\r
+  DD    -4474698\r
+  DD    -4870169\r
+  DD    -5262706\r
+  DD    -5652074\r
+  DD    -6038037\r
+  DD    -6420363\r
+  DD    -6798821\r
+  DD    -7173184\r
+  DD    -7543226\r
+  DD    -7908725\r
+  DD    -8269459\r
+  DD    -8625213\r
+  DD    -8975771\r
+  DD    -9320922\r
+  DD    -9660458\r
+  DD    -9994176\r
+  DD    -10321873\r
+  DD    -10643353\r
+  DD    -10958422\r
+  DD    -11266890\r
+  DD    -11568571\r
+  DD    -11863283\r
+  DD    -12150850\r
+  DD    -12431097\r
+  DD    -12703856\r
+  DD    -12968963\r
+  DD    -13226258\r
+  DD    -13475586\r
+  DD    -13716797\r
+  DD    -13949745\r
+  DD    -14174291\r
+  DD    -14390298\r
+  DD    -14597637\r
+  DD    -14796184\r
+  DD    -14985817\r
+  DD    -15166424\r
+  DD    -15337895\r
+  DD    -15500126\r
+  DD    -15653022\r
+  DD    -15796488\r
+  DD    -15930439\r
+  DD    -16054795\r
+  DD    -16169479\r
+  DD    -16274424\r
+  DD    -16369565\r
+  DD    -16454846\r
+  DD    -16530216\r
+  DD    -16595628\r
+  DD    -16651044\r
+  DD    -16696429\r
+  DD    -16731757\r
+  DD    -16757007\r
+  DD    -16772163\r
+  DD    -16777216\r
+  DD    -16772163\r
+  DD    -16757007\r
+  DD    -16731757\r
+  DD    -16696429\r
+  DD    -16651044\r
+  DD    -16595628\r
+  DD    -16530216\r
+  DD    -16454846\r
+  DD    -16369565\r
+  DD    -16274424\r
+  DD    -16169479\r
+  DD    -16054795\r
+  DD    -15930439\r
+  DD    -15796488\r
+  DD    -15653022\r
+  DD    -15500126\r
+  DD    -15337895\r
+  DD    -15166424\r
+  DD    -14985817\r
+  DD    -14796184\r
+  DD    -14597637\r
+  DD    -14390298\r
+  DD    -14174291\r
+  DD    -13949745\r
+  DD    -13716797\r
+  DD    -13475586\r
+  DD    -13226258\r
+  DD    -12968963\r
+  DD    -12703856\r
+  DD    -12431097\r
+  DD    -12150850\r
+  DD    -11863283\r
+  DD    -11568571\r
+  DD    -11266890\r
+  DD    -10958422\r
+  DD    -10643353\r
+  DD    -10321873\r
+  DD    -9994176\r
+  DD    -9660458\r
+  DD    -9320922\r
+  DD    -8975771\r
+  DD    -8625213\r
+  DD    -8269459\r
+  DD    -7908725\r
+  DD    -7543226\r
+  DD    -7173184\r
+  DD    -6798821\r
+  DD    -6420363\r
+  DD    -6038037\r
+  DD    -5652074\r
+  DD    -5262706\r
+  DD    -4870169\r
+  DD    -4474698\r
+  DD    -4076531\r
+  DD    -3675909\r
+  DD    -3273072\r
+  DD    -2868265\r
+  DD    -2461729\r
+  DD    -2053710\r
+  DD    -1644455\r
+  DD    -1234209\r
+  DD    -823219\r
+  DD    -411733\r
+  DD    0\r
+  DD    411733\r
+  DD    823219\r
+  DD    1234209\r
+  DD    1644455\r
+  DD    2053710\r
+  DD    2461729\r
+  DD    2868265\r
+  DD    3273072\r
+  DD    3675909\r
+  DD    4076531\r
+  DD    4474698\r
+  DD    4870169\r
+  DD    5262706\r
+  DD    5652074\r
+  DD    6038037\r
+  DD    6420363\r
+  DD    6798821\r
+  DD    7173184\r
+  DD    7543226\r
+  DD    7908725\r
+  DD    8269459\r
+  DD    8625213\r
+  DD    8975771\r
+  DD    9320922\r
+  DD    9660458\r
+  DD    9994176\r
+  DD    10321873\r
+  DD    10643353\r
+  DD    10958422\r
+  DD    11266890\r
+  DD    11568571\r
+  DD    11863283\r
+  DD    12150850\r
+  DD    12431097\r
+  DD    12703856\r
+  DD    12968963\r
+  DD    13226258\r
+  DD    13475586\r
+  DD    13716797\r
+  DD    13949745\r
+  DD    14174291\r
+  DD    14390298\r
+  DD    14597637\r
+  DD    14796184\r
+  DD    14985817\r
+  DD    15166424\r
+  DD    15337895\r
+  DD    15500126\r
+  DD    15653022\r
+  DD    15796488\r
+  DD    15930439\r
+  DD    16054795\r
+  DD    16169479\r
+  DD    16274424\r
+  DD    16369565\r
+  DD    16454846\r
+  DD    16530216\r
+  DD    16595628\r
+  DD    16651044\r
+  DD    16696429\r
+  DD    16731757\r
+  DD    16757007\r
+  DD    16772163\r
diff --git a/16/xw__/modex/THREED.ASM b/16/xw__/modex/THREED.ASM
new file mode 100755 (executable)
index 0000000..5ecd3ba
--- /dev/null
@@ -0,0 +1,872 @@
+COMMENT /\r
+        Fixed-point math functions and 3D transforms\r
+        Copyright (c) 1993,94 by Alessandro Scotti\r
+/\r
+WARN    PRO\r
+P386\r
+JUMPS\r
+LOCALS\r
+\r
+INCLUDE MATH.INC\r
+\r
+PUBLIC  tdFixedMul\r
+PUBLIC  tdGetNormal\r
+PUBLIC  tdRotate\r
+PUBLIC  tdGetSurfaceLight\r
+PUBLIC  tdSetLight\r
+PUBLIC  tdSetRotation\r
+PUBLIC  tdSetTranslation\r
+PUBLIC  tdTransform\r
+PUBLIC  tdTransformToImage\r
+PUBLIC  tdTransformLight\r
+PUBLIC  tdBackPlaneCull\r
+PUBLIC  tdSetPerspective\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Data segment\r
+;\r
+MATH_DATA       SEGMENT USE16 PARA PUBLIC 'DATA'\r
+                ASSUME ds:MATH_DATA\r
+\r
+INCLUDE         SINCOS.INC              ; Fixed 8:24 sin/cos table\r
+\r
+XRotation       TPOINT  <>              ; 3x3 rotation matrix\r
+YRotation       TPOINT  <>\r
+ZRotation       TPOINT  <>\r
+\r
+Translation     TPOINT  <>              ; Translation vector\r
+\r
+Light           TPOINT  <>              ; Light vector\r
+AmbientLight    DW      00              ; Ambient light\r
+\r
+XScale                  DD      10000h  ; Scaling factor for X coordinate\r
+YScale                  DD      10000h  ; Scaling factor for Y coordinate\r
+PerspectiveDistance     DD      20000000h\r
+\r
+MATH_DATA       ENDS\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Code segment\r
+;\r
+MATH_TEXT       SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MATH_TEXT, es:NOTHING, fs:NOTHING\r
+\r
+tdSetPerspective        PROC PASCAL FAR\r
+        ARG     Perspective:DWORD,      \\r
+                ScaleX:DWORD,           \\r
+                ScaleY:DWORD\r
+        USES    ds\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        mov     eax, [Perspective]\r
+        mov     [PerspectiveDistance], eax\r
+        mov     eax, [ScaleX]\r
+        mov     [XScale], eax\r
+        mov     eax, [ScaleY]\r
+        mov     [YScale], eax\r
+\r
+        ret\r
+tdSetPerspective        ENDP\r
+\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the rotation matrix.\r
+;\r
+; Input:\r
+;       RX      = X-axis rotation angle\r
+;       RY      = X-axis rotation angle\r
+;       RZ      = X-axis rotation angle\r
+; Output:\r
+;       none\r
+;\r
+tdSetRotation   PROC PASCAL FAR\r
+        ARG     RX:WORD,        \\r
+                RY:WORD,        \\r
+                RZ:WORD\r
+        USES    ds, si, di\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        mov     bx, [RZ]\r
+        mov     si, [RY]\r
+        mov     di, [RX]\r
+        shl     bx, 2\r
+        shl     si, 2\r
+        shl     di, 2\r
+\r
+        push    ebp                     ; We use EBP as a scratch register\r
+\r
+; Set X rotation\r
+        mov     eax, tblCos[bx]\r
+        imul    tblCos[si]\r
+        mov     [XRotation.X], edx\r
+\r
+        mov     eax, tblSin[bx]\r
+        imul    tblCos[si]\r
+        mov     [XRotation.Y], edx\r
+\r
+        mov     eax, tblSin[si]\r
+        sar     eax, 8                  ; Convert fixed 8:24 to fixed 16:16\r
+        mov     [XRotation.Z], eax\r
+\r
+; Set Y rotation\r
+        mov     eax, tblCos[bx]\r
+        imul    tblSin[si]              ; EDX:EAX = fixed 16:48\r
+        shrd    eax, edx, 24            ; EAX = fixed 8:24\r
+        imul    tblSin[di]              ; EDX:EAX = fixed 16:48\r
+        mov     ebp, eax\r
+        mov     ecx, edx\r
+        mov     eax, tblSin[bx]\r
+        imul    tblCos[di]\r
+        add     eax, ebp\r
+        adc     edx, ecx                ; EDX:EAX = fixed 16:48\r
+        neg     edx\r
+        mov     [YRotation.X], edx\r
+\r
+        mov     eax, tblSin[bx]\r
+        imul    tblSin[si]\r
+        shrd    eax, edx, 24\r
+        imul    tblSin[di]\r
+        mov     ebp, eax\r
+        mov     ecx, edx\r
+        mov     eax, tblCos[bx]\r
+        imul    tblCos[di]\r
+        sub     eax, ebp\r
+        sbb     edx, ecx\r
+        mov     [YRotation.Y], edx\r
+\r
+        mov     eax, tblCos[si]\r
+        imul    tblSin[di]\r
+        mov     [YRotation.Z], edx\r
+\r
+; Set Z rotation\r
+        mov     eax, tblCos[bx]\r
+        imul    tblSin[si]\r
+        shrd    eax, edx, 24\r
+        imul    tblCos[di]\r
+        mov     ebp, eax\r
+        mov     ecx, edx\r
+        mov     eax, tblSin[bx]\r
+        imul    tblSin[di]\r
+        sub     eax, ebp\r
+        sbb     edx, ecx\r
+        mov     [ZRotation.X], edx\r
+\r
+        mov     eax, tblSin[bx]\r
+        imul    tblSin[si]\r
+        shrd    eax, edx, 24\r
+        imul    tblCos[di]\r
+        mov     ebp, eax\r
+        mov     ecx, edx\r
+        mov     eax, tblCos[bx]\r
+        imul    tblSin[di]\r
+        add     eax, ebp\r
+        add     edx, ecx\r
+        neg     edx\r
+        mov     [ZRotation.Y], edx\r
+\r
+        mov     eax, tblCos[si]\r
+        imul    tblCos[di]\r
+        mov     [ZRotation.Z], edx\r
+\r
+        pop     ebp                     ; Restore EBP\r
+\r
+        ret\r
+tdSetRotation   ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the translation vector.\r
+;\r
+; Input:\r
+;       TV      = pointer to translation vector\r
+; Output:\r
+;       none\r
+;\r
+tdSetTranslation        PROC PASCAL FAR\r
+        ARG     TV:DWORD\r
+        USES    ds, es, di\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        les     di, [TV]\r
+        mov     eax, es:[di].X\r
+        mov     [Translation.X], eax\r
+        mov     eax, es:[di].Y\r
+        mov     [Translation.Y], eax\r
+        mov     eax, es:[di].Z\r
+        mov     [Translation.Z], eax\r
+\r
+        ret\r
+tdSetTranslation        ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Transforms an array of TPOINT.\r
+;\r
+; Input:\r
+;       Source  = pointer to source array of TPOINT\r
+;       Dest    = pointer to destination array of TPOINT\r
+;       Count   = number of entries to transform\r
+; Output:\r
+;       none\r
+;\r
+tdTransform     PROC PASCAL FAR\r
+        ARG     Source:DWORD,   \\r
+                Dest:DWORD,     \\r
+                Count:WORD\r
+        LOCAL   Adjust:DWORD\r
+        USES    ds, si, es, di, fs\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        lfs     si, [Source]\r
+        les     di, [Dest]\r
+\r
+        ALIGN   DWORD\r
+@@Loop:\r
+; Transform Z coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [ZRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [ZRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [ZRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        mov     ebx, eax\r
+        shrd    eax, edx, 16\r
+        add     eax, [Translation.Z]    ; EAX = new Z coord (fixed 16:16)\r
+        mov     es:[di].Z, eax\r
+; Get perspective factor\r
+        mov     ebx, [PerspectiveDistance]\r
+        sub     eax, ebx\r
+        neg     eax                     ; EAX = PD - Z\r
+        xor     edx, edx\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    ebx                     ; EAX = fixed 16:16 result\r
+        mov     [Adjust], eax\r
+\r
+; Transform X coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [XRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [XRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [XRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        add     eax, [Translation.X]\r
+        imul    [Adjust]\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].X, eax\r
+\r
+; Transform Y coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [YRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [YRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [YRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        add     eax, [Translation.Y]\r
+        imul    [Adjust]\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].Y, eax\r
+\r
+        add     si, SIZE TPOINT\r
+        add     di, SIZE TPOINT\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        ret\r
+tdTransform     ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Transforms an array of TPOINT into an array of TIMAGEPOINT.\r
+;\r
+; Input:\r
+;       Source  = pointer to source array of TPOINT\r
+;       Dest    = pointer to destination array of TIMAGEPOINT\r
+;       Count   = number of entries to transform\r
+;       DeltaX  = translation distance for the X coordinate\r
+;       DeltaY  = translation distance for the Y coordinate\r
+; Output:\r
+;       the maximum Z value\r
+;\r
+tdTransformToImage      PROC PASCAL FAR\r
+        ARG     Source:DWORD,   \\r
+                Dest:DWORD,     \\r
+                Count:WORD,     \\r
+                DeltaX:WORD,    \\r
+                DeltaY:WORD\r
+        LOCAL   Adjust:DWORD,   \\r
+                Max:DWORD\r
+        USES    ds, si, es, di, fs\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        lfs     si, [Source]\r
+        les     di, [Dest]\r
+        mov     [Max], 80000000h\r
+\r
+@@Loop:\r
+; Check max Z\r
+        mov     eax, fs:[si].Z\r
+        cmp     eax, [Max]\r
+        jle     @@1\r
+        mov     [Max], eax\r
+@@1:\r
+\r
+; Transform X coordinate\r
+        mov     ax, WORD PTR fs:[si].X[2]\r
+        add     ax, [DeltaX]\r
+        mov     es:[di].IX, ax\r
+\r
+; Transform Y coordinate\r
+        mov     ax, WORD PTR fs:[si].Y[2]\r
+        add     ax, [DeltaY]\r
+        mov     es:[di].IY, ax\r
+\r
+        add     si, SIZE TPOINT\r
+        add     di, SIZE TIMAGEPOINT\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        mov     eax, [Max]\r
+        shld    edx, eax, 16\r
+        ret\r
+tdTransformToImage      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the light source.\r
+;\r
+; Input:\r
+;       Light   = pointer to light vector\r
+; Output:\r
+;       none\r
+;\r
+tdSetLight      PROC PASCAL FAR\r
+        ARG     L:DWORD\r
+        USES    ds, es, di\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        les     di, [L]\r
+        mov     eax, es:[di].X\r
+        mov     [Light.X], eax\r
+        mov     eax, es:[di].Y\r
+        mov     [Light.Y], eax\r
+        mov     eax, es:[di].Z\r
+        mov     [Light.Z], eax\r
+\r
+        ret\r
+tdSetLight      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Computes light intensity for an array of surfaces.\r
+;\r
+; Input:\r
+;       Normals = pointer to an array of surface normals\r
+;       Lights  = pointer to an array of integer to be filled with\r
+;                 light intensity\r
+;       Count   = number of elements to transform\r
+; Output:\r
+;       none\r
+;\r
+tdTransformLight        PROC PASCAL FAR\r
+        ARG     Normals:DWORD,  \\r
+                Lights:DWORD,   \\r
+                Count:WORD\r
+        USES    ds, si, es, di, fs\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     fs, ax\r
+        ASSUME  fs:MATH_DATA\r
+\r
+        lds     si, [Normals]\r
+        les     di, [Lights]\r
+        ASSUME  ds:NOTHING\r
+\r
+; Intensity is given by the dot product between the Light vector and\r
+; the surface normal\r
+@@Loop:\r
+        mov     eax, ds:[si].Z\r
+        imul    [Light.Z]\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, ds:[si].Y\r
+        imul    [Light.Y]\r
+        add     ebx, eax\r
+        adc     ecx, edx\r
+        mov     eax, ds:[si].X\r
+        imul    [Light.X]\r
+        add     eax, ebx\r
+        adc     edx, ecx                ; EDX:EAX = fixed 32:32 intensity\r
+        add     dx, [AmbientLight]\r
+        test    dx, dx\r
+        jg      @@1\r
+        xor     dx, dx                  ; Return 0 for no light\r
+@@1:\r
+        mov     es:[di], dx\r
+        inc     di\r
+        inc     di\r
+        add     si, SIZE TPOINT\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        ASSUME  fs:NOTHING\r
+        ret\r
+tdTransformLight        ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns the light value given the normal to a surface.\r
+;\r
+; Input:\r
+;       Normal  = pointer to TPOINT surface normal vector\r
+; Output:\r
+;       AX      = light intensity (>=0)\r
+; Notes:\r
+;       the normal is rotated according to the current setting.\r
+;\r
+tdGetSurfaceLight       PROC PASCAL FAR\r
+        ARG     Normal:DWORD\r
+        USES    ds, esi, es, di\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        les     di, [Normal]\r
+\r
+; Transform Z coordinate\r
+        mov     eax, es:[di].X\r
+        imul    [ZRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, es:[di].Y\r
+        imul    [ZRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, es:[di].Z\r
+        imul    [ZRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        imul    [Light.Z]\r
+        shrd    eax, edx, 16\r
+        mov     esi, eax\r
+\r
+; Transform X coordinate\r
+        mov     eax, es:[di].X\r
+        imul    [XRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, es:[di].Y\r
+        imul    [XRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, es:[di].Z\r
+        imul    [XRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        imul    [Light.X]\r
+        shrd    eax, edx, 16\r
+        add     esi, eax\r
+\r
+; Transform Y coordinate\r
+        mov     eax, es:[di].X\r
+        imul    [YRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, es:[di].Y\r
+        imul    [YRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, es:[di].Z\r
+        imul    [YRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        imul    [Light.X]\r
+        shrd    eax, edx, 16\r
+        add     eax, esi\r
+        shr     eax, 16\r
+\r
+; Add ambient light\r
+        add     ax, [AmbientLight]\r
+        test    ax, ax\r
+        jge     @@Exit\r
+        xor     ax, ax\r
+\r
+@@Exit:\r
+        ret\r
+tdGetSurfaceLight       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Rotates an array of TPOINT.\r
+;\r
+; Input:\r
+;       Source  = pointer to source array of TPOINT\r
+;       Dest    = pointer to destination array of TPOINT\r
+;       Count   = number of entries to transform\r
+; Output:\r
+;       none\r
+;\r
+tdRotate        PROC PASCAL FAR\r
+        ARG     Source:DWORD,   \\r
+                Dest:DWORD,     \\r
+                Count:WORD\r
+        USES    ds, si, es, di, fs\r
+\r
+        mov     ax, SEG MATH_DATA\r
+        mov     ds, ax\r
+        ASSUME  ds:MATH_DATA\r
+\r
+        lfs     si, [Source]\r
+        les     di, [Dest]\r
+\r
+@@Loop:\r
+; Transform Z coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [ZRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [ZRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [ZRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].Z, eax\r
+\r
+; Transform X coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [XRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [XRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [XRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].X, eax\r
+\r
+; Transform Y coordinate\r
+        mov     eax, fs:[si].X\r
+        imul    [YRotation.X]\r
+        mov     ecx, eax\r
+        mov     ebx, edx\r
+        mov     eax, fs:[si].Y\r
+        imul    [YRotation.Y]\r
+        add     ecx, eax\r
+        adc     ebx, edx\r
+        mov     eax, fs:[si].Z\r
+        imul    [YRotation.Z]\r
+        add     eax, ecx\r
+        adc     edx, ebx\r
+        shrd    eax, edx, 16\r
+        mov     es:[di].Y, eax\r
+\r
+        add     si, SIZE TPOINT\r
+        add     di, SIZE TPOINT\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        ret\r
+tdRotate        ENDP\r
+\r
+tdFixedMul      PROC PASCAL FAR\r
+        ARG     F1:DWORD,       \\r
+                F2:DWORD\r
+\r
+        mov     eax, [F1]\r
+        imul    [F2]\r
+        shr     eax, 16\r
+\r
+        ret\r
+tdFixedMul      ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Returns in EAX the square root of EDX:EAX.\r
+;\r
+subSqrt PROC NEAR\r
+        push    esi\r
+        push    edi\r
+\r
+        add     eax, eax\r
+        adc     edx, 0\r
+        mov     eax, edx                ; Just discard the low bits\r
+\r
+        mov     esi, eax\r
+        xor     edi, edi\r
+        shld    edi, esi, 16\r
+        shl     esi, 16\r
+@@Loop:\r
+        mov     ebx, eax\r
+        mul     eax\r
+        add     eax, esi\r
+        adc     edx, edi\r
+        shrd    eax, edx, 1\r
+        shr     edx, 1\r
+        div     ebx\r
+        cmp     eax, ebx\r
+        jne     @@Loop\r
+\r
+; Adjust EAX\r
+        shl     eax, 8\r
+\r
+        pop     edi\r
+        pop     esi\r
+        ret\r
+subSqrt ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Finds the unitary normal to a given surface.\r
+;\r
+; Input:\r
+;       Dest            = pointer to TPOINT (vector) result\r
+;       P1, P2, P3      = pointer to TPOINT points on surface\r
+; Output:\r
+;       none\r
+; Notes:\r
+;       the normal is given by the cross-product between (P3-P1) and\r
+;       (P2-P1), so its orientation depends on the parameters order.\r
+;\r
+tdGetNormal     PROC PASCAL FAR\r
+        ARG     Dest:DWORD,     \\r
+                P1:DWORD,       \\r
+                P2:DWORD,       \\r
+                P3:DWORD\r
+        LOCAL   V1:TPOINT,      \\r
+                V2:TPOINT,      \\r
+                N:TPOINT\r
+        USES    ds, si, es, di\r
+\r
+; Get vector V1\r
+        lds     si, [P1]\r
+        les     di, [P3]\r
+        mov     eax, es:[di].X\r
+        sub     eax, ds:[si].X\r
+        mov     [V1.X], eax\r
+        mov     eax, es:[di].Y\r
+        sub     eax, ds:[si].Y\r
+        mov     [V1.Y], eax\r
+        mov     eax, es:[di].Z\r
+        sub     eax, ds:[si].Z\r
+        mov     [V1.Z], eax\r
+\r
+; Get vector V2\r
+        les     di, [P2]\r
+        mov     eax, es:[di].X\r
+        sub     eax, ds:[si].X\r
+        mov     [V2.X], eax\r
+        mov     eax, es:[di].Y\r
+        sub     eax, ds:[si].Y\r
+        mov     [V2.Y], eax\r
+        mov     eax, es:[di].Z\r
+        sub     eax, ds:[si].Z\r
+        mov     [V2.Z], eax\r
+\r
+; Get normal vector (V1 x V2)\r
+        mov     eax, [V1.Z]\r
+        imul    [V2.Y]\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, [V1.Y]\r
+        imul    [V2.Z]\r
+        sub     eax, ebx\r
+        sbb     edx, ecx\r
+        shrd    eax, edx, 16\r
+        mov     [N.X], eax\r
+\r
+        mov     eax, [V1.X]\r
+        imul    [V2.Z]\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, [V1.Z]\r
+        imul    [V2.X]\r
+        sub     eax, ebx\r
+        sbb     edx, ecx\r
+        shrd    eax, edx, 16\r
+        mov     [N.Y], eax\r
+\r
+        mov     eax, [V1.Y]\r
+        imul    [V2.X]\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, [V1.X]\r
+        imul    [V2.Y]\r
+        sub     eax, ebx\r
+        sbb     edx, ecx\r
+        shrd    eax, edx, 16\r
+        mov     [N.Z], eax\r
+\r
+; Get normal length\r
+        mov     eax, [N.X]\r
+        imul    eax\r
+        mov     ebx, eax\r
+        mov     ecx, edx\r
+        mov     eax, [N.Y]\r
+        imul    eax\r
+        add     ebx, eax\r
+        adc     ecx, edx\r
+        mov     eax, [N.Z]\r
+        imul    eax\r
+        add     eax, ebx\r
+        adc     edx, ecx                ; EDX:EAX = N.X*N.X + N.Y*N.Y + N.Z*N.Z\r
+        call    subSqrt                 ; EAX = normal length\r
+        mov     ebx, eax\r
+\r
+; Adjust vector and save it\r
+        les     di, [Dest]\r
+        mov     eax, [N.X]\r
+        cdq\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    ebx\r
+        mov     es:[di].X, eax\r
+        mov     eax, [N.Y]\r
+        cdq\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    ebx\r
+        mov     es:[di].Y, eax\r
+        mov     eax, [N.Z]\r
+        cdq\r
+        shld    edx, eax, 16\r
+        shl     eax, 16\r
+        idiv    ebx\r
+        mov     es:[di].Z, eax\r
+\r
+        ret\r
+tdGetNormal     ENDP\r
+\r
+TPOLY   STRUC\r
+        Vtx     DW      4 DUP(?)\r
+TPOLY   ENDS\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Performs surface removal on an array of polygons.\r
+;\r
+; Input:\r
+;       Poly    = pointer to an array of TPOLY\r
+;       Vertex  = pointer to an array of TPOINT\r
+;       Dest    = pointer to an array of integer\r
+;       Count   = number of polygons to check\r
+;       Step    = size of TPOLY structure\r
+; Output:\r
+;       if the n-th polygon is invisible the n-th entry of the\r
+;       Dest array is set to -1, other entries are not modified\r
+;       (so it's possible to use the Light array for Dest, because\r
+;       the light intensity is always >= 0)\r
+;\r
+tdBackPlaneCull PROC PASCAL FAR\r
+        ARG     Step:WORD,      \\r
+                Poly:DWORD,     \\r
+                Vertex:DWORD,   \\r
+                Dest:DWORD,     \\r
+                Count:WORD\r
+        USES    ds, si, es, di, fs\r
+        ASSUME  ds:NOTHING\r
+\r
+        mov     ds, WORD PTR Vertex[2]\r
+        les     di, [Poly]\r
+        mov     fs, WORD PTR Dest[2]\r
+\r
+@@Loop:\r
+        mov     ax, es:[di].Vtx[2]      ; Index of 2nd vertex\r
+        shl     ax, 2\r
+        mov     bx, ax\r
+        shl     ax, 1\r
+        add     bx, ax                  ; BX = index*SIZE TPOINT\r
+        add     bx, WORD PTR [Vertex]   ; BX = offset of 2nd vertex\r
+        mov     ax, es:[di].Vtx[4]      ; Index of 3rd vertex\r
+        shl     ax, 2\r
+        mov     si, ax\r
+        shl     ax, 1\r
+        add     si, ax\r
+        add     si, WORD PTR [Vertex]   ; SI = offset of 3rd vertex\r
+        mov     ecx, ds:[si].X\r
+        sub     ecx, ds:[bx].X          ; ECX = V3.X-V2.X\r
+        mov     edx, ds:[si].Y\r
+        sub     edx, ds:[bx].Y          ; EDX = V3.Y-V2.Y\r
+        mov     ax, es:[di].Vtx[0]      ; Index of 1st vertex\r
+        shl     ax, 2\r
+        mov     si, ax\r
+        shl     ax, 1\r
+        add     si, ax\r
+        add     si, WORD PTR [Vertex]   ; SI = offset of 1st vertex\r
+        mov     eax, ds:[si].X\r
+        sub     eax, ds:[bx].X          ; EAX = V1.X-V2.X\r
+        mov     esi, ds:[si].Y\r
+        sub     esi, ds:[bx].Y          ; ESI = V1.Y-V2.Y\r
+        imul    edx\r
+        mov     ebx, eax\r
+        xchg    ecx, edx                ; ECX:EBX = (V1.X-V2.X)*(V3.Y-V2.Y)\r
+        mov     eax, esi\r
+        imul    edx                     ; EDX:EAX = (V1.Y-V2.Y)*(V3.X-V2.X)\r
+        sub     eax, ebx\r
+        sbb     edx, ecx\r
+        jl      @@Next                  ; Polygon is visible\r
+        mov     bx, WORD PTR [Dest]     ; FS:BX -> current Dest entry\r
+        mov     WORD PTR fs:[bx], -1    ; Remove polygon\r
+@@Next:\r
+        add     WORD PTR [Dest], 2      ; Next entry for dest\r
+        add     di, [Step]              ; Next polygon\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+        ret\r
+tdBackPlaneCull ENDP\r
+\r
+MATH_TEXT       ENDS\r
+END\r
diff --git a/16/xw__/modex/THREED.H b/16/xw__/modex/THREED.H
new file mode 100755 (executable)
index 0000000..b993ef8
--- /dev/null
@@ -0,0 +1,32 @@
+typedef struct {\r
+    long    x, y, z;\r
+} TVECTOR;\r
+\r
+#define PVECTOR TVECTOR far *\r
+\r
+#define TPOINT  TVECTOR\r
+#define PPOINT  PVECTOR\r
+\r
+#define VPTR    void far *\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+long far pascal tdFixedMul( long, long );\r
+int  far pascal tdGetSurfaceLight( PPOINT );\r
+long far pascal tdTransformToImage( VPTR, VPTR, short, short, short );\r
+\r
+void far pascal tdBackPlaneCull( VPTR, VPTR, VPTR, short, short );\r
+void far pascal tdGetNormal( VPTR, PPOINT, PPOINT, PPOINT );\r
+void far pascal tdRotate( VPTR, VPTR, short );\r
+void far pascal tdSetLight( PVECTOR );\r
+void far pascal tdSetRotation( short, short, short );\r
+void far pascal tdSetTranslation( PVECTOR );\r
+void far pascal tdSetPerspective( long, long, long );\r
+void far pascal tdTransform( VPTR, VPTR, short );\r
+void far pascal tdTransformLight( VPTR, VPTR, short );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
diff --git a/16/xw__/modex/THREED.PAS b/16/xw__/modex/THREED.PAS
new file mode 100755 (executable)
index 0000000..8b712c9
--- /dev/null
@@ -0,0 +1,40 @@
+unit ThreeD;\r
+interface\r
+\r
+type\r
+  TVector       = record\r
+    X, Y, Z     : longint;\r
+  end;\r
+  TPoint        = TVector;\r
+\r
+function tdFixedMul( F1, F2: longint ): longint;\r
+function tdGetSurfaceLight( var Normal: TPoint ): integer;\r
+function tdTransformToImage( var Source, Dest; Count, DeltaX, DeltaY: integer ): longint;\r
+\r
+procedure tdBackPlaneCull( var Poly, Vertex, Dest; Count, Step: word );\r
+procedure tdGetNormal( var Dest, P1, P2, P3: TVector );\r
+procedure tdRotate( var Source, Dest; Count: word );\r
+procedure tdSetLight( var Light: TVector );\r
+procedure tdSetRotation( RX, RY, RZ: word );\r
+procedure tdSetTranslation( var TV: TVector );\r
+procedure tdSetPerspective( PD, XF, YF: longint );\r
+procedure tdTransform( var Source, Dest; Count: word );\r
+procedure tdTransformLight( var Source, Dest; Count: word );\r
+\r
+implementation\r
+\r
+function tdGetSurfaceLight;                             external;\r
+procedure tdSetRotation( RX, RY, RZ: word );            external;\r
+procedure tdGetNormal;                                  external;\r
+procedure tdSetTranslation( var TV: TVector );          external;\r
+procedure tdTransform( var Source, Dest; Count: word ); external;\r
+procedure tdRotate;                                     external;\r
+function  tdTransformToImage;                           external;\r
+procedure tdSetLight( var Light: TVector );             external;\r
+procedure tdSetPerspective;                             external;\r
+procedure tdTransformLight;                             external;\r
+function tdFixedMul( F1, F2: longint ): longint;        external;\r
+procedure tdBackPlaneCull;                              external;\r
+{$L THREED}\r
+\r
+end.\r
diff --git a/16/xw__/modex/demo01.c b/16/xw__/modex/demo01.c
new file mode 100755 (executable)
index 0000000..0908fdf
--- /dev/null
@@ -0,0 +1,125 @@
+/*\r
+    DEMO01 - Sprites, page flipping and palette rotation\r
+    Copyright (c) 1994 Alessandro Scotti\r
+*/\r
+uses Crt, Modex;\r
+\r
+#DEFINE MAX_SPRITE 100\r
+type\r
+  (* Sprite structure *)\r
+  TSprite = record\r
+    X, Y : integer;                        (* Sprite coordinates *)\r
+    DX,DY: integer;                        (* Deltas for sprite movement *)\r
+    W, H : integer;                        (* Sprite width and height *)\r
+    Image: array[ 1..16, 1..16 ] of byte;  (* Sprite image data *)\r
+  end;\r
+  (* RGB color structure *)\r
+  TRgb    = record\r
+    R, G, B: byte;\r
+  end;\r
+var\r
+  S      : array[ 1..MAX_SPRITE ] of TSprite;   (* An array of sprites *)\r
+  Palette: array[ byte ] of TRgb;               (* Palette *)\r
+  Page   : word;                                (* Page offset *)\r
+  I      : word;\r
+\r
+(* Initializes a sprite structure *)\r
+procedure sxInit( var S: TSprite );\r
+var\r
+  I: word;\r
+begin\r
+  S.X := Random( 320 );  (* Initialize position with random values *)\r
+  S.Y := Random( 240 );\r
+  S.DX := Random( 7 )-3; (* Initialize speed with random values *)\r
+  S.DY := Random( 7 )-3;\r
+  S.W := 16;             (* Size is fixed in this program *)\r
+  S.H := 16;\r
+  (* The image is a square with a hole inside *)\r
+  FillChar( S.Image, SizeOf(S.Image), Random(15)+1 );\r
+  for I:=5 to 12 do FillChar( S.Image[ I, 5 ], 8, 0 );\r
+end;\r
+\r
+(* Moves a sprite *)\r
+procedure sxMove( var S: TSprite );\r
+begin\r
+  Inc( S.X, S.DX );     (* Get new position *)\r
+  Inc( S.Y, S.DY );\r
+  (* Check sprite position, change delta if needed *)\r
+  if( S.X > 320 ) then begin\r
+    S.X := 320;\r
+    S.DX := -S.DX;\r
+  end;\r
+  if( S.X < -16 ) then begin\r
+    S.X := -16;\r
+    S.DX := -S.DX;\r
+  end;\r
+  if( S.Y > 240 ) then begin\r
+    S.Y := 240;\r
+    S.DY := -S.DY;\r
+  end;\r
+  if( S.Y < -16 ) then begin\r
+    S.Y := -16;\r
+    S.DY := -S.DY;\r
+  end;\r
+  (* Draw the sprite, note the Page offset added to the *)\r
+  (* Y coordinate of the image *)\r
+  mxPutImage( @S.Image, S.X, Page+S.Y, S.W, S.H, OP_TRANS );\r
+end;\r
+\r
+begin\r
+  (* Initialize library *)\r
+  mxInit;\r
+\r
+  (* Enter graphics mode *)\r
+  mxSetMode( MX_320x240 );\r
+\r
+  (* Print initialization message *)\r
+  mxSetTextColor( 15, OP_TRANS );\r
+  mxOutStr( 4, 4, 'Initializing...' );\r
+\r
+  (* Initialize sprites *)\r
+  for I:=1 to MAX_SPRITE do sxInit( S[I] );\r
+\r
+  (* Draw background *)\r
+  for I:=1 to 192 do begin\r
+    mxCircle( 160, 480+120, I, I+63 );\r
+    mxCircle( 161, 480+120, I, I+63 );\r
+  end;\r
+\r
+  (* Compute and set palette *)\r
+  for I:=1 to 192 do with Palette[I+63] do begin\r
+    R := 0;\r
+    G := 0;\r
+    B := 0;\r
+    if( I < 64 ) then\r
+      R := I shr 1+31\r
+    else if( I < 128 ) then\r
+      G := (I-64) shr 1+31\r
+    else\r
+      B := (I-128) shr 1+31;\r
+  end;\r
+  mxSetPalette( @Palette[64], 64, 192 );\r
+\r
+  (* Main loop *)\r
+  Page := 240;\r
+  while( not KeyPressed ) do begin\r
+    (* Set clip region to current page *)\r
+    mxSetClipRegion( 0, Page, 320, 240 );\r
+    mxSetClip( TRUE );\r
+    (* Restore background *)\r
+    mxBitBlt( 0, 480, 320, 240, 0, Page );\r
+    (* Draw sprites *)\r
+    for I:=1 to MAX_SPRITE do sxMove( S[I] );\r
+    (* Print message *)\r
+    mxOutStr( 4, Page+4, 'Some sprites moving...' );\r
+    (* Flip page *)\r
+    mxStartLine( Page );\r
+    Page := 240-Page;\r
+    (* Animate palette *)\r
+    mxSetPalette( @Palette[64], 64, 192 );\r
+    mxRotatePalette( @Palette[64], 192, 3 );\r
+  end;\r
+\r
+  mxSetMode( MX_TEXT );\r
+  mxTerm;\r
+end.\r
diff --git a/16/xw__/mxbb.asm b/16/xw__/mxbb.asm
new file mode 100755 (executable)
index 0000000..a403c63
--- /dev/null
@@ -0,0 +1,208 @@
+.387
+               PUBLIC  MXBITBLT
+               EXTRN   SUBHORIZONTALLINEINFO:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+               EXTRN   MX_BYTESPERLINE:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXBITBLT:
+       push            bp
+       mov             bp,sp
+       sub             sp,16H
+       push            ds
+       push            si
+       push            es
+       push            di
+       cmp             word ptr 0cH[bp],0
+       je              L$2
+       mov             ax,word ptr 10H[bp]
+       and             al,3
+       mov             dx,word ptr 8[bp]
+       and             dl,3
+       mov             bx,offset L$10
+       cmp             al,dl
+       jne             L$1
+       mov             bx,offset L$3
+L$1:
+       call            bx
+L$2:
+       xor             ax,ax
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0cH
+L$3:
+       mov             bx,word ptr 8[bp]
+       mov             ax,word ptr 6[bp]
+       mov             cx,word ptr 0cH[bp]
+       call            near ptr MX_TEXT:SUBHORIZONTALLINEINFO
+       mov             byte ptr -14H[bp],al
+       mov             byte ptr -16H[bp],ah
+       mov             word ptr 0cH[bp],cx
+       mov             ax,word ptr cs:MX_VIDEOSEGMENT
+       mov             ds,ax
+       mov             es,ax
+       mov             ax,word ptr 0eH[bp]
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             si,word ptr 10H[bp]
+       shr             si,1
+       shr             si,1
+       add             si,ax
+       mov             dx,3ceH
+       mov             ax,4105H
+       out             dx,ax
+       cld
+       mov             ah,byte ptr -14H[bp]
+       or              ah,ah
+       je              L$5
+       mov             dx,3c4H
+       mov             al,2
+       out             dx,ax
+       mov             ax,word ptr cs:MX_BYTESPERLINE
+       dec             ax
+       mov             cx,word ptr 0aH[bp]
+       push            si
+       push            di
+L$4:
+       movsb
+       add             si,ax
+       add             di,ax
+       dec             cx
+       jne             L$4
+       pop             di
+       pop             si
+       inc             si
+       inc             di
+L$5:
+       mov             bx,word ptr 0cH[bp]
+       test            bx,bx
+       je              L$7
+       mov             dx,3c4H
+       mov             ax,0f02H
+       out             dx,ax
+       mov             ax,word ptr cs:MX_BYTESPERLINE
+       sub             ax,bx
+       mov             dx,word ptr 0aH[bp]
+       push            si
+       push            di
+L$6:
+       mov             cx,bx
+       rep movsb
+       add             si,ax
+       add             di,ax
+       dec             dx
+       jne             L$6
+       pop             di
+       pop             si
+       add             si,bx
+       add             di,bx
+L$7:
+       mov             ah,byte ptr -16H[bp]
+       or              ah,ah
+       je              L$9
+       mov             dx,3c4H
+       mov             al,2
+       out             dx,ax
+       mov             ax,word ptr cs:MX_BYTESPERLINE
+       dec             ax
+       mov             cx,word ptr 0aH[bp]
+L$8:
+       movsb
+       add             si,ax
+       add             di,ax
+       dec             cx
+       jne             L$8
+L$9:
+       mov             dx,3ceH
+       mov             ax,4005H
+       out             dx,ax
+       ret
+L$10:
+       mov             cx,word ptr 0cH[bp]
+       mov             bx,cx
+       shr             bx,1
+       shr             bx,1
+       and             cl,3
+       mov             al,8
+       shr             al,cl
+       mov             si,6
+L$11:
+       mov             word ptr -8[bp+si],bx
+       shr             al,1
+       adc             bx,0
+       dec             si
+       dec             si
+       jge             L$11
+       mov             ax,word ptr cs:MX_VIDEOSEGMENT
+       mov             ds,ax
+       mov             es,ax
+       mov             ax,word ptr 0eH[bp]
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             si,word ptr 10H[bp]
+       shr             si,1
+       shr             si,1
+       add             si,ax
+       mov             word ptr -0aH[bp],si
+       mov             ax,word ptr 6[bp]
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             di,word ptr 8[bp]
+       shr             di,1
+       shr             di,1
+       add             di,ax
+       mov             word ptr -0cH[bp],di
+       mov             ax,word ptr 10H[bp]
+       and             al,3
+       mov             byte ptr -10H[bp],al
+       mov             cx,word ptr 8[bp]
+       and             cl,3
+       mov             al,11H
+       shl             al,cl
+       mov             byte ptr -12H[bp],al
+       cld
+       mov             byte ptr -0eH[bp],4
+       lea             bx,-8[bp]
+L$12:
+       cmp             word ptr ss:[bx],0
+       je              L$15
+       mov             ah,byte ptr -12H[bp]
+       and             ah,0fH
+       mov             al,2
+       mov             dx,3c4H
+       out             dx,ax
+       mov             ah,byte ptr -10H[bp]
+       mov             al,4
+       mov             dx,3ceH
+       out             dx,ax
+       mov             dx,word ptr 0aH[bp]
+       mov             ax,word ptr cs:MX_BYTESPERLINE
+       sub             ax,word ptr ss:[bx]
+L$13:
+       mov             cx,word ptr ss:[bx]
+       shr             cx,1
+       rep movsw
+       rcl             cx,1
+       rep movsb
+       add             si,ax
+       add             di,ax
+       dec             dx
+       jne             L$13
+       inc             bx
+       inc             bx
+       inc             byte ptr -10H[bp]
+       and             byte ptr -10H[bp],3
+       jne             L$14
+       inc             word ptr -0aH[bp]
+L$14:
+       rol             byte ptr -12H[bp],1
+       adc             word ptr -0cH[bp],0
+       mov             si,word ptr -0aH[bp]
+       mov             di,word ptr -0cH[bp]
+       dec             byte ptr -0eH[bp]
+       jne             L$12
+L$15:
+       ret
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxcc.asm b/16/xw__/mxcc.asm
new file mode 100755 (executable)
index 0000000..f59177f
--- /dev/null
@@ -0,0 +1,629 @@
+.387
+               PUBLIC  XSUBCLIPLINE
+               EXTRN   MX_CLIPY1:BYTE
+               EXTRN   MX_CLIPY2:BYTE
+               EXTRN   MX_CLIPX2:BYTE
+               EXTRN   MX_CLIPX1:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+               EXTRN   MX_BYTESPERLINE:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+       or              al,byte ptr [bx+si]
+L$2:
+    DW offset L$3
+       or              al,byte ptr [bx+si]
+    DW offset L$4
+       or              word ptr [bx+si],ax
+    DW offset L$5
+       ????
+       inc             word ptr [bx+si]
+       add             byte ptr [bp+si],cl
+       add             byte ptr 0a00H[bx+si],al
+       add             byte ptr 900H[bp],dl
+       add             byte ptr -100H[si],ch
+       inc             word ptr [bx+si]
+       add             byte ptr ds:[0c000H],al
+       add             byte ptr ds:[0ce00H],al
+       add             byte ptr [di],al
+       add             ah,bl
+       add             bh,bh
+       inc             word ptr [bx+si]
+       add             bh,bh
+       inc             word ptr [bx+si]
+       add             bh,bh
+       inc             word ptr [bx+si]
+       add             bh,bh
+       inc             word ptr [bx+si]
+       add             bh,bh
+       inc             word ptr [bx+si]
+    DB 0
+L$3:
+    DW offset MX_TEXT+0ecH
+    DW offset MX_TEXT+0eeH
+    DW offset MX_TEXT+0f1H
+    DW offset MX_TEXT+0eaH
+    DW offset MX_TEXT+0f4H
+    DW offset MX_TEXT+0f7H
+    DW offset MX_TEXT+104H
+    DW offset MX_TEXT+0eaH
+    DW offset MX_TEXT+111H
+    DW offset MX_TEXT+114H
+    DW offset MX_TEXT+121H
+L$4:
+    DW offset MX_TEXT+132H
+    DW offset MX_TEXT+0eaH
+    DW offset MX_TEXT+135H
+    DW offset MX_TEXT+0eaH
+    DW offset MX_TEXT+13bH
+    DW offset MX_TEXT+0eaH
+    DW offset MX_TEXT+148H
+    DW offset L$7
+    DW offset L$10
+    DW offset L$7
+    DW offset L$11
+L$5:
+    DW offset L$14
+    DW offset L$15
+    DW offset L$7
+    DW offset L$7
+    DW offset L$16
+    DW offset L$17
+    DW offset L$7
+    DW offset L$7
+    DW offset L$18
+    DW offset L$19
+    DW offset L$22
+    DW offset L$23
+    DW offset L$24
+    DW offset L$7
+    DW offset L$7
+    DW offset L$7
+    DW offset L$7
+    DW offset L$7
+    DW offset L$25
+    DW offset L$26
+    DW offset L$27
+    DW offset L$30
+    DW offset L$7
+    DW offset L$31
+    DW offset L$7
+    DW offset L$7
+    DW offset L$7
+    DW offset L$7
+    DW offset L$7
+    DW offset L$32
+    DW offset L$7
+    DW offset L$33
+    DW offset L$36
+    DW offset L$37
+    DW offset L$7
+    DW offset L$7
+    DW offset L$7
+    DW offset L$7
+    DW offset L$7
+    DW offset L$7
+    DW offset L$38
+    DW offset L$39
+    DW offset L$43
+    DW offset L$44
+    DW offset L$45
+    DW offset L$7
+    DW offset L$46
+    DW offset L$47
+    DW offset L$48
+    DW offset L$51
+    DW offset L$7
+    DW offset L$52
+    DW offset L$7
+    DW offset L$53
+    DW offset L$7
+    DW offset L$54
+    DW offset L$58
+    DW offset L$59
+    DW offset L$7
+    DW offset L$7
+    DW offset L$60
+    DW offset L$61
+L$6:
+       clc
+       ret
+L$7:
+       stc
+       ret
+       clc
+       ret
+       jmp             near ptr L$67
+       jmp             near ptr L$68
+       jmp             near ptr L$70
+       call            near ptr L$67
+       cmp             si,word ptr cs:MX_CLIPY1
+       jge             L$6
+       jmp             near ptr L$70
+       call            near ptr L$68
+       cmp             si,word ptr cs:MX_CLIPY1
+       jge             L$6
+       jmp             near ptr L$70
+       jmp             near ptr L$69
+       call            near ptr L$67
+       cmp             si,word ptr cs:MX_CLIPY2
+       jle             L$6
+       jmp             near ptr L$69
+       call            near ptr L$68
+       cmp             si,word ptr cs:MX_CLIPY2
+       jle             L$6
+       jmp             near ptr L$69
+L$8:
+       stc
+       ret
+L$9:
+       clc
+       ret
+       jmp             near ptr L$63
+       call            near ptr L$63
+       jmp             near ptr L$68
+       call            near ptr L$63
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jl              L$8
+       jmp             near ptr L$70
+       call            near ptr L$63
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jl              L$8
+       call            near ptr L$70
+       cmp             cx,word ptr cs:MX_CLIPX2
+       jle             L$9
+       jmp             near ptr L$68
+L$10:
+       call            near ptr L$63
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jg              L$8
+       jmp             near ptr L$69
+L$11:
+       call            near ptr L$63
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jg              L$8
+       call            near ptr L$69
+       cmp             cx,word ptr cs:MX_CLIPX2
+       jle             L$9
+       jmp             near ptr L$68
+L$12:
+       clc
+       ret
+L$13:
+       stc
+       ret
+L$14:
+       jmp             near ptr L$64
+L$15:
+       call            near ptr L$64
+       jmp             near ptr L$67
+L$16:
+       call            near ptr L$64
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jl              L$13
+       jmp             near ptr L$70
+L$17:
+       call            near ptr L$64
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jl              L$13
+       call            near ptr L$70
+       cmp             cx,word ptr cs:MX_CLIPX1
+       jge             L$12
+       jmp             near ptr L$67
+L$18:
+       call            near ptr L$64
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jg              L$13
+       jmp             near ptr L$69
+L$19:
+       call            near ptr L$64
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jg              L$13
+       call            near ptr L$69
+       cmp             cx,word ptr cs:MX_CLIPX1
+       jge             L$12
+       jmp             near ptr L$67
+L$20:
+       clc
+       ret
+L$21:
+       stc
+       ret
+L$22:
+       jmp             near ptr L$66
+L$23:
+       call            near ptr L$66
+       cmp             di,word ptr cs:MX_CLIPX1
+       jl              L$21
+       call            near ptr L$67
+       cmp             si,word ptr cs:MX_CLIPY1
+       jge             L$20
+       jmp             near ptr L$70
+L$24:
+       call            near ptr L$66
+       cmp             di,word ptr cs:MX_CLIPX2
+       jg              L$21
+       jmp             near ptr L$68
+L$25:
+       call            near ptr L$66
+       jmp             near ptr L$69
+L$26:
+       call            near ptr L$66
+       cmp             di,word ptr cs:MX_CLIPX1
+       jl              L$21
+       call            near ptr L$67
+       cmp             si,word ptr cs:MX_CLIPY2
+       jle             L$20
+       jmp             near ptr L$69
+L$27:
+       call            near ptr L$66
+       cmp             di,word ptr cs:MX_CLIPX2
+       jg              L$21
+       call            near ptr L$68
+       cmp             si,word ptr cs:MX_CLIPY2
+       jle             L$20
+       jmp             near ptr L$69
+L$28:
+       clc
+       ret
+L$29:
+       stc
+       ret
+L$30:
+       call            near ptr L$63
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jge             L$28
+       jmp             near ptr L$66
+L$31:
+       call            near ptr L$68
+       cmp             si,word ptr cs:MX_CLIPY1
+       jl              L$29
+       call            near ptr L$66
+       cmp             di,word ptr cs:MX_CLIPX1
+       jge             L$28
+       jmp             near ptr L$63
+L$32:
+       call            near ptr L$69
+       cmp             cx,word ptr cs:MX_CLIPX1
+       jl              L$29
+       call            near ptr L$66
+       cmp             di,word ptr cs:MX_CLIPX1
+       jge             L$28
+       jmp             near ptr L$63
+L$33:
+       call            near ptr L$63
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jg              L$29
+       call            near ptr L$68
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jl              L$29
+       cmp             si,word ptr cs:MX_CLIPY2
+       jle             L$28
+       jmp             near ptr L$69
+L$34:
+       clc
+       ret
+L$35:
+       stc
+       ret
+L$36:
+       call            near ptr L$64
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jge             L$34
+       jmp             near ptr L$66
+L$37:
+       call            near ptr L$67
+       cmp             si,word ptr cs:MX_CLIPY2
+       jl              L$35
+       call            near ptr L$66
+       cmp             di,word ptr cs:MX_CLIPX2
+       jle             L$34
+       jmp             near ptr L$64
+L$38:
+       call            near ptr L$69
+       cmp             cx,word ptr cs:MX_CLIPX2
+       jg              L$35
+       call            near ptr L$64
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jge             L$34
+       jmp             near ptr L$66
+L$39:
+       call            near ptr L$67
+       cmp             si,word ptr cs:MX_CLIPY1
+       jl              L$35
+       call            near ptr L$64
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jg              L$35
+       cmp             si,word ptr cs:MX_CLIPY2
+       jle             L$40
+       call            near ptr L$69
+L$40:
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jge             L$34
+       jmp             near ptr L$66
+L$41:
+       clc
+       ret
+L$42:
+       stc
+       ret
+L$43:
+       jmp             near ptr L$65
+L$44:
+       call            near ptr L$65
+       cmp             di,word ptr cs:MX_CLIPX1
+       jl              L$42
+       jmp             near ptr L$67
+L$45:
+       call            near ptr L$65
+       cmp             di,word ptr cs:MX_CLIPX2
+       jg              L$42
+       jmp             near ptr L$68
+L$46:
+       call            near ptr L$65
+       jmp             near ptr L$70
+L$47:
+       call            near ptr L$65
+       cmp             di,word ptr cs:MX_CLIPX1
+       jl              L$42
+       call            near ptr L$67
+       cmp             si,word ptr cs:MX_CLIPY1
+       jge             L$42
+       jmp             near ptr L$70
+L$48:
+       call            near ptr L$65
+       cmp             di,word ptr cs:MX_CLIPX2
+       jg              L$42
+       call            near ptr L$68
+       cmp             si,word ptr cs:MX_CLIPY1
+       jge             L$41
+       jmp             near ptr L$70
+L$49:
+       clc
+       ret
+L$50:
+       stc
+       ret
+L$51:
+       call            near ptr L$63
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jle             L$49
+       jmp             near ptr L$65
+L$52:
+       call            near ptr L$68
+       cmp             si,word ptr cs:MX_CLIPY2
+       jg              L$50
+       call            near ptr L$65
+       cmp             di,word ptr cs:MX_CLIPX1
+       jge             L$49
+       jmp             near ptr L$63
+L$53:
+       call            near ptr L$70
+       cmp             cx,word ptr cs:MX_CLIPX1
+       jl              L$50
+       call            near ptr L$63
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jle             L$49
+       jmp             near ptr L$65
+L$54:
+       call            near ptr L$63
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jl              L$50
+       call            near ptr L$68
+       cmp             si,word ptr cs:MX_CLIPY2
+       jg              L$50
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jle             L$55
+       call            near ptr L$65
+L$55:
+       cmp             si,word ptr cs:MX_CLIPY1
+       jge             L$49
+       jmp             near ptr L$70
+L$56:
+       clc
+       ret
+L$57:
+       stc
+       ret
+L$58:
+       call            near ptr L$64
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jle             L$56
+       jmp             near ptr L$65
+L$59:
+       call            near ptr L$67
+       cmp             si,word ptr cs:MX_CLIPY2
+       jg              L$57
+       call            near ptr L$65
+       cmp             di,word ptr cs:MX_CLIPX2
+       jle             L$56
+       jmp             L$64
+L$60:
+       call            near ptr L$70
+       cmp             cx,word ptr cs:MX_CLIPX2
+       jg              L$57
+       call            near ptr L$64
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jle             L$56
+       jmp             L$65
+L$61:
+       call            near ptr L$67
+       cmp             si,word ptr cs:MX_CLIPY2
+       jg              L$57
+       call            near ptr L$64
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jl              L$57
+       cmp             si,word ptr cs:MX_CLIPY1
+       jge             L$62
+       call            near ptr L$70
+L$62:
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jle             L$56
+       jmp             L$65
+L$63:
+       mov             ax,si
+       sub             ax,bx
+       mov             dx,word ptr cs:MX_CLIPX1
+       sub             dx,di
+       imul            dx
+       mov             bp,cx
+       sub             bp,di
+       idiv            bp
+       add             bx,ax
+       mov             di,word ptr cs:MX_CLIPX1
+       clc
+       ret
+L$64:
+       mov             ax,si
+       sub             ax,bx
+       mov             dx,word ptr cs:MX_CLIPX2
+       sub             dx,di
+       imul            dx
+       mov             bp,cx
+       sub             bp,di
+       idiv            bp
+       add             bx,ax
+       mov             di,word ptr cs:MX_CLIPX2
+       clc
+       ret
+L$65:
+       mov             ax,cx
+       sub             ax,di
+       mov             dx,word ptr cs:MX_CLIPY2
+       sub             dx,bx
+       imul            dx
+       mov             bp,si
+       sub             bp,bx
+       idiv            bp
+       add             di,ax
+       mov             bx,word ptr cs:MX_CLIPY2
+       clc
+       ret
+L$66:
+       mov             ax,cx
+       sub             ax,di
+       mov             dx,word ptr cs:MX_CLIPY1
+       sub             dx,bx
+       imul            dx
+       mov             bp,si
+       sub             bp,bx
+       idiv            bp
+       add             di,ax
+       mov             bx,word ptr cs:MX_CLIPY1
+       clc
+       ret
+L$67:
+       mov             ax,bx
+       sub             ax,si
+       mov             dx,word ptr cs:MX_CLIPX1
+       sub             dx,cx
+       imul            dx
+       mov             bp,di
+       sub             bp,cx
+       idiv            bp
+       add             si,ax
+       mov             cx,word ptr cs:MX_CLIPX1
+       clc
+       ret
+L$68:
+       mov             ax,bx
+       sub             ax,si
+       mov             dx,word ptr cs:MX_CLIPX2
+       sub             dx,cx
+       imul            dx
+       mov             bp,di
+       sub             bp,cx
+       idiv            bp
+       add             si,ax
+       mov             cx,word ptr cs:MX_CLIPX2
+       clc
+       ret
+L$69:
+       mov             ax,di
+       sub             ax,cx
+       mov             dx,word ptr cs:MX_CLIPY2
+       sub             dx,si
+       imul            dx
+       mov             bp,bx
+       sub             bp,si
+       idiv            bp
+       add             cx,ax
+       mov             si,word ptr cs:MX_CLIPY2
+       clc
+       ret
+L$70:
+       mov             ax,di
+       sub             ax,cx
+       mov             dx,word ptr cs:MX_CLIPY1
+       sub             dx,si
+       imul            dx
+       mov             bp,bx
+       sub             bp,si
+       idiv            bp
+       add             cx,ax
+       mov             si,word ptr cs:MX_CLIPY1
+       clc
+       ret
+XSUBCLIPLINE:
+       push            bp
+       xor             si,si
+       cmp             dx,word ptr cs:MX_CLIPY2
+       jle             L$71
+       or              si,8
+       jmp             L$72
+L$71:
+       cmp             dx,word ptr cs:MX_CLIPY1
+       jge             L$72
+       or              si,4
+L$72:
+       cmp             cx,word ptr cs:MX_CLIPX2
+       jle             L$73
+       or              si,2
+       jmp             L$74
+L$73:
+       cmp             cx,word ptr cs:MX_CLIPX1
+       jge             L$74
+       or              si,1
+L$74:
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jle             L$75
+       or              si,80H
+       jmp             L$76
+L$75:
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jge             L$76
+       or              si,40H
+L$76:
+       cmp             ax,word ptr cs:MX_CLIPX2
+       jle             L$77
+       or              si,20H
+       jmp             L$78
+L$77:
+       cmp             ax,word ptr cs:MX_CLIPX1
+       jge             L$78
+       or              si,10H
+L$78:
+       mov             di,si
+       and             di,0fH
+       and             si,0f0H
+       shr             si,1
+       shr             si,1
+       cmp             di,word ptr cs:L$1[si]
+       jg              L$79
+       mov             si,word ptr cs:L$2[si]
+       shl             di,1
+       add             si,di
+       mov             di,ax
+       mov             si,word ptr cs:[si]
+       xchg            si,dx
+       call            dx
+       mov             ax,di
+       mov             dx,si
+       pop             bp
+       ret
+L$79:
+       pop             bp
+       stc
+       ret
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxcg.asm b/16/xw__/mxcg.asm
new file mode 100755 (executable)
index 0000000..72cd3ab
--- /dev/null
@@ -0,0 +1,43 @@
+.387
+               PUBLIC  MXCOLORTOGRAY
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXCOLORTOGRAY:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             cx,word ptr 6[bp]
+       jcxz            L$2
+       lds             si,dword ptr 0cH[bp]
+       les             di,dword ptr 8[bp]
+       cld
+       mov             bx,4d97H
+L$1:
+       lodsb
+       mul             bh
+       mov             dx,ax
+       lodsb
+       mul             bl
+       add             dx,ax
+       lodsb
+       mov             ah,1cH
+       mul             ah
+       add             ax,dx
+       mov             al,ah
+       stosw
+       stosb
+       loop            L$1
+L$2:
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0aH
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxcl.asm b/16/xw__/mxcl.asm
new file mode 100755 (executable)
index 0000000..1f5af64
--- /dev/null
@@ -0,0 +1,111 @@
+.387
+               PUBLIC  MXCIRCLE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+               EXTRN   MX_CLIPX1:BYTE
+               EXTRN   MX_CLIPX2:BYTE
+               EXTRN   MX_CLIPY1:BYTE
+               EXTRN   MX_CLIPY2:BYTE
+               EXTRN   MX_BYTESPERLINE:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXCIRCLE:
+       push            bp
+       mov             bp,sp
+       sub             sp,2
+       push            ds
+       push            si
+       push            di
+       xor             si,si
+       mov             di,word ptr 8[bp]
+       mov             ax,3
+       sub             ax,di
+       sub             ax,di
+       mov             word ptr -2[bp],ax
+       mov             ds,word ptr cs:MX_VIDEOSEGMENT
+L$1:
+       cmp             si,di
+       jg              L$3
+       mov             ax,si
+       mov             bx,di
+       call            near ptr L$4
+       mov             ax,si
+       neg             ax
+       mov             bx,di
+       call            near ptr L$4
+       mov             ax,si
+       mov             bx,di
+       neg             bx
+       call            near ptr L$4
+       mov             ax,si
+       neg             ax
+       mov             bx,di
+       neg             bx
+       call            near ptr L$4
+       mov             ax,di
+       mov             bx,si
+       call            near ptr L$4
+       mov             ax,di
+       neg             ax
+       mov             bx,si
+       call            near ptr L$4
+       mov             ax,di
+       mov             bx,si
+       neg             bx
+       call            near ptr L$4
+       mov             ax,di
+       neg             ax
+       mov             bx,si
+       neg             bx
+       call            near ptr L$4
+       mov             ax,word ptr -2[bp]
+       test            ax,ax
+       jl              L$2
+       mov             ax,di
+       shl             ax,1
+       shl             ax,1
+       sub             ax,4
+       sub             word ptr -2[bp],ax
+       dec             di
+L$2:
+       mov             ax,si
+       shl             ax,1
+       shl             ax,1
+       add             ax,6
+       add             word ptr -2[bp],ax
+       inc             si
+       jmp             L$1
+L$3:
+       xor             ax,ax
+       pop             di
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+L$4:
+       add             bx,word ptr 0cH[bp]
+       add             ax,word ptr 0aH[bp]
+       cmp             bx,word ptr cs:MX_CLIPX1
+       jl              L$5
+       cmp             bx,word ptr cs:MX_CLIPX2
+       jg              L$5
+       cmp             ax,word ptr cs:MX_CLIPY1
+       jl              L$5
+       cmp             ax,word ptr cs:MX_CLIPY2
+       jg              L$5
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             cx,bx
+       shr             bx,1
+       shr             bx,1
+       add             bx,ax
+       and             cl,3
+       mov             ax,102H
+       shl             ah,cl
+       mov             dx,3c4H
+       out             dx,ax
+       mov             al,byte ptr 6[bp]
+       mov             byte ptr [bx],al
+L$5:
+       ret
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxcr.asm b/16/xw__/mxcr.asm
new file mode 100755 (executable)
index 0000000..254269f
--- /dev/null
@@ -0,0 +1,244 @@
+.387
+               PUBLIC  MX_CLIPX1
+               PUBLIC  MX_CLIPY1
+               PUBLIC  MX_CLIPX2
+               PUBLIC  MX_CLIPY2
+               PUBLIC  MXSETCLIP
+               PUBLIC  MXGETCLIP
+               PUBLIC  MXSETSYSCLIPREGION
+               PUBLIC  MXSETCLIPREGION
+               PUBLIC  MXGETCLIPREGION
+               PUBLIC  SUBCLIPIMAGE
+               PUBLIC  SUBCLIPBOX
+               EXTRN   MX_CODESEGMENT:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MX_CLIPX1:
+       add             byte ptr [bx+si],al
+MX_CLIPY1:
+       add             byte ptr [bx+si],al
+MX_CLIPX2:
+       add             byte ptr [bx+si],al
+MX_CLIPY2:
+       add             byte ptr [bx+si],al
+L$1:
+       add             byte ptr [bx+si],al
+L$2:
+       add             byte ptr [bx+si],al
+L$3:
+       add             byte ptr [bx+si],al
+L$4:
+       add             byte ptr [bx+si],al
+L$5:
+       add             byte ptr [bx+si],al
+L$6:
+       add             byte ptr [bx+si],al
+L$7:
+       add             byte ptr [bx+si],al
+L$8:
+       add             byte ptr [bx+si],al
+L$9:
+    DB 0
+MXSETCLIP:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       mov             ax,word ptr L$5
+       mov             bx,word ptr L$6
+       mov             cx,word ptr L$7
+       mov             dx,word ptr L$8
+       cmp             byte ptr 6[bp],1
+       je              L$10
+       mov             ax,word ptr L$1
+       mov             bx,word ptr L$2
+       mov             cx,word ptr L$3
+       mov             dx,word ptr L$4
+L$10:
+       mov             word ptr MX_CLIPX1,ax
+       mov             word ptr MX_CLIPY1,bx
+       mov             word ptr MX_CLIPX2,cx
+       mov             word ptr MX_CLIPY2,dx
+       mov             al,byte ptr 6[bp]
+       xchg            byte ptr L$9,al
+       xor             ah,ah
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            2
+MXGETCLIP:
+       mov             al,byte ptr cs:L$9
+       xor             ah,ah
+       retf
+MXSETSYSCLIPREGION:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       xor             ax,ax
+       mov             word ptr L$1,ax
+       mov             word ptr L$2,ax
+       mov             ax,word ptr 8[bp]
+       dec             ax
+       mov             word ptr L$3,ax
+       mov             ax,word ptr 6[bp]
+       dec             ax
+       mov             word ptr L$4,ax
+       mov             ax,0
+       push            ax
+       push            cs
+       call            near ptr MXSETCLIP
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            4
+MXSETCLIPREGION:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       mov             ax,word ptr 0cH[bp]
+       mov             word ptr L$5,ax
+       mov             ax,word ptr 0aH[bp]
+       mov             word ptr L$6,ax
+       mov             ax,word ptr 8[bp]
+       add             ax,word ptr 0cH[bp]
+       dec             ax
+       mov             word ptr L$7,ax
+       mov             ax,word ptr 6[bp]
+       add             ax,word ptr 0aH[bp]
+       dec             ax
+       mov             word ptr L$8,ax
+       mov             al,byte ptr L$9
+       cmp             al,1
+       jne             L$11
+       push            ax
+       push            cs
+       call            near ptr MXSETCLIP
+L$11:
+       xor             ax,ax
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+MXGETCLIPREGION:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            es
+       push            di
+       mov             ax,word ptr cs:L$5
+       les             di,dword ptr 12H[bp]
+       mov             word ptr es:[di],ax
+       mov             ax,word ptr cs:L$6
+       les             di,dword ptr 0eH[bp]
+       mov             word ptr es:[di],ax
+       mov             ax,word ptr cs:L$7
+       sub             ax,word ptr cs:L$5
+       inc             ax
+       les             di,dword ptr 0aH[bp]
+       mov             word ptr es:[di],ax
+       mov             ax,word ptr cs:L$8
+       sub             ax,word ptr cs:L$6
+       inc             ax
+       les             di,dword ptr 6[bp]
+       mov             word ptr es:[di],ax
+       mov             al,byte ptr cs:L$9
+       xor             ah,ah
+       pop             di
+       pop             es
+       mov             sp,bp
+       pop             bp
+       retf            10H
+SUBCLIPIMAGE:
+       xor             si,si
+       mov             di,word ptr cs:MX_CLIPY1
+       cmp             ax,di
+       jge             L$12
+       sub             di,ax
+       sub             dx,di
+       jle             L$16
+       mov             ax,di
+       mov             di,dx
+       mul             cx
+       mov             si,ax
+       mov             dx,di
+       mov             ax,word ptr cs:MX_CLIPY1
+L$12:
+       mov             di,word ptr cs:MX_CLIPY2
+       cmp             ax,di
+       jg              L$16
+       inc             di
+       sub             di,dx
+       sub             di,ax
+       jge             L$13
+       add             dx,di
+L$13:
+       mov             di,word ptr cs:MX_CLIPX1
+       cmp             bx,di
+       jge             L$14
+       sub             di,bx
+       sub             cx,di
+       jle             L$16
+       add             si,di
+       mov             bx,word ptr cs:MX_CLIPX1
+L$14:
+       mov             di,word ptr cs:MX_CLIPX2
+       cmp             bx,di
+       jg              L$16
+       inc             di
+       sub             di,bx
+       sub             di,cx
+       jge             L$15
+       add             cx,di
+L$15:
+       clc
+       ret
+L$16:
+       stc
+       ret
+SUBCLIPBOX:
+       mov             di,word ptr cs:MX_CLIPY1
+       cmp             ax,di
+       jge             L$17
+       sub             di,ax
+       sub             dx,di
+       jle             L$21
+       mov             ax,word ptr cs:MX_CLIPY1
+L$17:
+       mov             di,word ptr cs:MX_CLIPY2
+       cmp             ax,di
+       jg              L$21
+       inc             di
+       sub             di,dx
+       sub             di,ax
+       jge             L$18
+       add             dx,di
+L$18:
+       mov             di,word ptr cs:MX_CLIPX1
+       cmp             bx,di
+       jge             L$19
+       sub             di,bx
+       sub             cx,di
+       jle             L$21
+       mov             bx,word ptr cs:MX_CLIPX1
+L$19:
+       mov             di,word ptr cs:MX_CLIPX2
+       cmp             bx,di
+       jg              L$21
+       inc             di
+       sub             di,bx
+       sub             di,cx
+       jge             L$20
+       add             cx,di
+L$20:
+       clc
+       ret
+L$21:
+       stc
+       ret
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxel.asm b/16/xw__/mxel.asm
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/16/xw__/mxfb.asm b/16/xw__/mxfb.asm
new file mode 100755 (executable)
index 0000000..d0993a1
--- /dev/null
@@ -0,0 +1,134 @@
+.387
+               PUBLIC  MXFILLBOX
+               EXTRN   SUBCLIPBOX:BYTE
+               EXTRN   SUBHORIZONTALLINEINFO:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+               EXTRN   MX_BYTESPERLINE:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+       mov             ah,al
+       shr             cx,1
+       rep stosw
+       rcl             cx,1
+       rep stosb
+       ret
+L$2:
+       mov             byte ptr [bx],al
+       add             bx,dx
+       loop            L$2
+       ret
+L$3:
+       mov             si,di
+L$4:
+       mov             ah,byte ptr [si]
+       mov             byte ptr [si],al
+       inc             si
+       loop            L$4
+       ret
+L$5:
+       mov             ah,byte ptr [bx]
+       mov             byte ptr [bx],al
+       add             bx,dx
+       loop            L$5
+       ret
+MXFILLBOX:
+       push            bp
+       mov             bp,sp
+       sub             sp,8
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             bx,word ptr 10H[bp]
+       mov             ax,word ptr 0eH[bp]
+       mov             cx,word ptr 0cH[bp]
+       mov             dx,word ptr 0aH[bp]
+       call            near ptr MX_TEXT:SUBCLIPBOX
+       jae             L$6
+       jmp             near ptr L$12
+L$6:
+       mov             word ptr 0aH[bp],dx
+       call            near ptr MX_TEXT:SUBHORIZONTALLINEINFO
+       mov             word ptr 0cH[bp],cx
+       mov             byte ptr -2[bp],al
+       mov             byte ptr -4[bp],ah
+       mov             ax,word ptr cs:MX_VIDEOSEGMENT
+       mov             es,ax
+       mov             ds,ax
+       cld
+       mov             word ptr -6[bp],offset L$2
+       mov             word ptr -8[bp],offset L$1
+       mov             ax,word ptr 6[bp]
+       cmp             al,3
+       ja              L$7
+       cmp             al,0
+       je              L$7
+       shl             al,1
+       shl             al,1
+       shl             al,1
+       mov             ah,al
+       mov             al,3
+       mov             dx,3ceH
+       out             dx,ax
+       mov             word ptr -6[bp],offset L$5
+       mov             word ptr -8[bp],offset L$3
+L$7:
+       mov             ah,byte ptr -2[bp]
+       or              ah,ah
+       je              L$8
+       mov             dx,3c4H
+       mov             al,2
+       out             dx,ax
+       mov             dx,word ptr cs:MX_BYTESPERLINE
+       mov             cx,word ptr 0aH[bp]
+       mov             bx,di
+       mov             al,byte ptr 8[bp]
+       call            word ptr -6[bp]
+       inc             di
+L$8:
+       mov             cx,word ptr 0cH[bp]
+       jcxz            L$10
+       mov             dx,3c4H
+       mov             ax,0f02H
+       out             dx,ax
+       mov             al,byte ptr 8[bp]
+       mov             bx,di
+       mov             dx,word ptr 0aH[bp]
+       push            di
+L$9:
+       mov             di,bx
+       call            word ptr -8[bp]
+       mov             cx,word ptr 0cH[bp]
+       add             bx,word ptr cs:MX_BYTESPERLINE
+       dec             dx
+       jne             L$9
+       pop             di
+       add             di,word ptr 0cH[bp]
+L$10:
+       mov             ah,byte ptr -4[bp]
+       or              ah,ah
+       je              L$11
+       mov             dx,3c4H
+       mov             al,2
+       out             dx,ax
+       mov             dx,word ptr cs:MX_BYTESPERLINE
+       mov             cx,word ptr 0aH[bp]
+       mov             bx,di
+       mov             al,byte ptr 8[bp]
+       call            word ptr -6[bp]
+L$11:
+       mov             dx,3ceH
+       mov             ax,3
+       out             dx,ax
+L$12:
+       xor             ax,ax
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0cH
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxfp.asm b/16/xw__/mxfp.asm
new file mode 100755 (executable)
index 0000000..45900b0
--- /dev/null
@@ -0,0 +1,220 @@
+.387
+               PUBLIC  MXFADEPALETTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+       inc             bx
+       outsw
+       jo              L$5
+       jb              L$4
+       push            2074H
+       sub             byte ptr 29H[bp+di],ah
+       and             byte ptr [bx+di],dh
+       cmp             word ptr [bx+di],di
+       xor             ch,byte ptr [di]
+       xor             word ptr [bx+di],di
+       cmp             word ptr [si],si
+       and             byte ptr 52H[bx+di],al
+       push            sp
+       dec             cx
+       push            bx
+       and             byte ptr 2eH[bp+di],dh
+       jb              L$1
+       insb
+       and             byte ptr cs:6cH[bx+di],al
+       insb
+       and             byte ptr 69H[bp+si],dh
+       push            7374H
+       and             byte ptr 65H[bp+si],dh
+       jae             L$7
+       jb              L$9
+    DB 65H, 64H, 2eH
+MXFADEPALETTE:
+       push            bp
+       mov             bp,sp
+       sub             sp,60aH
+       push            si
+       push            di
+       push            ds
+       push            es
+       mov             word ptr -608H[bp],1
+       mov             ax,word ptr 10H[bp]
+       and             ax,0ff00H
+L$1:
+       je              L$2
+       mov             cl,8
+       shr             ax,cl
+       mov             word ptr -608H[bp],ax
+L$2:
+       mov             ax,word ptr 10H[bp]
+       and             ax,0feH
+       mov             cl,1
+       shr             ax,cl
+       or              ax,ax
+       jne             L$3
+       mov             ax,30H
+L$3:
+       mov             word ptr -60aH[bp],ax
+L$4:
+       inc             ax
+       mov             byte ptr -606H[bp],al
+       mov             byte ptr -604H[bp],1
+    DB 0c6H, 86H, 0feH, 0f9H
+L$5:
+       add             byte ptr 0e46H[bp+di],cl
+       cmp             ax,100H
+       jb              L$6
+       jmp             near ptr L$12
+L$6:
+       add             ax,word ptr 0cH[bp]
+       cmp             ax,100H
+       jbe             L$8
+       mov             ax,100H
+       sub             ax,word ptr 0eH[bp]
+    DB 89H, 46H
+L$7:
+       or              al,0bH
+       ????
+       jne             L$8
+       jmp             near ptr L$12
+L$8:
+       mov             cx,word ptr 0cH[bp]
+       mov             ax,cx
+       shl             ax,1
+       add             cx,ax
+       mov             ax,ss
+L$9:
+       mov             es,ax
+       lea             di,-300H[bp]
+       mov             ax,word ptr 0eH[bp]
+       mov             si,ax
+       shl             ax,1
+       add             ax,si
+       lds             si,dword ptr 12H[bp]
+       add             si,ax
+       cld
+       shr             cx,1
+       rep movsw
+       rcl             cx,1
+       rep movsb
+       test            word ptr 10H[bp],1
+       je              L$10
+       mov             ax,word ptr -60aH[bp]
+       mov             byte ptr -602H[bp],al
+       mov             byte ptr -604H[bp],0ffH
+       mov             ax,ss
+       mov             ds,ax
+       mov             es,ax
+       lea             di,-300H[bp]
+       mov             ax,word ptr 0eH[bp]
+       mov             cx,word ptr 0cH[bp]
+       call            near ptr L$19
+L$10:
+       mov             bh,byte ptr 0aH[bp]
+       and             bh,3fH
+       mov             bl,byte ptr 8[bp]
+       and             bl,3fH
+       mov             dh,byte ptr 6[bp]
+       and             dh,3fH
+       mov             dl,byte ptr -602H[bp]
+       mov             ax,ss
+       mov             ds,ax
+       mov             es,ax
+L$11:
+       mov             ax,word ptr 0cH[bp]
+       mov             cx,word ptr -60aH[bp]
+       lea             si,-300H[bp]
+       lea             di,-600H[bp]
+       call            near ptr L$13
+       push            bx
+       push            dx
+       lea             si,-600H[bp]
+       mov             ax,word ptr 0eH[bp]
+       mov             bx,word ptr 0cH[bp]
+       mov             cx,word ptr -608H[bp]
+       call            near ptr L$15
+       pop             dx
+       pop             bx
+       add             dl,byte ptr -604H[bp]
+       dec             byte ptr -606H[bp]
+       jne             L$11
+L$12:
+       pop             es
+       pop             ds
+       pop             di
+       pop             si
+       mov             sp,bp
+       pop             bp
+       retf            10H
+L$13:
+       cld
+       push            bp
+       mov             bp,ax
+L$14:
+       lodsb
+       sub             al,bh
+       imul            dl
+       idiv            cl
+       add             al,bh
+       stosb
+       lodsb
+       sub             al,bl
+       imul            dl
+       idiv            cl
+       add             al,bl
+       stosb
+       lodsb
+       sub             al,dh
+       imul            dl
+       idiv            cl
+       add             al,dh
+       stosb
+       dec             bp
+       jne             L$14
+       pop             bp
+       ret
+L$15:
+       mov             ah,al
+       mov             dx,3daH
+L$16:
+       in              al,dx
+       test            al,8
+       jne             L$16
+L$17:
+       in              al,dx
+       test            al,8
+       je              L$17
+       loop            L$16
+       mov             cx,bx
+       mov             dx,3c8H
+       mov             al,ah
+       out             dx,al
+       inc             dx
+       cld
+       cli
+L$18:
+       lodsb
+       out             dx,al
+       lodsb
+       out             dx,al
+       lodsb
+       out             dx,al
+       loop            L$18
+       sti
+       ret
+L$19:
+       mov             dx,3c7H
+       out             dx,al
+       inc             dx
+       inc             dx
+       cld
+L$20:
+       in              al,dx
+       stosb
+       in              al,dx
+       stosb
+       in              al,dx
+       stosb
+       loop            L$20
+       ret
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxgc.asm b/16/xw__/mxgc.asm
new file mode 100755 (executable)
index 0000000..5b128d2
--- /dev/null
@@ -0,0 +1,31 @@
+.387
+               PUBLIC  MXGETCOLOR
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXGETCOLOR:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       mov             ax,word ptr 12H[bp]
+       mov             dx,3c7H
+       out             dx,al
+       inc             dx
+       inc             dx
+       lds             si,dword ptr 0eH[bp]
+       in              al,dx
+       mov             byte ptr [si],al
+       lds             si,dword ptr 0aH[bp]
+       in              al,dx
+       mov             byte ptr [si],al
+       lds             si,dword ptr 6[bp]
+       in              al,dx
+       mov             byte ptr [si],al
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0eH
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxgi.asm b/16/xw__/mxgi.asm
new file mode 100755 (executable)
index 0000000..36fe708
--- /dev/null
@@ -0,0 +1,99 @@
+.387
+               PUBLIC  MXGETIMAGE
+               EXTRN   SUBCLIPIMAGE:BYTE
+               EXTRN   MX_BYTESPERLINE:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXGETIMAGE:
+       push            bp
+       mov             bp,sp
+       sub             sp,10H
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             bx,word ptr 0cH[bp]
+       mov             ax,word ptr 0aH[bp]
+       mov             cx,word ptr 8[bp]
+       mov             dx,word ptr 6[bp]
+       call            near ptr MX_TEXT:SUBCLIPIMAGE
+       jae             L$1
+       jmp             near ptr L$7
+L$1:
+       mov             word ptr 6[bp],dx
+       add             word ptr 0eH[bp],si
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             si,bx
+       shr             si,1
+       shr             si,1
+       add             si,ax
+       mov             word ptr -0aH[bp],si
+       mov             ds,word ptr cs:MX_VIDEOSEGMENT
+       and             bl,3
+       mov             byte ptr -0eH[bp],bl
+       mov             bx,cx
+       shr             bx,1
+       shr             bx,1
+       and             cl,3
+       mov             al,8
+       shr             al,cl
+       mov             di,6
+L$2:
+       mov             word ptr -8[bp+di],bx
+       shr             al,1
+       adc             bx,0
+       dec             di
+       dec             di
+       jge             L$2
+       cld
+       mov             byte ptr -10H[bp],4
+       lea             bx,-8[bp]
+       mov             es,word ptr 10H[bp]
+       mov             ah,byte ptr -0eH[bp]
+L$3:
+       cmp             word ptr ss:[bx],0
+       je              L$7
+       mov             di,word ptr 0eH[bp]
+       mov             al,4
+       mov             dx,3ceH
+       out             dx,ax
+       mov             dx,word ptr 6[bp]
+       mov             si,word ptr -0aH[bp]
+L$4:
+       push            si
+       push            di
+       mov             cx,word ptr ss:[bx]
+L$5:
+       movsb
+       add             di,3
+       dec             cx
+       jne             L$5
+       pop             di
+       pop             si
+       add             di,word ptr 8[bp]
+       add             si,word ptr cs:MX_BYTESPERLINE
+       dec             dx
+       jne             L$4
+       inc             bx
+       inc             bx
+       inc             ah
+       test            ah,4
+       je              L$6
+       inc             word ptr -0aH[bp]
+       and             ah,3
+L$6:
+       inc             word ptr 0eH[bp]
+       dec             byte ptr -10H[bp]
+       jne             L$3
+L$7:
+       xor             ax,ax
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0cH
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxgm.asm b/16/xw__/mxgm.asm
new file mode 100755 (executable)
index 0000000..0c97985
--- /dev/null
@@ -0,0 +1,69 @@
+.387
+               PUBLIC  MXGAMMACORRECT
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+       add             byte ptr [bp+si],cl
+       push            cs
+       adc             word ptr [bp+di],dx
+       adc             ax,1817H
+       sbb             bl,byte ptr [bp+di]
+       sbb             al,1dH
+       pop             ds
+       and             byte ptr [bx+di],ah
+       and             ah,byte ptr [bp+di]
+       and             al,25H
+       and             ax,2726H
+       sub             byte ptr [bx+di],ch
+       sub             word ptr [bp+si],bp
+       sub             bp,word ptr [si]
+       sub             al,2dH
+       das
+       xor             byte ptr [bx+si],dh
+       xor             word ptr [bx+di],si
+       xor             dh,byte ptr [bp+di]
+       xor             si,word ptr [si]
+       xor             al,35H
+       xor             ax,3636H
+       aaa
+       aaa
+       cmp             byte ptr [bx+si],bh
+       cmp             word ptr [bx+di],di
+       cmp             bh,byte ptr [bp+si]
+       cmp             di,word ptr [bp+di]
+       cmp             al,3cH
+       cmp             ax,3e3dH
+       aas
+       aas
+MXGAMMACORRECT:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             cx,word ptr 6[bp]
+       jcxz            L$3
+       lds             si,dword ptr 0cH[bp]
+       les             di,dword ptr 8[bp]
+       mov             bx,offset L$1
+       cld
+       mov             ax,cx
+       add             cx,cx
+       add             cx,ax
+L$2:
+       lodsb
+       xlat            word ptr cs:[bx]
+       stosb
+       loop            L$2
+L$3:
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0aH
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxgp.asm b/16/xw__/mxgp.asm
new file mode 100755 (executable)
index 0000000..19a10cc
--- /dev/null
@@ -0,0 +1,33 @@
+.387
+               PUBLIC  MXGETPALETTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXGETPALETTE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            es
+       push            di
+       les             di,dword ptr 0aH[bp]
+       mov             cx,word ptr 6[bp]
+       mov             ax,word ptr 8[bp]
+       mov             dx,3c7H
+       out             dx,al
+       inc             dx
+       inc             dx
+       cld
+L$1:
+       in              al,dx
+       stosb
+       in              al,dx
+       stosb
+       in              al,dx
+       stosb
+       loop            L$1
+       pop             di
+       pop             es
+       mov             sp,bp
+       pop             bp
+       retf            8
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxgv.asm b/16/xw__/mxgv.asm
new file mode 100755 (executable)
index 0000000..bbe19c9
--- /dev/null
@@ -0,0 +1,9 @@
+.387
+               PUBLIC  MXGETVERSION
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXGETVERSION:
+       mov             ax,128H
+       retf
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxhl.asm b/16/xw__/mxhl.asm
new file mode 100755 (executable)
index 0000000..159e5c9
--- /dev/null
@@ -0,0 +1,45 @@
+.387
+               PUBLIC  SUBHORIZONTALLINEINFO
+               EXTRN   MX_BYTESPERLINE:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+       add             byte ptr [bx+si],al
+       add             ax,word ptr [bx+si]
+       add             al,byte ptr [bx+si]
+       add             word ptr [bx+si],ax
+L$2:
+       add             byte ptr ds:[80cH],cl
+L$3:
+       add             byte ptr [bx+di],al
+       add             ax,word ptr [bx]
+L$4:
+    DB 2, 6
+SUBHORIZONTALLINEINFO:
+    DD ds:[0f72eH]
+       add             byte ptr -2e05H[bp+di],cl
+       out             dx,ax
+       shr             di,1
+       add             di,ax
+       and             bx,3
+       mov             al,byte ptr cs:L$2[bx]
+       shl             bx,1
+       sub             cx,word ptr cs:L$1[bx]
+       jge             L$5
+       mov             bx,cx
+       inc             bx
+       inc             bx
+       and             al,byte ptr cs:L$4[bx]
+       xor             ah,ah
+       xor             cx,cx
+       jmp             L$6
+L$5:
+       mov             bx,cx
+       and             bx,3
+       mov             ah,byte ptr cs:L$3[bx]
+       shr             cx,1
+       shr             cx,1
+L$6:
+       ret
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxit.asm b/16/xw__/mxit.asm
new file mode 100755 (executable)
index 0000000..4f68fdd
--- /dev/null
@@ -0,0 +1,92 @@
+.387
+               PUBLIC  MX_VIDEOSEGMENT
+               PUBLIC  MX_CODESEGMENT
+               PUBLIC  MXINIT
+               PUBLIC  MXTERM
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+       dec             bp
+       dec             di
+       inc             sp
+       inc             bp
+       pop             ax
+       and             byte ptr 69H[si],ch
+       bound           si,word ptr 61H[bp+si]
+       jb              L$3
+       and             byte ptr [di],ch
+       and             byte ptr 6fH[bp+di],al
+       jo              L$5
+       jb              L$2
+       push            2074H
+       sub             byte ptr 29H[bp+di],ah
+       and             byte ptr [bx+di],dh
+       cmp             word ptr [bx+di],di
+       xor             ch,byte ptr [di]
+       xor             word ptr [bx+di],di
+       cmp             word ptr [si],si
+       and             byte ptr 6cH[bx+di],al
+       ; The label referred to here is an undefined location
+       jae             0a0H
+       popa
+       outsb
+       ; The label referred to here is an undefined location
+       jb              0a1H
+       and             byte ptr 63H[bp+di],dl
+       outsw
+       ; The label referred to here is an undefined location
+       je              0acH
+    DB 69H
+MX_VIDEOSEGMENT:
+    DB 0, 0a0H
+MX_CODESEGMENT:
+    DW MX_TEXT
+MXINIT:
+       push            bp
+       mov             bp,sp
+       sub             sp,6
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             word ptr -2[bp],0ffffH
+       mov             word ptr -4[bp],0a000H
+       mov             word ptr -6[bp],cs
+       mov             ax,1686H
+       int             2fH
+       or              ax,ax
+       jne             L$1
+       mov             ax,0aH
+       mov             bx,cs
+       int             31H
+       jb              L$4
+       mov             word ptr -6[bp],ax
+       mov             ax,2
+       mov             bx,0a000H
+       int             31H
+       jb              L$4
+       mov             word ptr -4[bp],ax
+L$1:
+       mov             ds,word ptr -6[bp]
+       mov             word ptr MX_CODESEGMENT,ds
+    DB 8bH, 46H
+L$2:
+       cld
+       mov             word ptr MX_VIDEOSEGMENT,ax
+    DB 0c7H, 46H, 0feH
+L$3:
+       add             byte ptr [bx+si],al
+L$4:
+       mov             ax,word ptr -2[bp]
+       pop             di
+       pop             es
+L$5:
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf
+MXTERM:
+       xor             ax,ax
+       retf
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxll.asm b/16/xw__/mxll.asm
new file mode 100755 (executable)
index 0000000..94e5b2c
--- /dev/null
@@ -0,0 +1,51 @@
+.387
+               PUBLIC  MXLOADLATCHES
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXLOADLATCHES:
+       push            ds
+       push            si
+       mov             dx,3ceH
+       mov             ax,0ff08H
+       out             dx,ax
+       mov             ax,3
+       out             dx,ax
+       mov             ax,5
+       out             dx,ax
+       mov             ax,word ptr cs:MX_VIDEOSEGMENT
+       mov             ds,ax
+       mov             si,0ffffH
+       mov             bh,8
+       mov             cx,3
+L$1:
+       mov             dx,3ceH
+       mov             al,4
+       mov             ah,cl
+       out             dx,ax
+       mov             dx,3c4H
+       mov             al,2
+       mov             ah,bh
+       out             dx,ax
+       mov             al,byte ptr [si]
+       push            ax
+       mov             byte ptr [si],bl
+       mov             al,byte ptr [di]
+       shr             bh,1
+       loop            L$1
+       mov             cx,3
+       mov             bh,8
+       mov             dx,3c4H
+L$2:
+       mov             al,2
+       mov             ah,bh
+       out             dx,ax
+       pop             ax
+       mov             byte ptr [si],al
+       shr             bh,1
+       loop            L$2
+       pop             si
+       pop             ds
+       ret
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxln.asm b/16/xw__/mxln.asm
new file mode 100755 (executable)
index 0000000..b488734
--- /dev/null
@@ -0,0 +1,333 @@
+.387
+               PUBLIC  MXLINE
+               EXTRN   MX_BYTESPERLINE:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+               EXTRN   MX_CLIPX1:BYTE
+               EXTRN   MX_CLIPX2:BYTE
+               EXTRN   MX_CLIPY1:BYTE
+               EXTRN   MX_CLIPY2:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+    DW offset L$29
+    DW offset L$32
+    DW offset L$35
+    DW offset L$38
+MXLINE:
+       push            bp
+       mov             bp,sp
+       sub             sp,12H
+       push            ds
+       push            si
+       push            di
+       mov             ax,word ptr 10H[bp]
+       mov             bx,word ptr 0eH[bp]
+       mov             cx,word ptr 0cH[bp]
+       mov             dx,word ptr 0aH[bp]
+       call            near ptr L$8
+       jae             L$2
+       jmp             near ptr L$7
+L$2:
+       mov             si,cx
+       xchg            ax,si
+       sub             ax,si
+       jge             L$3
+       xchg            cx,si
+       xchg            dx,bx
+       neg             ax
+L$3:
+       mov             word ptr -2[bp],ax
+       mov             cx,word ptr cs:MX_BYTESPERLINE
+       mov             ax,dx
+       sub             ax,bx
+       jge             L$4
+       neg             cx
+       neg             ax
+L$4:
+       mov             word ptr -4[bp],ax
+       mov             word ptr -0cH[bp],cx
+       mov             ax,bx
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             cx,si
+       shr             si,1
+       shr             si,1
+       add             si,ax
+       and             cl,3
+       mov             ax,1102H
+       shl             ah,cl
+       mov             byte ptr -12H[bp],ah
+       mov             dx,3c4H
+       out             dx,ax
+       mov             ax,word ptr cs:MX_VIDEOSEGMENT
+       mov             ds,ax
+       xor             bx,bx
+       mov             al,byte ptr 6[bp]
+       cmp             al,0
+       je              L$5
+       and             al,3
+       shl             al,1
+       shl             al,1
+       shl             al,1
+       mov             ah,al
+       mov             al,3
+       mov             dx,3ceH
+       out             dx,ax
+       inc             bx
+       inc             bx
+L$5:
+       mov             ax,word ptr -2[bp]
+       mov             cx,word ptr -4[bp]
+       cmp             ax,cx
+       jae             L$6
+       inc             bx
+L$6:
+       shl             bx,1
+       call            word ptr cs:L$1[bx]
+       cmp             byte ptr 6[bp],0
+       je              L$7
+       mov             ax,3
+       mov             dx,3ceH
+       out             dx,ax
+L$7:
+       xor             ax,ax
+       pop             di
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0cH
+L$8:
+       mov             di,ax
+       mov             si,dx
+       xor             al,al
+       cmp             cx,word ptr cs:MX_CLIPX1
+       jge             L$9
+       or              al,1
+L$9:
+       cmp             cx,word ptr cs:MX_CLIPX2
+       jle             L$10
+       or              al,2
+L$10:
+       cmp             si,word ptr cs:MX_CLIPY1
+       jge             L$11
+       or              al,4
+L$11:
+       cmp             si,word ptr cs:MX_CLIPY2
+       jle             L$12
+       or              al,8
+L$12:
+       mov             byte ptr -10H[bp],al
+       xor             al,al
+       cmp             di,word ptr cs:MX_CLIPX1
+       jge             L$13
+       or              al,1
+L$13:
+       cmp             di,word ptr cs:MX_CLIPX2
+       jle             L$14
+       or              al,2
+L$14:
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jge             L$15
+       or              al,4
+L$15:
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jle             L$16
+       or              al,8
+L$16:
+       mov             byte ptr -0eH[bp],al
+       mov             ah,byte ptr -10H[bp]
+       test            ah,al
+       je              L$17
+       jmp             near ptr L$28
+L$17:
+       or              ah,al
+       jne             L$18
+       jmp             near ptr L$27
+L$18:
+       mov             ax,cx
+       sub             ax,di
+       mov             word ptr -0aH[bp],ax
+       mov             ax,si
+       sub             ax,bx
+       mov             word ptr -0cH[bp],ax
+       mov             al,byte ptr -0eH[bp]
+L$19:
+       test            al,al
+       jne             L$20
+       xchg            di,cx
+       xchg            si,bx
+       xchg            byte ptr -10H[bp],al
+L$20:
+       test            al,1
+       je              L$21
+       mov             ax,word ptr cs:MX_CLIPX1
+       sub             ax,di
+       mov             di,word ptr cs:MX_CLIPX1
+       jmp             L$22
+L$21:
+       test            al,2
+       je              L$23
+       mov             ax,word ptr cs:MX_CLIPX2
+       sub             ax,di
+       mov             di,word ptr cs:MX_CLIPX2
+L$22:
+       imul            word ptr -0cH[bp]
+       idiv            word ptr -0aH[bp]
+       add             bx,ax
+       mov             al,8
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jg              L$26
+       mov             al,4
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jl              L$26
+       xor             al,al
+       jmp             L$26
+L$23:
+       test            al,4
+       je              L$24
+       mov             ax,word ptr cs:MX_CLIPY1
+       sub             ax,bx
+       mov             bx,word ptr cs:MX_CLIPY1
+       jmp             L$25
+L$24:
+       mov             ax,word ptr cs:MX_CLIPY2
+       sub             ax,bx
+       mov             bx,word ptr cs:MX_CLIPY2
+L$25:
+       imul            word ptr -0aH[bp]
+       idiv            word ptr -0cH[bp]
+       add             di,ax
+       mov             al,1
+       cmp             di,word ptr cs:MX_CLIPX1
+       jl              L$26
+       mov             al,2
+       cmp             di,word ptr cs:MX_CLIPX2
+       jg              L$26
+       xor             al,al
+L$26:
+       mov             ah,byte ptr -10H[bp]
+       test            ah,al
+       jne             L$28
+       or              ah,al
+       je              L$27
+       jmp             near ptr L$19
+L$27:
+       mov             ax,di
+       mov             dx,si
+       clc
+       ret
+L$28:
+       stc
+       ret
+L$29:
+       mov             di,ax
+       neg             di
+       shl             cx,1
+       mov             word ptr -6[bp],cx
+       mov             cx,ax
+       shl             ax,1
+       mov             word ptr -8[bp],ax
+       mov             al,2
+       mov             ah,byte ptr -12H[bp]
+       mov             bl,byte ptr 8[bp]
+       mov             dx,3c4H
+       inc             cx
+L$30:
+       mov             byte ptr [si],bl
+       dec             cx
+       je              L$31
+       rol             ah,1
+       adc             si,0
+       out             dx,ax
+       add             di,word ptr -6[bp]
+       jl              L$30
+       add             si,word ptr -0cH[bp]
+       sub             di,word ptr -8[bp]
+       jmp             L$30
+L$31:
+       ret
+L$32:
+       mov             di,cx
+       neg             di
+       shl             ax,1
+       mov             word ptr -6[bp],ax
+       mov             ax,cx
+       shl             ax,1
+       mov             word ptr -8[bp],ax
+       mov             bl,byte ptr 8[bp]
+       mov             ah,byte ptr -12H[bp]
+       mov             al,2
+       mov             dx,3c4H
+       inc             cx
+L$33:
+       mov             byte ptr [si],bl
+       dec             cx
+       je              L$34
+       add             si,word ptr -0cH[bp]
+       add             di,word ptr -6[bp]
+       jl              L$33
+       rol             ah,1
+       adc             si,0
+       out             dx,ax
+       sub             di,word ptr -8[bp]
+       jmp             L$33
+L$34:
+       ret
+L$35:
+       mov             di,ax
+       neg             di
+       shl             cx,1
+       mov             word ptr -6[bp],cx
+       mov             cx,ax
+       shl             ax,1
+       mov             word ptr -8[bp],ax
+       mov             al,2
+       mov             ah,byte ptr -12H[bp]
+       mov             bl,byte ptr 8[bp]
+       mov             dx,3c4H
+       inc             cx
+L$36:
+       mov             bh,byte ptr [si]
+       mov             byte ptr [si],bl
+       dec             cx
+       je              L$37
+       rol             ah,1
+       adc             si,0
+       out             dx,ax
+       add             di,word ptr -6[bp]
+       jl              L$36
+       add             si,word ptr -0cH[bp]
+       sub             di,word ptr -8[bp]
+       jmp             L$36
+L$37:
+       ret
+L$38:
+       mov             di,cx
+       neg             di
+       shl             ax,1
+       mov             word ptr -6[bp],ax
+       mov             ax,cx
+       shl             ax,1
+       mov             word ptr -8[bp],ax
+       mov             bl,byte ptr 8[bp]
+       mov             ah,byte ptr -12H[bp]
+       mov             al,2
+       mov             dx,3c4H
+       inc             cx
+L$39:
+       mov             bh,byte ptr [si]
+       mov             byte ptr [si],bl
+       dec             cx
+       je              L$40
+       add             si,word ptr -0cH[bp]
+       add             di,word ptr -6[bp]
+       jl              L$39
+       rol             ah,1
+       adc             si,0
+       out             dx,ax
+       sub             di,word ptr -8[bp]
+       jmp             L$39
+L$40:
+       ret
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxot.asm b/16/xw__/mxot.asm
new file mode 100755 (executable)
index 0000000..7bd6011
--- /dev/null
@@ -0,0 +1,1310 @@
+.387
+               PUBLIC  MXSETFONT
+               PUBLIC  MXSETTEXTCOLOR
+               PUBLIC  MXOUTCHAR
+               PUBLIC  MXOUTTEXT
+               PUBLIC  MXSETTEXTSTEP
+               PUBLIC  MXGETTEXTSTEP
+               EXTRN   MX_CODESEGMENT:BYTE
+               EXTRN   MXPUTIMAGE:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       ; The label referred to here is an undefined location
+       jle             0ffffff8bH
+       movsw
+       and             word ptr -7e67H[di],7e7eH
+       call            bx
+       call            bx
+       out             0ffH,ax
+       jle             L$9
+       ????
+       ????
+       ????
+       jl              L$7
+       adc             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],bh
+L$2:
+       jl              L$2
+       jl              L$8
+       adc             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],bh
+       adc             byte ptr -2[si],dl
+       push            sp
+       adc             dh,bh
+       adc             byte ptr [bx+si],bh
+L$3:
+       jl              L$3
+L$4:
+       ????
+       jl              L$5
+       inc             byte ptr [bx+si]
+       sbb             byte ptr [si],bh
+       jle             L$11
+       cmp             al,18H
+       add             bh,bh
+       out             0c3H,ax
+    DB 81H, 81H, 0c3H, 0e7H
+L$5:
+       inc             word ptr [bx+si]
+       cmp             al,66H
+       inc             dx
+       inc             dx
+    DB 66H, 3cH
+L$6:
+       add             bh,bh
+       ret
+       cwd
+       mov             bp,99bdH
+L$7:
+       ret
+       inc             word ptr [bx]
+       add             ax,word ptr [di]
+       ; The label referred to here is an undefined location
+       js              0ffffffe1H
+    DB 84H
+L$8:
+       test            byte ptr 7cH[bx+si],bh
+       add             byte ptr 7c82H[bp+si],10H
+       cmp             byte ptr [bx+si],dl
+       sbb             al,10H
+       sbb             al,10H
+       adc             byte ptr [bx+si],dl
+       xor             byte ptr [bx+si],dh
+       and             bh,byte ptr ds:[2222H]
+       pushad
+       cwd
+       pop             dx
+       cmp             al,0e7H
+       out             3cH,ax
+       pop             dx
+       cwd
+       add             byte ptr [bx+si],dl
+       xor             byte ptr -10H[bx+si],dh
+L$9:
+       jo              L$10
+       adc             byte ptr [bx+si],al
+       add             al,0e0H
+       lock loopnz     L$6
+       adc             byte ptr [bx+si],38H
+       push            sp
+       adc             byte ptr [bx+si],dl
+       push            sp
+       cmp             byte ptr [bx+si],dl
+       dec             ax
+       dec             ax
+       dec             ax
+       dec             ax
+       dec             ax
+       add             byte ptr [bx+si],cl
+       jle             L$4
+       xchg            ax,dx
+       jb              L$10
+       adc             dl,byte ptr [bp+si]
+       add             byte ptr [si],bh
+       and             bl,byte ptr [bx+si]
+       and             al,24H
+       sbb             byte ptr 3cH[si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+    DB 0, 3eH
+    DD ds:[3eH]
+L$10:
+       add             byte ptr [bx+si],bh
+       push            sp
+    DB 10H
+L$11:
+       adc             byte ptr [bx+si],dl
+       push            sp
+       cmp             dh,bh
+       add             byte ptr [bx+si],dl
+       cmp             byte ptr 10H[si],dl
+       adc             byte ptr [bx+si],dl
+       add             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr 38H[si],dl
+       adc             byte ptr [bx+si],al
+       add             byte ptr [bx+si],cl
+       add             al,0feH
+       add             al,8
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],ah
+       inc             ax
+       inc             byte ptr 20H[bx+si]
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr -380H[bx+si],0
+       add             byte ptr [bx+si],al
+       and             al,42H
+       inc             word ptr 24H[bp+si]
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],bh
+L$12:
+       jl              L$12
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       ????
+       jl              L$15
+       adc             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       add             byte ptr [bx+si],dl
+       add             byte ptr [bx+si],al
+       and             al,24H
+       add             byte ptr [bx+si],al
+    DB 0
+L$13:
+       add             byte ptr [bx+si],al
+       and             al,24H
+       jle             140H
+       jle             142H
+L$14:
+       and             al,0
+       cmp             byte ptr 50H[si],dl
+       cmp             byte ptr [si],dl
+       push            sp
+       cmp             byte ptr [bx+si],dl
+       add             byte ptr [bp+si],al
+       inc             sp
+       or              byte ptr [bx+si],dl
+       and             byte ptr [bp+si],al
+       cmp             byte ptr 38H[si],al
+       pusha
+       xchg            ax,sp
+L$15:
+    DB 88H
+L$16:
+       je              138H
+       and             byte ptr [bx+si],ah
+       inc             ax
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],dl
+       and             byte ptr 40H[bx+si],al
+       inc             ax
+       and             byte ptr [bx+si],dl
+       add             byte ptr 20H[bx+si],al
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],ah
+L$17:
+       inc             ax
+       add             byte ptr [bx+si],al
+       and             al,18H
+       jle             L$18
+       and             al,0
+       add             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],dl
+       jl              L$18
+       adc             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],dl
+       and             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       cld
+    DB 0
+L$18:
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],dl
+       add             byte ptr [bx+si],al
+       add             al,8
+       adc             byte ptr [bx+si],ah
+       inc             ax
+L$19:
+       add             byte ptr [bx+si],7cH
+       ????
+    DB 8aH, 92H
+L$20:
+       mov             byte ptr 0c6H,al
+    DD L$21
+L$21:
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],bh
+       add             byte ptr L$13[bx+si],bh
+       add             al,18H
+       pusha
+       cmp             ah,0
+       js              L$14
+       add             al,38H
+       add             al,84H
+       js              L$22
+L$22:
+       sbb             al,24H
+       inc             sp
+       test            dh,bh
+       add             al,0eH
+       add             ah,bh
+       cmp             al,4
+       add             al,84H
+       js              L$23
+L$23:
+       js              L$16
+       cmp             al,84H
+       test            byte ptr [bx+si],bh
+       cld
+       add             al,4
+       or              byte ptr [bx+si],dl
+       and             byte ptr [bx+si],ah
+       add             byte ptr -7cH[bx+si],bh
+       test            byte ptr -7cH[bx+si],bh
+       test            byte ptr [bx+si],bh
+       js              L$17
+       test            byte ptr 4[si],bh
+       test            byte ptr [bx+si],bh
+       add             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],al
+       add             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],ah
+       or              byte ptr [bx+si],dl
+       and             byte ptr 20H[bx+si],al
+       adc             byte ptr [bx+si],cl
+       add             byte ptr [bx+si],al
+       add             ah,bh
+       add             byte ptr [bx+si],al
+       cld
+       add             byte ptr [bx+si],al
+       inc             ax
+       and             byte ptr [bx+si],dl
+       or              byte ptr [bx+si],dl
+       and             byte ptr [bx+si],al
+       js              L$19
+       add             al,8
+       adc             byte ptr [bx+si],al
+L$24:
+       adc             byte ptr [bx+si],al
+       jl              L$20
+       mov             dx,0bea6H
+       cmp             byte ptr [si],78H
+       test            byte ptr -7b04H[si],al
+       test            byte ptr -800H[si],al
+       test            byte ptr -7b08H[si],al
+       test            al,bh
+       add             byte ptr -7cH[bx+si],bh
+       add             byte ptr -7b80H[bx+si],78H
+       add             al,dh
+       mov             byte ptr -7b7cH[si],al
+       mov             al,dh
+       add             ah,bh
+       add             byte ptr -7f10H[bx+si],80H
+       cld
+       add             ah,bh
+       add             byte ptr -7f10H[bx+si],80H
+       add             byte ptr [bx+si],78H
+       test            byte ptr -7b64H[bx+si],al
+       test            byte ptr [bx+si],bh
+       test            byte ptr -37cH[si],al
+       test            byte ptr 84H[si],al
+       cmp             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       cmp             byte ptr [bx+si],al
+       sbb             al,8
+       or              byte ptr [bx+si],cl
+       mov             byte ptr 70H[bx+si],cl
+       test            byte ptr -1f70H[bx+si],cl
+       nop
+       mov             byte ptr -8000H[si],al
+       add             byte ptr -7f80H[bx+si],80H
+       cld
+       add             dh,al
+       stosb
+       xchg            ax,dx
+       add             byte ptr -7d7eH[bp+si],0
+       add             dl,0a2H
+       xchg            ax,dx
+       mov             al,byte ptr 82H[bp]
+       js              L$24
+       test            byte ptr -7b7cH[si],al
+       js              L$25
+L$25:
+       clc
+       test            byte ptr -7f08H[si],al
+       add             byte ptr 7800H[bx+si],84H
+       test            byte ptr -776cH[si],al
+       jbe             L$26
+L$26:
+       clc
+       test            byte ptr -6f08H[si],al
+       mov             byte ptr 7800H[si],al
+       test            byte ptr 478H[bx+si],al
+       test            byte ptr [bx+si],bh
+       ????
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       add             byte ptr -7b7cH[si],al
+       test            byte ptr 7884H[si],al
+       add             byte ptr -7b7cH[si],al
+       test            byte ptr 3048H[si],al
+       add             byte ptr -7d7eH[bp+si],al
+       adc             byte ptr -3956H[bp+si],0
+       add             byte ptr 28H[si],10H
+       sub             byte ptr -7eH[si],al
+       add             byte ptr 44H[si],al
+       inc             sp
+       cmp             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       add             dh,bh
+       add             al,8
+       adc             byte ptr [bx+si],ah
+       inc             ax
+       inc             byte ptr [bx+si]
+       js              L$32
+       inc             ax
+       inc             ax
+       inc             ax
+       inc             ax
+       js              L$27
+L$27:
+       add             byte ptr 2040H[bx+si],al
+       adc             byte ptr [bx+si],cl
+       add             al,0
+       js              L$29
+       or              byte ptr [bx+si],cl
+       or              byte ptr [bx+si],cl
+       js              L$28
+L$28:
+       adc             byte ptr [bx+si],ch
+L$29:
+       inc             sp
+       add             byte ptr [bx+si],0
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             bh,bh
+       and             byte ptr [bx+si],ah
+       adc             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       cmp             byte ptr [si],al
+       cmp             al,44H
+       jl              L$30
+L$30:
+       add             byte ptr 40H[bx+si],al
+       js              L$33
+       inc             sp
+       js              L$31
+L$31:
+       add             byte ptr [bx+si],al
+L$32:
+       cmp             al,40H
+       inc             ax
+       inc             ax
+       cmp             al,0
+       add             byte ptr [si],al
+       add             al,3cH
+       inc             sp
+       inc             sp
+       cmp             al,0
+       add             byte ptr [bx+si],al
+       cmp             byte ptr 7cH[si],al
+       inc             ax
+       cmp             al,0
+       add             byte ptr [si],cl
+       adc             byte ptr [si],bh
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       cmp             al,44H
+       inc             sp
+       cmp             al,4
+       cmp             byte ptr [bx+si],al
+       inc             ax
+       inc             ax
+       js              L$35
+       inc             sp
+       inc             sp
+       add             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       add             byte ptr [bx+si],al
+       add             al,0
+       add             al,4
+       add             al,44H
+       cmp             byte ptr [bx+si],al
+L$33:
+       inc             ax
+       inc             ax
+       push            ax
+       pusha
+       push            ax
+       dec             ax
+       add             byte ptr [bx+si],al
+       xor             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       add             byte ptr [bx+si],al
+       add             byte ptr 54H[bx+si],ch
+       push            sp
+       inc             sp
+       inc             sp
+       add             byte ptr [bx+si],al
+       add             byte ptr 44H[bx+si],bh
+       inc             sp
+       inc             sp
+       inc             sp
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],bh
+       inc             sp
+       inc             sp
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+L$34:
+       js              L$42
+       inc             sp
+       js              L$41
+       inc             ax
+    DB 0
+L$35:
+       add             byte ptr [si],bh
+       inc             sp
+       inc             sp
+       cmp             al,4
+       add             al,0
+       add             byte ptr 60H[si],bl
+       inc             ax
+       inc             ax
+       inc             ax
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],bh
+L$36:
+       inc             ax
+       jl              L$38
+       jl              L$37
+L$37:
+       add             byte ptr [bx+si],dl
+L$38:
+       cmp             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       sbb             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       inc             sp
+       inc             sp
+       inc             sp
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       inc             sp
+       inc             sp
+       inc             sp
+       sub             byte ptr [bx+si],dl
+       add             byte ptr [bx+si],al
+       add             byte ptr 44H[si],al
+L$39:
+       push            sp
+       push            sp
+       insb
+       add             byte ptr [bx+si],al
+       add             byte ptr 28H[si],al
+L$40:
+       adc             byte ptr [bx+si],ch
+       inc             sp
+L$41:
+    DB 0
+L$42:
+       add             byte ptr [bx+si],al
+       inc             sp
+       inc             sp
+       inc             sp
+       cmp             al,4
+       jl              L$43
+L$43:
+       add             byte ptr 4[si],bh
+       cmp             byte ptr 7cH[bx+si],al
+       add             byte ptr [bx+si],al
+       or              byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dh
+       adc             byte ptr [bx+si],dl
+       or              byte ptr [bx+si],al
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],al
+       and             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],bl
+       adc             byte ptr [bx+si],dl
+       and             byte ptr -68H[si],ah
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],dl
+       sub             byte ptr -7eH[si],al
+       cmp             dh,0
+       jl              L$34
+       add             byte ptr 7c80H[bx+si],4
+       jl              L$44
+L$44:
+       sub             byte ptr [bx+si],al
+       inc             sp
+       inc             sp
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       cmp             al,0
+       jl              L$54
+       jl              L$53
+       jl              L$45
+L$45:
+       jle             L$36
+       cmp             byte ptr [si],al
+       cmp             al,44H
+       jl              L$46
+L$46:
+       and             al,0
+L$47:
+       cmp             byte ptr [si],al
+       cmp             al,44H
+       jl              L$48
+L$48:
+       js              L$49
+L$49:
+       cmp             byte ptr [si],al
+       cmp             al,44H
+       jl              L$50
+L$50:
+       sbb             byte ptr [bx+si],bl
+       cmp             byte ptr [si],al
+       cmp             al,44H
+       jl              L$51
+L$51:
+       add             byte ptr [bx+si],al
+       js              L$39
+       cmp             byte ptr 8[bx+si],38H
+       jl              L$40
+       cmp             byte ptr 7cH[si],al
+       inc             ax
+       cmp             al,0
+       dec             ax
+       add             byte ptr [bx+si],bh
+       inc             sp
+       jl              L$55
+       cmp             al,0
+       js              L$52
+L$52:
+       cmp             byte ptr 7cH[si],al
+       inc             ax
+L$53:
+       cmp             al,0
+L$54:
+       add             byte ptr [bx+si],ch
+       add             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],ch
+       add             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],al
+       add             byte ptr [bx+si],dh
+       add             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],al
+       dec             ax
+       add             byte ptr -7cH[bx+si],bh
+       cld
+       test            byte ptr 3000H[si],al
+       xor             byte ptr -7cH[bx+si],bh
+       cld
+       test            byte ptr 3800H[si],al
+       add             ah,bh
+       xor             al,80H
+       cld
+       add             byte ptr [bx+si],al
+       add             byte ptr 8[bp],bh
+       jle             L$59
+L$55:
+       jle             L$56
+L$56:
+       jle             L$47
+       nop
+       cld
+       nop
+       nop
+       sahf
+       add             byte ptr -7eH[si],bh
+       cmp             byte ptr 44H[si],al
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       sub             byte ptr [bx+si],al
+       cmp             byte ptr 44H[si],al
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       jo              L$57
+L$57:
+       cmp             byte ptr 44H[si],al
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       cmp             byte ptr [si],al
+       inc             sp
+       inc             sp
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       jo              L$58
+L$58:
+       inc             sp
+       inc             sp
+       inc             sp
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       sub             byte ptr [bx+si],al
+       inc             sp
+       inc             sp
+       inc             sp
+       cmp             al,4
+       jl              L$64
+       add             byte ptr -7cH[bx+si],bh
+       test            byte ptr 78H[si],al
+       dec             ax
+       add             byte ptr -7b7cH[si],al
+    DB 84H
+L$59:
+       js              4d8H
+       add             byte ptr [bx+si],dl
+       cmp             byte ptr 40H[bx+si],al
+       inc             ax
+       cmp             byte ptr [bx+si],dl
+       cmp             byte ptr 40H[si],al
+       loopnz          L$66
+       inc             ax
+       cmp             ah,44H
+       jl              L$60
+       jl              L$61
+       jl              L$62
+       add             al,dh
+       mov             byte ptr -7d09H[bp+si],cl
+       add             byte ptr 0c00H[bp+si],12H
+    DB 10H
+L$60:
+       sbb             byte ptr [bx+si],dh
+L$61:
+    DB 10H, 90H
+L$62:
+       pusha
+       cmp             al,0
+       cmp             byte ptr [si],al
+       cmp             al,44H
+       jl              L$63
+L$63:
+       add             byte ptr [bx+si],bl
+       add             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],al
+    DB 1cH
+L$64:
+       add             byte ptr [bx+si],bh
+       inc             sp
+       inc             sp
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       sbb             al,0
+       inc             sp
+       inc             sp
+       inc             sp
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       jl              L$65
+L$65:
+       js              L$67
+       inc             sp
+L$66:
+       inc             sp
+       inc             sp
+       add             byte ptr [si],bh
+       inc             sp
+       push            sp
+       dec             sp
+       inc             sp
+       add             byte ptr [bx+si],bl
+       and             al,24H
+       push            ds
+       add             byte ptr ds:[0],bh
+       sbb             al,22H
+       and             bl,byte ptr [si]
+       add             byte ptr ds:[0],bh
+       adc             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],ah
+       inc             ax
+       inc             dx
+       cmp             al,0
+       add             byte ptr [bx+si],al
+       add             ah,bh
+       add             byte ptr [bx+si],0
+       add             byte ptr [bx+si],al
+       cld
+       add             al,4
+       add             byte ptr [bx+si],al
+       inc             ax
+       inc             sp
+       dec             ax
+       push            di
+       and             word ptr 4[bx],ax
+       pop             es
+       inc             ax
+       inc             sp
+       dec             ax
+       push            dx
+       dec             dx
+       pop             ds
+    DB 2
+L$67:
+       adc             byte ptr [bx+si],al
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+L$68:
+       adc             byte ptr [bx+si],al
+       add             byte ptr [si],ah
+L$69:
+       dec             ax
+       nop
+       dec             ax
+       and             al,0
+       add             byte ptr [bx+si],al
+       dec             ax
+       and             al,12H
+       and             al,48H
+       add             byte ptr [bx+si],al
+       and             cl,byte ptr -77deH[bx+si]
+       and             cl,byte ptr -77deH[bx+si]
+       push            bp
+       stosb
+       push            bp
+       stosb
+       push            bp
+       stosb
+       push            bp
+       stosb
+       ????
+       ja              L$68
+       out             dx,al
+       ????
+       ja              L$69
+       out             dx,al
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       clc
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             al,bh
+       sbb             al,bh
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr ds:[3636H],dh
+       div             byte ptr ss:[3636H]
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       ????
+       add             byte ptr ss:[bx+si],al
+       clc
+       sbb             al,bh
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr ds:[0f636H],dh
+       push            es
+       div             byte ptr ds:[3636H]
+       add             byte ptr ss:[bx+si],al
+       inc             byte ptr ds:[36f6H]
+       test            byte ptr ss:[0feH],0
+       add             byte ptr ds:[3636H],dh
+       inc             byte ptr ss:[bx+si]
+       add             byte ptr [bx+si],al
+       sbb             byte ptr [bx+si],bl
+       clc
+       sbb             al,bh
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             al,bh
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx],bl
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             bh,bh
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             bh,bh
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             bh,bh
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             bh,bh
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx],bl
+       sbb             byte ptr [bx],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr ds:[3636H],dh
+       aaa
+       aaa
+       xor             byte ptr [bx],bh
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx],bh
+       xor             byte ptr [bx],dh
+       test            word ptr ss:[bx+si],0ffH
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       inc             word ptr [bx+si]
+       div             word ptr ds:[3636H]
+       aaa
+       xor             byte ptr [bx],dh
+       add             byte ptr ss:[bx+si],al
+       inc             word ptr [bx+si]
+       inc             word ptr [bx+si]
+       add             byte ptr [bx+si],al
+       test            word ptr ss:[bx+si],36f7H
+       sbb             byte ptr ss:[bx+si],bl
+       inc             word ptr [bx+si]
+       inc             word ptr [bx+si]
+       add             byte ptr [bx+si],al
+       inc             word ptr ss:[bx+si]
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       inc             word ptr [bx+si]
+       call            dword ptr [bx+si]
+       sbb             byte ptr [bx+si],bl
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       push            word ptr ds:[3636H]
+       aas
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],bl
+       sbb             byte ptr [bx],bl
+       sbb             byte ptr [bx],bl
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx],bl
+       sbb             byte ptr [bx],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx],bh
+       push            word ptr ss:[3636H]
+       sbb             byte ptr [bx+si],bl
+       call            dword ptr [bx+si]
+       call            dword ptr [bx+si]
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       sbb             byte ptr [bx+si],bl
+       clc
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx],bl
+    DB 18H
+L$70:
+       sbb             byte ptr [bx+si],bl
+       ????
+       ????
+       ????
+       ????
+       ????
+       ????
+       ????
+       inc             word ptr [bx+si]
+       add             byte ptr [bx+si],al
+       add             bh,bh
+       ????
+       ????
+       push            ax
+       ????
+       ????
+       ????
+       ????
+       ????
+       ????
+       ????
+       ????
+       ????
+       ????
+       ????
+       ????
+       ????
+       ????
+       ????
+       ????
+       ????
+       ????
+       inc             word ptr [bx+si]
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr -6cH[bp+si],ah
+       mov             byte ptr 62H[si],dl
+       add             al,dh
+       mov             al,dh
+       mov             byte ptr -7f10H[bx+si],cl
+       add             al,bh
+       mov             byte ptr -7f80H[bx+si],al
+       add             byte ptr [bx+si],0
+       cld
+       dec             ax
+       dec             ax
+       dec             ax
+       dec             ax
+       dec             ax
+       add             ah,bh
+       test            byte ptr 20H[bx+si],al
+       inc             ax
+       test            ah,bh
+       add             byte ptr [si],bh
+       inc             ax
+       cmp             byte ptr 44H[si],al
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       inc             sp
+       inc             sp
+       inc             sp
+       js              L$71
+       inc             ax
+       add             byte ptr ds:[848H],dh
+       or              byte ptr [bx+si],cl
+       or              byte ptr [bx+si],al
+       cmp             byte ptr [bx+si],dl
+       cmp             byte ptr 44H[si],al
+       cmp             byte ptr [bx+si],dl
+       cmp             byte ptr -7cH[bx+si],bh
+       test            ah,bh
+       test            byte ptr 78H[si],al
+       js              L$70
+       test            byte ptr 4848H[si],al
+       int             3
+       add             byte ptr 4[bx+si],bh
+       cmp             byte ptr 44H[si],al
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       insb
+       xchg            ax,dx
+       xchg            ax,dx
+       insb
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       cmp             al,byte ptr 5aH[si]
+       and             bl,byte ptr [si]
+       sbb             byte ptr [bx+si],ah
+       inc             ax
+       js              L$73
+       and             byte ptr [bx+si],bl
+L$71:
+       add             byte ptr -7cH[bx+si],bh
+       test            byte ptr -7b7cH[si],al
+       test            byte ptr [bx+si],al
+       add             ah,bh
+       add             ah,bh
+       add             ah,bh
+       add             byte ptr [bx+si],al
+       and             byte ptr [bx+si],ah
+       clc
+       and             byte ptr [bx+si],ah
+       add             al,bh
+       add             byte ptr [bx+si],ah
+       adc             byte ptr [bx+si],cl
+       adc             byte ptr [bx+si],ah
+       add             byte ptr [si],bh
+       or              byte ptr [bx+si],dl
+       and             byte ptr [bx+si],dl
+       or              byte ptr [bx+si],al
+       jl              L$72
+L$72:
+       or              al,12H
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       adc             byte ptr [bx+si],dl
+       nop
+       pusha
+       add             byte ptr [bx+si],dl
+       add             byte ptr [si],bh
+L$73:
+       adc             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       xor             cl,byte ptr [si]
+       xor             cl,byte ptr [si]
+       add             byte ptr [bx+si],bh
+       inc             sp
+       inc             sp
+       cmp             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       sbb             byte ptr [bx+si],bl
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],bl
+       add             byte ptr [bx+si],al
+       add             byte ptr ds:[808H],cl
+       or              byte ptr 28H[bx+si],cl
+       sbb             byte ptr [bx+si],cl
+       cmp             byte ptr [si],ah
+       and             al,24H
+       and             al,0
+       add             byte ptr [bx+si],al
+       cmp             al,4
+       cmp             al,20H
+       cmp             al,0
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       cmp             al,3cH
+       cmp             al,3cH
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+L$74:
+    DW offset L$1
+L$75:
+    DB 8
+L$76:
+       add             byte ptr [bx+si],cl
+    DB 0
+L$77:
+    DW offset L$1
+L$78:
+    DW seg L$1
+L$79:
+       or              byte ptr [bx+si],al
+L$80:
+       or              byte ptr [bx+si],al
+L$81:
+       or              byte ptr [bx+si],al
+L$82:
+       inc             word ptr [bx+si]
+L$83:
+       add             byte ptr [bx+si],al
+L$84:
+       or              byte ptr [bx+si],al
+L$85:
+       add             byte ptr [bx+si],al
+MXSETFONT:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       mov             ax,word ptr 0cH[bp]
+       test            ax,ax
+       jne             L$87
+       mov             ax,word ptr 0aH[bp]
+       cmp             ax,1
+       jb              L$86
+       xor             ax,ax
+L$86:
+       shl             ax,1
+       shl             ax,1
+       mov             bx,ax
+       mov             ax,word ptr L$74[bx]
+       mov             word ptr L$77,ax
+       mov             word ptr L$78,cs
+       mov             al,byte ptr L$75[bx]
+       xor             ah,ah
+       mov             word ptr L$79,ax
+       mov             word ptr L$84,ax
+       mov             dl,byte ptr L$76[bx]
+       xor             dh,dh
+       mov             word ptr L$80,dx
+       mul             dx
+       mov             word ptr L$81,ax
+       mov             word ptr L$84,ax
+       xor             ax,ax
+       mov             word ptr L$85,ax
+       jmp             L$88
+L$87:
+       mov             ax,0ffffH
+       mov             bx,word ptr 8[bp]
+       cmp             bx,10H
+       ja              L$88
+       mov             dx,word ptr 6[bp]
+       cmp             dx,20H
+       ja              L$88
+       mov             word ptr L$79,bx
+       mov             word ptr L$80,dx
+       mov             ax,bx
+       add             ax,7
+       shr             ax,1
+       shr             ax,1
+       shr             ax,1
+       mul             dx
+       mov             word ptr L$81,ax
+       mov             ax,word ptr 0aH[bp]
+       mov             word ptr L$77,ax
+       mov             ax,word ptr 0cH[bp]
+       mov             word ptr L$78,ax
+       xor             ax,ax
+L$88:
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+MXSETTEXTCOLOR:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       mov             ax,word ptr 8[bp]
+       mov             word ptr L$82,ax
+       mov             ax,word ptr 6[bp]
+       mov             word ptr L$83,ax
+       xor             ax,ax
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            4
+MXOUTCHAR:
+       push            bp
+       mov             bp,sp
+       sub             sp,202H
+       push            ds
+       push            si
+       push            es
+       push            di
+       lds             si,dword ptr cs:L$77
+       mov             al,byte ptr 6[bp]
+       xor             ah,ah
+       mul             word ptr cs:L$81
+       add             si,ax
+       mov             ax,ss
+       mov             es,ax
+       lea             di,-200H[bp]
+       mov             dx,word ptr cs:L$82
+       mov             ax,word ptr cs:L$80
+       mov             word ptr -202H[bp],ax
+L$89:
+       mov             cx,word ptr cs:L$79
+       mov             bh,byte ptr [si]
+       inc             si
+       cmp             cx,8
+       jbe             L$90
+       mov             bl,byte ptr [si]
+       inc             si
+L$90:
+       mov             al,dl
+       shl             bx,1
+       jb              L$91
+       mov             al,dh
+L$91:
+       mov             byte ptr es:[di],al
+       inc             di
+       dec             cx
+       jne             L$90
+       dec             word ptr -202H[bp]
+       jne             L$89
+       lea             ax,-200H[bp]
+       push            es
+       push            ax
+       push            word ptr 0aH[bp]
+       push            word ptr 8[bp]
+       push            word ptr cs:L$79
+       push            word ptr cs:L$80
+       push            word ptr cs:L$83
+       push            cs
+       call            near ptr MX_TEXT:MXPUTIMAGE
+       xor             ax,ax
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            6
+MXOUTTEXT:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       lds             si,dword ptr 6[bp]
+L$92:
+       mov             al,byte ptr [si]
+       test            al,al
+       je              L$93
+       inc             si
+       push            word ptr 0cH[bp]
+       push            word ptr 0aH[bp]
+       push            ax
+       push            cs
+       call            near ptr MXOUTCHAR
+       mov             ax,word ptr cs:L$84
+       add             word ptr 0cH[bp],ax
+       mov             ax,word ptr cs:L$85
+       add             word ptr 0aH[bp],ax
+       dec             word ptr -202H[bp]
+       jne             L$92
+L$93:
+       xor             ax,ax
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+       retf
+MXSETTEXTSTEP:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       mov             ax,word ptr 8[bp]
+       mov             word ptr L$84,ax
+       mov             ax,word ptr 6[bp]
+       mov             word ptr L$85,ax
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            4
+MXGETTEXTSTEP:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       mov             ax,word ptr cs:L$84
+       lds             si,dword ptr 0aH[bp]
+       mov             word ptr [si],ax
+       mov             ax,word ptr cs:L$85
+       lds             si,dword ptr 6[bp]
+       mov             word ptr [si],ax
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxot_.asm b/16/xw__/mxot_.asm
new file mode 100755 (executable)
index 0000000..e431b13
--- /dev/null
@@ -0,0 +1,333 @@
+;-----------------------------------------------------------\r
+;\r
+; MXOT.ASM - Text functions\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+;WARN    PRO\r
+;NOWARN  RES                             ; We use the reserved name 'WIDTH'\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxOutChar\r
+PUBLIC  mxOutText\r
+PUBLIC  mxSetFont\r
+PUBLIC  mxSetTextColor\r
+PUBLIC  mxGetTextStep\r
+PUBLIC  mxSetTextStep\r
+\r
+MAX_WIDTH       EQU     16              ; Must be <= 16\r
+MAX_HEIGHT      EQU     32\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   mx_CodeSegment  : WORD\r
+EXTRN   mxPutImage      : FAR\r
+\r
+; Default 8x8 font\r
+fnt_Default     LABEL  BYTE\r
+        INCLUDE DEFAULT.FNT\r
+\r
+; Table of system fonts\r
+tbl_SystemFont   LABEL   WORD\r
+        DW      fnt_Default, 8, 8\r
+\r
+MX_MAXSYSFONT   EQU     ($-OFFSET tbl_SystemFont) SHR 2\r
+\r
+mx_FontPtr      DW      OFFSET fnt_Default, SEG MX_TEXT\r
+mx_FontWidth    DW      8               ; Font width in pixels\r
+mx_FontHeight   DW      8               ; Font height in pixels\r
+mx_FontCharSize DW      8               ; Size in bytes of a font character\r
+mx_FontColor    DW      00FFh           ; Color: foreground + background*256\r
+mx_FontOp       DW      OP_MOVE         ; Raster op\r
+mx_DeltaX       DW      8               ; Horizontal step\r
+mx_DeltaY       DW      0               ; Vertical step\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the current font.\r
+;\r
+; Input:\r
+;       Font    = pointer to font data\r
+;       Width   = width of font character in pixels\r
+;       Height  = height of font character in pixels\r
+; Output:\r
+;       AX = 0 on success, else invalid parameters\r
+;\r
+; Note: when the high word of Font (i.e. the segment) is zero, the low\r
+;       word is used to select one of the system fonts.\r
+;\r
+mxSetFont       PROC FAR\r
+       push            bp\r
+       mov             bp,sp\r
+       sub             sp,0\r
+       push            ds\r
+        .enter  0\r
+        .push   ds\r
+\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, WORD PTR Font[2]    ; Get font segment\r
+        test    ax, ax                  ; Null segment?\r
+        jnz     @@UserFont              ; No, install user font\r
+\r
+; Install system font\r
+        mov     ax, WORD PTR Font[0]    ; Get font number\r
+        cmp     ax, MX_MAXSYSFONT       ; Check range\r
+        jb      @@SystemFont\r
+        xor     ax, ax                  ; Out of range, use default font\r
+@@SystemFont:\r
+        shl     ax, 1\r
+        shl     ax, 1\r
+        mov     bx, ax\r
+        mov     ax, tbl_SystemFont[bx]  ; Get font offset\r
+        mov     WORD PTR mx_FontPtr[0], ax\r
+        mov     WORD PTR mx_FontPtr[2], cs\r
+        mov     al, BYTE PTR tbl_SystemFont[bx+2]\r
+        xor     ah, ah\r
+        mov     [mx_FontWidth], ax\r
+        mov     [mx_DeltaX], ax\r
+        mov     dl, BYTE PTR tbl_SystemFont[bx+3]\r
+        xor     dh, dh\r
+        mov     [mx_FontHeight], dx\r
+        mul     dx\r
+        mov     [mx_FontCharSize], ax\r
+        mov     [mx_DeltaX], ax\r
+        xor     ax, ax\r
+        mov     [mx_DeltaY], ax\r
+        jmp     @@Exit\r
+\r
+; Install user font\r
+@@UserFont:\r
+        mov     ax, -1                  ; Assume an error\r
+        mov     bx, [bp+8]\r
+        cmp     bx, MAX_WIDTH\r
+        ja      @@Exit                  ; Invalid character width\r
+        mov     dx, [bp+4]\r
+        cmp     dx, MAX_HEIGHT\r
+        ja      @@Exit                  ; Invalid character height\r
+        mov     [mx_FontWidth], bx\r
+        mov     [mx_FontHeight], dx\r
+        mov     ax, bx\r
+        add     ax, 7\r
+        shr    ax, 1\r
+        shr    ax, 1\r
+       shr    ax, 1\r
+        mul     dx\r
+        mov     [mx_FontCharSize], ax\r
+        mov     ax, WORD PTR Font[0]\r
+        mov     WORD PTR mx_FontPtr[0], ax\r
+        mov     ax, WORD PTR Font[2]\r
+        mov     WORD PTR mx_FontPtr[2], ax\r
+        xor     ax, ax\r
+\r
+@@Exit:\r
+        .pop    ds\r
+        ASSUME  ds:NOTHING\r
+        ;.leave  ARG_SIZE\r
+mxSetFont       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the text color and raster op.\r
+;\r
+; Input:\r
+;       Color   = text color (foreground + background*256)\r
+;       Op      = raster op\r
+; Output:\r
+;       none\r
+;\r
+mxSetTextColor  PROC FAR\r
+        ARG     Op:WORD,        \\r
+                Color:WORD      = ARG_SIZE\r
+        .enter  0\r
+        .push   ds\r
+\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, [Color]\r
+        mov     [mx_FontColor], ax\r
+        mov     ax, [Op]\r
+        mov     [mx_FontOp], ax\r
+\r
+        xor     ax, ax\r
+        .pop    ds\r
+        ASSUME  ds:NOTHING\r
+        .leave  ARG_SIZE\r
+mxSetTextColor  ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a character using the current font and attributes.\r
+;\r
+; Input:\r
+;       X, Y    = video coordinates\r
+;       C       = character to print\r
+; Output:\r
+;       none\r
+;\r
+mxOutChar       PROC FAR\r
+        ARG     C:BYTE:2,       \\r
+                Y:WORD,         \\r
+                X:WORD          = ARG_SIZE\r
+        LOCAL   Image:BYTE:MAX_WIDTH*MAX_HEIGHT,        \\r
+                Count:WORD                              = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+        ASSUME  ds:NOTHING\r
+\r
+; Gets the pointer to font data for the selected character\r
+        lds     si, DWORD PTR [mx_FontPtr]\r
+        mov     al, [C]\r
+        xor     ah, ah\r
+        mul     [mx_FontCharSize]       ; Offset into font\r
+        add     si, ax                  ; DS:SI -> font data for character\r
+\r
+; Converts font data into a 256-color linear image\r
+        mov     ax, ss\r
+        mov     es, ax\r
+        lea     di, [Image]\r
+        mov     dx, [mx_FontColor]\r
+        mov     ax, [mx_FontHeight]\r
+        mov     [Count], ax\r
+@@HeightLoop:\r
+        mov     cx, [mx_FontWidth]\r
+        mov     bh, ds:[si]\r
+        inc     si                      ; Get a byte from font data\r
+        cmp     cx, 8\r
+        jbe     @@WidthLoop             ; Ok for width <= 8\r
+        mov     bl, ds:[si]             ; Get another byte\r
+        inc     si\r
+@@WidthLoop:\r
+        mov     al, dl                  ; Assume foreground color\r
+        shl     bx, 1                   ; Is font bit set?\r
+        jc      @@1                     ; Yes, foreground is just great\r
+        mov     al, dh                  ; Get background color\r
+@@1:\r
+        mov     es:[di], al             ; Put pixel into image\r
+        inc     di\r
+        dec     cx\r
+        jnz     @@WidthLoop\r
+        dec     [Count]\r
+        jnz     @@HeightLoop\r
+\r
+; Now pass image to mx_PutImage\r
+        lea     ax, [Image]\r
+        push    es\r
+        push    ax                      ; Pointer to image\r
+        push    [X]\r
+        push    [Y]                     ; Image coordinates\r
+        push    [mx_FontWidth]\r
+        push    [mx_FontHeight]         ; Image size\r
+        push    [mx_FontOp]             ; Raster op\r
+        call    mxPutImage              ; Write character\r
+\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+mxOutChar       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a string at the coordinates specified.\r
+;\r
+; Input:\r
+;       X, Y    = text coordinates\r
+;       S       = pointer to ASCIIZ string\r
+; Output:\r
+;       none\r
+;\r
+mxOutText       PROC FAR\r
+        ARG     S:DWORD,        \\r
+                Y:WORD,         \\r
+                X:WORD          = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+        ASSUME  ds:NOTHING\r
+\r
+        lds     si, [S]\r
+@@Loop:\r
+        mov     al, ds:[si]\r
+        test    al, al                  ; End of string?\r
+        jz      @@Exit                  ; Yes, exit\r
+        inc     si\r
+        push    [X]                     ; Display character\r
+        push    [Y]\r
+        push    ax\r
+        call    mxOutChar\r
+        mov     ax, [mx_DeltaX]\r
+        add     [X], ax                 ; Bump X coordinate\r
+        mov     ax, [mx_DeltaY]\r
+        add     [Y], ax                 ; Bump Y coordinate\r
+        dec     [Count]\r
+        jnz     @@Loop\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+        ret\r
+mxOutText       ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the distance between characters.\r
+;\r
+; Input:\r
+;       DeltaX  = horizontal distance in pixels\r
+;       DeltaY  = vertical distance in pixels\r
+; Output:\r
+;       none\r
+;\r
+; Note: this function may be used to set the text direction.\r
+;\r
+mxSetTextStep   PROC FAR\r
+        ARG     DeltaY:WORD,    \\r
+                DeltaX:WORD     = ARG_SIZE\r
+        .enter  0\r
+        .push   ds\r
+\r
+        mov     ds, [mx_CodeSegment]\r
+        ASSUME  ds:MX_TEXT\r
+\r
+        mov     ax, [DeltaX]\r
+        mov     [mx_DeltaX], ax\r
+        mov     ax, [DeltaY]\r
+        mov     [mx_DeltaY], ax\r
+\r
+        .pop    ds\r
+        .leave  ARG_SIZE\r
+mxSetTextStep   ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Gets the current distance between characters.\r
+;\r
+; Input:\r
+;       DeltaX  = pointer to horizontal distance in pixels (integer)\r
+;       DeltaY  = pointer to vertical distance in pixels (integer)\r
+; Output:\r
+;       none\r
+;\r
+mxGetTextStep   PROC FAR\r
+        ARG     DeltaY:DWORD,   \\r
+                DeltaX:DWORD    = ARG_SIZE\r
+        .enter  0\r
+        .push   ds, si\r
+        ASSUME  ds:NOTHING\r
+\r
+        mov     ax, [mx_DeltaX]\r
+        lds     si, [DeltaX]\r
+        mov     ds:[si], ax\r
+        mov     ax, [mx_DeltaY]\r
+        lds     si, [DeltaY]\r
+        mov     ds:[si], ax\r
+\r
+        .pop    ds, si\r
+        .leave  ARG_SIZE\r
+mxGetTextStep   ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r
diff --git a/16/xw__/mxpb.asm b/16/xw__/mxpb.asm
new file mode 100755 (executable)
index 0000000..36ed352
--- /dev/null
@@ -0,0 +1,4103 @@
+.387
+               PUBLIC  MX_SCANBUFFER
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MX_SCANBUFFER:
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxpf.asm b/16/xw__/mxpf.asm
new file mode 100755 (executable)
index 0000000..3777fe5
--- /dev/null
@@ -0,0 +1,328 @@
+.387
+               PUBLIC  MXFILLPOLY
+               EXTRN   MX_CLIPX1:BYTE
+               EXTRN   MX_CLIPX2:BYTE
+               EXTRN   MX_CLIPY1:BYTE
+               EXTRN   MX_CLIPY2:BYTE
+               EXTRN   MX_CODESEGMENT:BYTE
+               EXTRN   MX_SCANBUFFER:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+               EXTRN   MX_BYTESPERLINE:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+       mov             cx,word ptr [si]
+       sub             cx,word ptr [bx]
+       jg              L$2
+       ret
+L$2:
+       push            bp
+       mov             ax,word ptr 2[si]
+       mov             bx,word ptr 2[bx]
+       sub             ax,bx
+       jg              L$4
+       jl              L$6
+       mov             ax,bx
+L$3:
+       mov             word ptr es:[di],ax
+       add             di,4
+       dec             cx
+       jne             L$3
+       jmp             L$8
+L$4:
+       cwd
+       div             cx
+       mov             bp,ax
+       xor             ax,ax
+       div             cx
+       xchg            ax,bx
+       mov             dx,8000H
+L$5:
+       mov             word ptr es:[di],ax
+       add             di,4
+       add             dx,bx
+       adc             ax,bp
+       dec             cx
+       jne             L$5
+       jmp             L$8
+L$6:
+       neg             ax
+       cwd
+       div             cx
+       mov             bp,ax
+       xor             ax,ax
+       div             cx
+       xchg            ax,bx
+       mov             dx,8000H
+L$7:
+       mov             word ptr es:[di],ax
+       add             di,4
+       sub             dx,bx
+       sbb             ax,bp
+       dec             cx
+       jne             L$7
+L$8:
+       pop             bp
+       ret
+MXFILLPOLY:
+       push            bp
+       mov             bp,sp
+       sub             sp,1eH
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             cx,word ptr 10H[bp]
+       cmp             cx,3
+       jae             L$9
+       jmp             near ptr L$36
+L$9:
+       les             di,dword ptr 0cH[bp]
+       lds             si,dword ptr 8[bp]
+       mov             word ptr -16H[bp],7fffH
+       mov             word ptr -1aH[bp],8000H
+       mov             word ptr -18H[bp],7fffH
+       mov             word ptr -1eH[bp],8000H
+       xor             dx,dx
+L$10:
+       mov             bx,word ptr es:[di]
+       shl             bx,1
+       shl             bx,1
+       add             bx,si
+       mov             ax,word ptr [bx]
+       cmp             ax,word ptr -16H[bp]
+       jge             L$11
+       mov             word ptr -16H[bp],ax
+       mov             word ptr -0eH[bp],dx
+       mov             word ptr -10H[bp],dx
+L$11:
+       cmp             ax,word ptr -1aH[bp]
+       jle             L$12
+       mov             word ptr -1aH[bp],ax
+       mov             word ptr -12H[bp],dx
+L$12:
+       mov             ax,word ptr 2[bx]
+       cmp             ax,word ptr -18H[bp]
+       jge             L$13
+       mov             word ptr -18H[bp],ax
+L$13:
+       cmp             ax,word ptr -1eH[bp]
+       jle             L$14
+       mov             word ptr -1eH[bp],ax
+L$14:
+       inc             di
+       inc             dx
+       inc             di
+       inc             dx
+       dec             cx
+       jne             L$10
+       mov             ax,word ptr -1aH[bp]
+       cmp             ax,word ptr cs:MX_CLIPX1
+       jge             L$15
+       jmp             near ptr L$36
+L$15:
+       mov             bx,word ptr -16H[bp]
+       cmp             bx,word ptr cs:MX_CLIPX2
+       jle             L$16
+       jmp             near ptr L$36
+L$16:
+       sub             ax,bx
+       jg              L$17
+       jmp             near ptr L$36
+L$17:
+       mov             ax,word ptr -1eH[bp]
+       cmp             ax,word ptr cs:MX_CLIPY1
+       jge             L$18
+       jmp             near ptr L$36
+L$18:
+       mov             bx,word ptr -18H[bp]
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jle             L$19
+       jmp             near ptr L$36
+L$19:
+       sub             ax,bx
+       jg              L$20
+       jmp             near ptr L$36
+L$20:
+       dec             word ptr 10H[bp]
+       shl             word ptr 10H[bp],1
+       mov             es,word ptr cs:MX_CODESEGMENT
+       mov             ax,offset MX_TEXT:MX_SCANBUFFER
+       mov             word ptr -4[bp],ax
+       mov             si,word ptr -0eH[bp]
+L$21:
+       lds             bx,dword ptr 0cH[bp]
+       mov             di,word ptr [bx+si]
+       dec             si
+       dec             si
+       test            si,si
+       jge             L$22
+       mov             si,word ptr 10H[bp]
+L$22:
+       mov             word ptr -0eH[bp],si
+       mov             si,word ptr [bx+si]
+       shl             di,1
+       shl             di,1
+       shl             si,1
+       shl             si,1
+       lds             bx,dword ptr 8[bp]
+       add             si,bx
+       add             bx,di
+       mov             di,word ptr -4[bp]
+       call            near ptr L$1
+       mov             word ptr -4[bp],di
+       mov             si,word ptr -0eH[bp]
+       cmp             si,word ptr -12H[bp]
+       jne             L$21
+       mov             ax,offset MX_TEXT:MX_SCANBUFFER+2
+       mov             word ptr -6[bp],ax
+       mov             si,word ptr -10H[bp]
+L$23:
+       lds             bx,dword ptr 0cH[bp]
+       mov             di,word ptr [bx+si]
+       inc             si
+       inc             si
+       cmp             si,word ptr 10H[bp]
+       jbe             L$24
+       xor             si,si
+L$24:
+       mov             word ptr -10H[bp],si
+       mov             si,word ptr [bx+si]
+       shl             di,1
+       shl             di,1
+       shl             si,1
+       shl             si,1
+       lds             bx,dword ptr 8[bp]
+       add             si,bx
+       add             bx,di
+       mov             di,word ptr -6[bp]
+       call            near ptr L$1
+       mov             word ptr -6[bp],di
+       mov             si,word ptr -10H[bp]
+       cmp             si,word ptr -12H[bp]
+       jne             L$23
+       mov             si,offset MX_TEXT:MX_SCANBUFFER
+       mov             ax,word ptr -16H[bp]
+       mov             cx,word ptr -1aH[bp]
+       sub             cx,ax
+       mov             bx,word ptr cs:MX_CLIPX1
+       sub             bx,ax
+       jle             L$25
+       sub             cx,bx
+       add             ax,bx
+       mov             word ptr -16H[bp],ax
+       shl             bx,1
+       shl             bx,1
+       add             si,bx
+L$25:
+       mov             bx,ax
+       add             bx,cx
+       sub             bx,word ptr cs:MX_CLIPX2
+       jle             L$26
+       sub             cx,bx
+L$26:
+       test            cx,cx
+       jg              L$27
+       jmp             near ptr L$36
+L$27:
+       mov             word ptr -8[bp],cx
+       mov             word ptr -4[bp],si
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       mov             ax,word ptr -18H[bp]
+       cmp             ax,word ptr cs:MX_CLIPY1
+       jl              L$28
+       mov             ax,word ptr -1eH[bp]
+       cmp             ax,word ptr cs:MX_CLIPY2
+       jg              L$28
+       jmp             L$32
+L$28:
+       mov             di,cx
+       inc             di
+       sub             si,4
+L$29:
+       dec             di
+       je              L$32
+       add             si,4
+       mov             ax,word ptr [si]
+       mov             cx,word ptr 2[si]
+       mov             dx,word ptr cs:MX_CLIPY2
+       cmp             ax,dx
+       jg              L$31
+       cmp             cx,dx
+       jle             L$30
+       mov             word ptr 2[si],dx
+       mov             bx,cx
+       sub             bx,dx
+       sub             cx,ax
+       jle             L$31
+       mov             cx,word ptr 2[si]
+L$30:
+       mov             dx,word ptr cs:MX_CLIPY1
+       cmp             cx,dx
+       jl              L$31
+       sub             cx,ax
+       jle             L$31
+       cmp             ax,dx
+       jge             L$29
+       mov             word ptr [si],dx
+       sub             dx,ax
+       cmp             cx,dx
+       ja              L$29
+L$31:
+       mov             word ptr [si],0ffffH
+       jmp             L$29
+L$32:
+       mov             es,word ptr cs:MX_VIDEOSEGMENT
+       mov             si,word ptr -4[bp]
+       mov             cl,byte ptr -16H[bp]
+       and             cl,3
+       mov             al,11H
+       shl             al,cl
+       mov             byte ptr -2[bp],al
+       shr             word ptr -16H[bp],1
+       shr             word ptr -16H[bp],1
+L$33:
+       mov             ax,word ptr [si]
+       test            ax,ax
+       js              L$35
+       mov             cx,word ptr 2[si]
+       sub             cx,ax
+       jle             L$35
+       mul             word ptr cs:MX_BYTESPERLINE
+       add             ax,word ptr -16H[bp]
+       mov             di,ax
+       mov             ah,byte ptr -2[bp]
+       mov             dx,3c4H
+       mov             al,2
+       out             dx,ax
+       mov             ax,word ptr 6[bp]
+       mov             dx,word ptr cs:MX_BYTESPERLINE
+       shr             cx,1
+       jae             L$34
+       mov             byte ptr es:[di],al
+       add             di,dx
+       jcxz            L$35
+L$34:
+       mov             byte ptr es:[di],al
+       add             di,dx
+       mov             byte ptr es:[di],al
+       add             di,dx
+       dec             cx
+       jne             L$34
+L$35:
+       rol             byte ptr -2[bp],1
+       adc             word ptr -16H[bp],0
+       add             si,4
+       dec             word ptr -8[bp]
+       jne             L$33
+L$36:
+       xor             ax,ax
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0cH
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxpg.asm b/16/xw__/mxpg.asm
new file mode 100755 (executable)
index 0000000..7318f07
--- /dev/null
@@ -0,0 +1,458 @@
+.387
+               PUBLIC  MXGOURAUDPOLY
+               EXTRN   MX_BYTESPERLINE:BYTE
+               EXTRN   MX_CLIPX1:BYTE
+               EXTRN   MX_CLIPX2:BYTE
+               EXTRN   MX_CLIPY1:BYTE
+               EXTRN   MX_CLIPY2:BYTE
+               EXTRN   MX_CODESEGMENT:BYTE
+               EXTRN   MX_SCANBUFFER:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+       mov             cx,word ptr [si]
+       sub             cx,word ptr [bx]
+       jg              L$2
+       ret
+L$2:
+       push            bp
+       push            di
+       push            cx
+       push            ax
+       push            dx
+       mov             ax,word ptr 2[si]
+       mov             bx,word ptr 2[bx]
+       sub             ax,bx
+       jg              L$4
+       jl              L$6
+       mov             ax,bx
+L$3:
+       mov             word ptr es:[di],ax
+       add             di,8
+       dec             cx
+       jne             L$3
+       jmp             L$8
+L$4:
+       cwd
+       div             cx
+       mov             bp,ax
+       xor             ax,ax
+       div             cx
+       xchg            ax,bx
+       mov             dx,8000H
+L$5:
+       mov             word ptr es:[di],ax
+       add             di,8
+       add             dx,bx
+       adc             ax,bp
+       dec             cx
+       jne             L$5
+       jmp             L$8
+L$6:
+       neg             ax
+       cwd
+       div             cx
+       mov             bp,ax
+       xor             ax,ax
+       div             cx
+       xchg            ax,bx
+       mov             dx,8000H
+L$7:
+       mov             word ptr es:[di],ax
+       add             di,8
+       sub             dx,bx
+       sbb             ax,bp
+       dec             cx
+       jne             L$7
+L$8:
+       pop             bx
+       pop             ax
+       pop             cx
+       pop             di
+       sub             ax,bx
+       jg              L$10
+       jl              L$12
+       mov             ah,bl
+       mov             al,80H
+L$9:
+       mov             word ptr es:2[di],ax
+       add             di,8
+       dec             cx
+       jne             L$9
+       jmp             L$14
+L$10:
+       cwd
+       div             cx
+       mov             bp,ax
+       xor             ax,ax
+       div             cx
+       xchg            ax,bx
+       mov             dx,8000H
+L$11:
+       mov             byte ptr es:3[di],al
+       mov             byte ptr es:2[di],dh
+       add             di,8
+       add             dx,bx
+       adc             ax,bp
+       dec             cx
+       jne             L$11
+       jmp             L$14
+L$12:
+       neg             ax
+       cwd
+       div             cx
+       mov             bp,ax
+       xor             ax,ax
+       div             cx
+       xchg            ax,bx
+       mov             dx,8000H
+L$13:
+       mov             byte ptr es:3[di],al
+       mov             byte ptr es:2[di],dh
+       add             di,8
+       sub             dx,bx
+       sbb             ax,bp
+       dec             cx
+       jne             L$13
+L$14:
+       pop             bp
+       ret
+L$15:
+       mov             ax,word ptr 6[si]
+       mov             bx,word ptr 2[si]
+       cmp             ah,bh
+       jg              L$17
+       jl              L$19
+       add             ax,dx
+       mov             dx,word ptr cs:MX_BYTESPERLINE
+L$16:
+       mov             byte ptr es:[di],ah
+       add             di,dx
+       dec             cx
+       jne             L$16
+       ret
+L$17:
+       push            bp
+       push            si
+       mov             si,bx
+       add             si,dx
+       sub             ax,bx
+       xor             dx,dx
+       div             cx
+       mov             bp,ax
+       xor             ax,ax
+       div             cx
+       mov             bx,ax
+       mov             dx,8000H
+       mov             ax,word ptr cs:MX_BYTESPERLINE
+       xchg            ax,si
+L$18:
+       mov             byte ptr es:[di],ah
+       add             dx,bx
+       adc             ax,bp
+       add             di,si
+       dec             cx
+       jne             L$18
+       pop             si
+       pop             bp
+       ret
+L$19:
+       push            bp
+       push            si
+       mov             si,bx
+       add             si,dx
+       sub             ax,bx
+       neg             ax
+       xor             dx,dx
+       div             cx
+       mov             bp,ax
+       xor             ax,ax
+       div             cx
+       mov             bx,ax
+       mov             dx,8000H
+       mov             ax,word ptr cs:MX_BYTESPERLINE
+       xchg            ax,si
+L$20:
+       mov             byte ptr es:[di],ah
+       sub             dx,bx
+       sbb             ax,bp
+       add             di,si
+       dec             cx
+       jne             L$20
+       pop             si
+       pop             bp
+       ret
+MXGOURAUDPOLY:
+       push            bp
+       mov             bp,sp
+       sub             sp,1eH
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             cx,word ptr 14H[bp]
+       cmp             cx,3
+       jae             L$21
+       jmp             near ptr L$47
+L$21:
+       les             di,dword ptr 10H[bp]
+       lds             si,dword ptr 0cH[bp]
+       mov             word ptr -16H[bp],7fffH
+       mov             word ptr -1aH[bp],8000H
+       mov             word ptr -18H[bp],7fffH
+       mov             word ptr -1eH[bp],8000H
+       xor             dx,dx
+L$22:
+       mov             bx,word ptr es:[di]
+       shl             bx,1
+       shl             bx,1
+       add             bx,si
+       mov             ax,word ptr [bx]
+       cmp             ax,word ptr -16H[bp]
+       jge             L$23
+       mov             word ptr -16H[bp],ax
+       mov             word ptr -0eH[bp],dx
+       mov             word ptr -10H[bp],dx
+L$23:
+       cmp             ax,word ptr -1aH[bp]
+       jle             L$24
+       mov             word ptr -1aH[bp],ax
+       mov             word ptr -12H[bp],dx
+L$24:
+       mov             ax,word ptr 2[bx]
+       cmp             ax,word ptr -18H[bp]
+       jge             L$25
+       mov             word ptr -18H[bp],ax
+L$25:
+       cmp             ax,word ptr -1eH[bp]
+       jle             L$26
+       mov             word ptr -1eH[bp],ax
+L$26:
+       inc             di
+       inc             di
+       inc             dx
+       inc             dx
+       dec             cx
+       jne             L$22
+       mov             ax,word ptr -1aH[bp]
+       cmp             ax,word ptr cs:MX_CLIPX1
+       jge             L$27
+       jmp             near ptr L$47
+L$27:
+       mov             bx,word ptr -16H[bp]
+       cmp             bx,word ptr cs:MX_CLIPX2
+       jle             L$28
+       jmp             near ptr L$47
+L$28:
+       sub             ax,bx
+       jg              L$29
+       jmp             near ptr L$47
+L$29:
+       mov             ax,word ptr -1eH[bp]
+       cmp             ax,word ptr cs:MX_CLIPY1
+       jge             L$30
+       jmp             near ptr L$47
+L$30:
+       mov             bx,word ptr -18H[bp]
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jle             L$31
+       jmp             near ptr L$47
+L$31:
+       sub             ax,bx
+       jg              L$32
+       jmp             near ptr L$47
+L$32:
+       dec             word ptr 14H[bp]
+       shl             word ptr 14H[bp],1
+       mov             es,word ptr cs:MX_CODESEGMENT
+       mov             ax,offset MX_TEXT:MX_SCANBUFFER
+       mov             word ptr -4[bp],ax
+       mov             si,word ptr -0eH[bp]
+L$33:
+       lds             bx,dword ptr 10H[bp]
+       mov             di,word ptr [bx+si]
+       dec             si
+       dec             si
+       test            si,si
+       jge             L$34
+       mov             si,word ptr 14H[bp]
+L$34:
+       mov             word ptr -0eH[bp],si
+       mov             si,word ptr [bx+si]
+       lds             bx,dword ptr 8[bp]
+       shl             di,1
+       shl             si,1
+       mov             ax,word ptr [bx+si]
+       mov             dx,word ptr [bx+di]
+       lds             bx,dword ptr 0cH[bp]
+       shl             si,1
+       shl             di,1
+       add             si,bx
+       add             bx,di
+       mov             di,word ptr -4[bp]
+       call            near ptr L$1
+       mov             word ptr -4[bp],di
+       mov             si,word ptr -0eH[bp]
+       cmp             si,word ptr -12H[bp]
+       jne             L$33
+       mov             ax,offset MX_TEXT:MX_SCANBUFFER+4
+       mov             word ptr -6[bp],ax
+       mov             si,word ptr -10H[bp]
+L$35:
+       lds             bx,dword ptr 10H[bp]
+       mov             di,word ptr [bx+si]
+       inc             si
+       inc             si
+       cmp             si,word ptr 14H[bp]
+       jbe             L$36
+       xor             si,si
+L$36:
+       mov             word ptr -10H[bp],si
+       mov             si,word ptr [bx+si]
+       lds             bx,dword ptr 8[bp]
+       shl             di,1
+       shl             si,1
+       mov             ax,word ptr [bx+si]
+       mov             dx,word ptr [bx+di]
+       lds             bx,dword ptr 0cH[bp]
+       shl             si,1
+       shl             di,1
+       add             si,bx
+       add             bx,di
+       mov             di,word ptr -6[bp]
+       call            near ptr L$1
+       mov             word ptr -6[bp],di
+       mov             si,word ptr -10H[bp]
+       cmp             si,word ptr -12H[bp]
+       jne             L$35
+       mov             si,offset MX_TEXT:MX_SCANBUFFER
+       mov             ax,word ptr -16H[bp]
+       mov             cx,word ptr -1aH[bp]
+       sub             cx,ax
+       mov             bx,word ptr cs:MX_CLIPX1
+       sub             bx,ax
+       jle             L$37
+       sub             cx,bx
+       add             ax,bx
+       mov             word ptr -16H[bp],ax
+       shl             bx,1
+       shl             bx,1
+       shl             bx,1
+       add             si,bx
+L$37:
+       mov             bx,ax
+       add             bx,cx
+       sub             bx,word ptr cs:MX_CLIPX2
+       jle             L$38
+       sub             cx,bx
+L$38:
+       test            cx,cx
+       jg              L$39
+       jmp             near ptr L$47
+L$39:
+       mov             word ptr -8[bp],cx
+       mov             word ptr -4[bp],si
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       mov             ax,word ptr -18H[bp]
+       cmp             ax,word ptr cs:MX_CLIPY1
+       jl              L$40
+       mov             ax,word ptr -1eH[bp]
+       cmp             ax,word ptr cs:MX_CLIPY2
+       jg              L$40
+       jmp             L$44
+L$40:
+       mov             di,cx
+       inc             di
+       sub             si,8
+L$41:
+       dec             di
+       je              L$44
+       add             si,8
+       mov             ax,word ptr [si]
+       mov             cx,word ptr 4[si]
+       mov             dx,word ptr cs:MX_CLIPY2
+       cmp             ax,dx
+       jg              L$43
+       cmp             cx,dx
+       jle             L$42
+       mov             word ptr 4[si],dx
+       mov             bx,cx
+       sub             bx,dx
+       sub             cx,ax
+       jle             L$43
+       mov             ax,word ptr 2[si]
+       sub             ax,word ptr 6[si]
+       imul            bx
+       idiv            cx
+       add             word ptr 6[si],ax
+       mov             ax,word ptr [si]
+       mov             cx,word ptr 4[si]
+L$42:
+       mov             dx,word ptr cs:MX_CLIPY1
+       cmp             cx,dx
+       jl              L$43
+       sub             cx,ax
+       jle             L$43
+       cmp             ax,dx
+       jge             L$41
+       mov             word ptr [si],dx
+       sub             dx,ax
+       cmp             cx,dx
+       jbe             L$43
+       mov             ax,word ptr 6[si]
+       sub             ax,word ptr 2[si]
+       imul            dx
+       idiv            cx
+       add             word ptr 2[si],ax
+       jmp             L$41
+L$43:
+       mov             word ptr [si],0ffffH
+       jmp             L$41
+L$44:
+       mov             es,word ptr cs:MX_VIDEOSEGMENT
+       mov             si,word ptr -4[bp]
+       mov             cl,byte ptr -16H[bp]
+       and             cl,3
+       mov             al,11H
+       shl             al,cl
+       mov             byte ptr -2[bp],al
+       shr             word ptr -16H[bp],1
+       shr             word ptr -16H[bp],1
+       mov             ax,word ptr 6[bp]
+       mov             ah,al
+       xor             al,al
+       mov             word ptr 6[bp],ax
+L$45:
+       mov             ax,word ptr [si]
+       test            ax,ax
+       js              L$46
+       mov             cx,word ptr 4[si]
+       sub             cx,ax
+       jle             L$46
+       mul             word ptr cs:MX_BYTESPERLINE
+       add             ax,word ptr -16H[bp]
+       mov             di,ax
+       mov             ah,byte ptr -2[bp]
+       mov             al,2
+       mov             dx,3c4H
+       out             dx,ax
+       mov             dx,word ptr 6[bp]
+       call            near ptr L$15
+L$46:
+       rol             byte ptr -2[bp],1
+       adc             word ptr -16H[bp],0
+       add             si,8
+       dec             word ptr -8[bp]
+       jne             L$45
+L$47:
+       xor             ax,ax
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            10H
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxpi.asm b/16/xw__/mxpi.asm
new file mode 100755 (executable)
index 0000000..3484a58
--- /dev/null
@@ -0,0 +1,219 @@
+.387
+               PUBLIC  MXPUTIMAGE
+               EXTRN   SUBCLIPIMAGE:BYTE
+               EXTRN   MX_BYTESPERLINE:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+    DW offset L$2
+    DW offset L$6
+    DW offset L$10
+    DW offset L$14
+    DW offset L$18
+    DW offset L$20
+L$2:
+       shr             cx,1
+       jb              L$5
+L$3:
+       movsb
+       add             si,3
+       movsb
+       add             si,3
+       dec             cx
+       jne             L$3
+L$4:
+       ret
+L$5:
+       movsb
+       add             si,3
+       jcxz            L$4
+       jmp             L$3
+L$6:
+       shr             cx,1
+       jb              L$9
+L$7:
+       mov             al,byte ptr [si]
+       mov             ah,byte ptr 4[si]
+       and             word ptr es:[di],ax
+       inc             di
+       inc             di
+       add             si,8
+       dec             cx
+       jne             L$7
+L$8:
+       ret
+L$9:
+       lodsb
+       and             byte ptr es:[di],al
+       inc             di
+       add             si,3
+       jcxz            L$8
+       jmp             L$7
+L$10:
+       shr             cx,1
+       jb              L$13
+L$11:
+       mov             al,byte ptr [si]
+       mov             ah,byte ptr 4[si]
+       or              word ptr es:[di],ax
+       inc             di
+       inc             di
+       add             si,8
+       dec             cx
+       jne             L$11
+L$12:
+       ret
+L$13:
+       lodsb
+       or              byte ptr es:[di],al
+       inc             di
+       add             si,3
+       jcxz            L$12
+       jmp             L$11
+L$14:
+       shr             cx,1
+       jb              L$17
+L$15:
+       mov             al,byte ptr [si]
+       mov             ah,byte ptr 4[si]
+       xor             word ptr es:[di],ax
+       inc             di
+       inc             di
+       add             si,8
+       dec             cx
+       jne             L$15
+L$16:
+       ret
+L$17:
+       lodsb
+       xor             byte ptr es:[di],al
+       inc             di
+       add             si,3
+       jcxz            L$16
+       jmp             L$15
+L$18:
+       mov             al,byte ptr [si]
+       cmp             al,ah
+       je              L$19
+       mov             byte ptr es:[di],al
+L$19:
+       inc             di
+       add             si,4
+       dec             cx
+       jne             L$18
+       ret
+L$20:
+       mov             al,byte ptr [si]
+       add             byte ptr es:[di],al
+       inc             di
+       add             si,4
+       dec             cx
+       jne             L$20
+       ret
+MXPUTIMAGE:
+       push            bp
+       mov             bp,sp
+       sub             sp,14H
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             bx,word ptr 0eH[bp]
+       mov             ax,word ptr 0cH[bp]
+       mov             cx,word ptr 0aH[bp]
+       mov             dx,word ptr 8[bp]
+       call            near ptr MX_TEXT:SUBCLIPIMAGE
+       jae             L$21
+       jmp             near ptr L$26
+L$21:
+       mov             word ptr 8[bp],dx
+       add             word ptr 10H[bp],si
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             di,bx
+       shr             di,1
+       shr             di,1
+       add             di,ax
+       mov             word ptr -0aH[bp],di
+       mov             es,word ptr cs:MX_VIDEOSEGMENT
+       and             bl,3
+       mov             byte ptr -10H[bp],bl
+       mov             bx,cx
+       shr             bx,1
+       shr             bx,1
+       and             cl,3
+       mov             al,8
+       shr             al,cl
+       mov             si,6
+L$22:
+       mov             word ptr -8[bp+si],bx
+       shr             al,1
+       adc             bx,0
+       dec             si
+       dec             si
+       jge             L$22
+       mov             cl,byte ptr -10H[bp]
+       mov             al,11H
+       shl             al,cl
+       mov             byte ptr -14H[bp],al
+       mov             bx,word ptr 6[bp]
+       mov             byte ptr -12H[bp],bh
+       xor             bh,bh
+       cmp             bl,5
+       jbe             L$23
+       xor             bl,bl
+L$23:
+       shl             bx,1
+       mov             ax,word ptr cs:L$1[bx]
+       mov             word ptr -0cH[bp],ax
+       cld
+       mov             byte ptr -0eH[bp],4
+       lea             bx,-8[bp]
+       mov             ds,word ptr 12H[bp]
+L$24:
+       cmp             word ptr ss:[bx],0
+       je              L$26
+       mov             si,word ptr 10H[bp]
+       mov             ah,byte ptr -14H[bp]
+       and             ah,0fH
+       mov             al,2
+       mov             dx,3c4H
+       out             dx,ax
+       mov             ah,byte ptr -10H[bp]
+       and             ah,3
+       mov             al,4
+       mov             dx,3ceH
+       out             dx,ax
+       mov             dx,word ptr 8[bp]
+       mov             di,word ptr -0aH[bp]
+L$25:
+       push            si
+       push            di
+       mov             cx,word ptr ss:[bx]
+       mov             ah,byte ptr -12H[bp]
+       call            word ptr -0cH[bp]
+       pop             di
+       pop             si
+       add             si,word ptr 0aH[bp]
+       add             di,word ptr cs:MX_BYTESPERLINE
+       dec             dx
+       jne             L$25
+       inc             bx
+       inc             bx
+       inc             byte ptr -10H[bp]
+       rol             byte ptr -14H[bp],1
+       adc             word ptr -0aH[bp],0
+       inc             word ptr 10H[bp]
+       dec             byte ptr -0eH[bp]
+       jne             L$24
+L$26:
+       xor             ax,ax
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0eH
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxpn.asm b/16/xw__/mxpn.asm
new file mode 100755 (executable)
index 0000000..7b60449
--- /dev/null
@@ -0,0 +1,35 @@
+.387
+               PUBLIC  MXPAN
+               EXTRN   MX_BYTESPERLINE:BYTE
+               EXTRN   MXWAITDISPLAY:BYTE
+               EXTRN   MXSTARTADDRESS:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXPAN:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       mov             ax,word ptr 6[bp]
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             dx,word ptr 8[bp]
+       shr             dx,1
+       shr             dx,1
+       add             ax,dx
+       push            ax
+       call            far ptr MXWAITDISPLAY
+       call            far ptr MXSTARTADDRESS
+       mov             dx,3daH
+       in              al,dx
+       mov             dx,3c0H
+       mov             al,33H
+       out             dx,al
+       mov             al,byte ptr 8[bp]
+       and             al,3
+       shl             al,1
+       out             dx,al
+       xor             ax,ax
+       mov             sp,bp
+       pop             bp
+       retf            4
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxpp.asm b/16/xw__/mxpp.asm
new file mode 100755 (executable)
index 0000000..d15387e
--- /dev/null
@@ -0,0 +1,85 @@
+.387
+               PUBLIC  MXGETPIXEL
+               PUBLIC  MXPUTPIXEL
+               EXTRN   MX_CLIPX1:BYTE
+               EXTRN   MX_CLIPX2:BYTE
+               EXTRN   MX_CLIPY1:BYTE
+               EXTRN   MX_CLIPY2:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+               EXTRN   MX_BYTESPERLINE:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXGETPIXEL:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       xor             ax,ax
+       mov             si,word ptr 8[bp]
+       cmp             si,word ptr cs:MX_CLIPX1
+       jl              L$1
+       cmp             si,word ptr cs:MX_CLIPX2
+       jg              L$1
+       mov             bx,word ptr 6[bp]
+       cmp             bx,word ptr cs:MX_CLIPY1
+       jl              L$1
+       cmp             bx,word ptr cs:MX_CLIPY2
+       jg              L$1
+       mov             al,4
+       mov             ah,byte ptr 8[bp]
+       and             ah,3
+       mov             dx,3ceH
+       out             dx,ax
+       mov             ds,word ptr cs:MX_VIDEOSEGMENT
+       mov             ax,bx
+       mul             word ptr cs:MX_BYTESPERLINE
+       shr             si,1
+       shr             si,1
+       add             si,ax
+       mov             al,byte ptr [si]
+       xor             ah,ah
+L$1:
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            4
+MXPUTPIXEL:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       mov             si,word ptr 0aH[bp]
+       cmp             si,word ptr cs:MX_CLIPX1
+       jl              L$2
+       cmp             si,word ptr cs:MX_CLIPX2
+       jg              L$2
+       mov             ax,word ptr 8[bp]
+       cmp             ax,word ptr cs:MX_CLIPY1
+       jl              L$2
+       cmp             ax,word ptr cs:MX_CLIPY2
+       jg              L$2
+       mov             ds,word ptr cs:MX_VIDEOSEGMENT
+       mul             word ptr cs:MX_BYTESPERLINE
+       shr             si,1
+       shr             si,1
+       add             si,ax
+       mov             cl,byte ptr 0aH[bp]
+       and             cl,3
+       mov             ax,102H
+       shl             ah,cl
+       mov             dx,3c4H
+       out             dx,ax
+       mov             al,byte ptr 6[bp]
+       mov             byte ptr [si],al
+L$2:
+       xor             ax,ax
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            6
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxra.asm b/16/xw__/mxra.asm
new file mode 100755 (executable)
index 0000000..539f4ee
--- /dev/null
@@ -0,0 +1,18 @@
+.387
+               PUBLIC  MXROWADDRESS
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXROWADDRESS:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       mov             dx,3d4H
+       mov             al,13H
+       mov             ah,byte ptr 6[bp]
+       out             dx,ax
+       xor             ax,ax
+       mov             sp,bp
+       pop             bp
+       retf            2
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxrp.asm b/16/xw__/mxrp.asm
new file mode 100755 (executable)
index 0000000..be508c5
--- /dev/null
@@ -0,0 +1,73 @@
+.387
+               PUBLIC  MXROTATEPALETTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXROTATEPALETTE:
+       push            bp
+       mov             bp,sp
+       sub             sp,300H
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             bx,word ptr 8[bp]
+       add             bx,bx
+       add             bx,word ptr 8[bp]
+       lds             si,dword ptr 0aH[bp]
+       push            ss
+       pop             es
+       lea             di,-300H[bp]
+       cld
+       mov             ax,word ptr 6[bp]
+       mov             dx,ax
+       test            ax,ax
+       je              L$2
+       jl              L$1
+       add             ax,ax
+       add             dx,ax
+       sub             bx,dx
+       add             si,bx
+       push            si
+       mov             cx,dx
+       rep movsb
+       mov             es,word ptr 0cH[bp]
+       mov             di,si
+       dec             di
+       pop             si
+       dec             si
+       mov             cx,bx
+       std
+       rep movsb
+       push            ss
+       pop             ds
+       lea             si,-300H[bp]
+       les             di,dword ptr 0aH[bp]
+       mov             cx,dx
+       cld
+       rep movsb
+       jmp             L$2
+L$1:
+       add             ax,ax
+       add             dx,ax
+       neg             dx
+       sub             bx,dx
+       mov             cx,dx
+       rep movsb
+       les             di,dword ptr 0aH[bp]
+       mov             cx,bx
+       rep movsb
+       push            ss
+       pop             ds
+       lea             si,-300H[bp]
+       mov             cx,dx
+       rep movsb
+L$2:
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxsa.asm b/16/xw__/mxsa.asm
new file mode 100755 (executable)
index 0000000..8504fa9
--- /dev/null
@@ -0,0 +1,23 @@
+.387
+               PUBLIC  MXSTARTADDRESS
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXSTARTADDRESS:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       mov             bx,word ptr 6[bp]
+       mov             dx,3d4H
+       mov             al,0cH
+       mov             ah,bh
+       cli
+       out             dx,ax
+       mov             al,0dH
+       mov             ah,bl
+       out             dx,ax
+       sti
+       mov             sp,bp
+       pop             bp
+       retf            2
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxsc.asm b/16/xw__/mxsc.asm
new file mode 100755 (executable)
index 0000000..e65d846
--- /dev/null
@@ -0,0 +1,27 @@
+.387
+               PUBLIC  MXSETCOLOR
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXSETCOLOR:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       mov             ax,word ptr 0cH[bp]
+       mov             dx,3c8H
+       out             dx,al
+       inc             dx
+       mov             al,byte ptr 0aH[bp]
+       out             dx,al
+       mov             al,byte ptr 8[bp]
+       out             dx,al
+       mov             al,byte ptr 6[bp]
+       out             dx,al
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxsi.asm b/16/xw__/mxsi.asm
new file mode 100755 (executable)
index 0000000..a9179a8
--- /dev/null
@@ -0,0 +1,221 @@
+.387
+               PUBLIC  MXSTRETCHIMAGE
+               EXTRN   SUBCLIPBOX:BYTE
+               EXTRN   MX_BYTESPERLINE:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+    DW offset L$8
+    DW offset L$10
+    DW offset L$12
+    DW offset L$14
+    DW offset L$16
+    DW offset L$19
+MXSTRETCHIMAGE:
+       push            bp
+       mov             bp,sp
+       sub             sp,14H
+       push            ds
+       push            si
+       push            es
+       push            di
+       xor             dx,dx
+       mov             ax,word ptr 0eH[bp]
+       mov             bx,word ptr 0aH[bp]
+       div             bx
+       mov             word ptr -0aH[bp],ax
+       xor             ax,ax
+       div             bx
+       mov             word ptr -0cH[bp],ax
+       xor             dx,dx
+       mov             ax,word ptr 0cH[bp]
+       mov             bx,word ptr 8[bp]
+       div             bx
+       mov             word ptr -0eH[bp],ax
+       xor             ax,ax
+       div             bx
+       mov             word ptr -10H[bp],ax
+       mov             bx,word ptr 12H[bp]
+       mov             ax,word ptr 10H[bp]
+       mov             cx,word ptr 0aH[bp]
+       mov             dx,word ptr 8[bp]
+       call            near ptr MX_TEXT:SUBCLIPBOX
+       jae             L$2
+       jmp             near ptr L$7
+L$2:
+       mov             word ptr 0aH[bp],cx
+       mov             word ptr 8[bp],dx
+       sub             word ptr 12H[bp],bx
+       sub             word ptr 10H[bp],ax
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             di,bx
+       shr             di,1
+       shr             di,1
+       add             di,ax
+       mov             word ptr -2[bp],di
+       mov             es,word ptr cs:MX_VIDEOSEGMENT
+       and             bl,3
+       mov             byte ptr -6[bp],bl
+       mov             cl,bl
+       mov             al,11H
+       shl             al,cl
+       mov             byte ptr -14H[bp],al
+       mov             ax,word ptr 10H[bp]
+       test            ax,ax
+       je              L$3
+       mov             bx,ax
+       mul             word ptr -10H[bp]
+       mov             cx,dx
+       mov             ax,bx
+       mul             word ptr -0eH[bp]
+       add             ax,cx
+       mul             word ptr 0eH[bp]
+       add             word ptr 14H[bp],ax
+L$3:
+       mov             ax,word ptr 12H[bp]
+       test            ax,ax
+       je              L$4
+       mov             bx,ax
+       mul             word ptr -0cH[bp]
+       mov             cx,dx
+       mov             ax,bx
+       mul             word ptr -0aH[bp]
+       add             ax,cx
+       add             word ptr 14H[bp],ax
+L$4:
+       mov             ax,word ptr -0eH[bp]
+       mul             word ptr 0eH[bp]
+       mov             word ptr -0eH[bp],ax
+       mov             bx,word ptr 6[bp]
+       mov             byte ptr -8[bp],bh
+       xor             bh,bh
+       cmp             bl,5
+       jbe             L$5
+       xor             bl,bl
+L$5:
+       shl             bx,1
+       mov             ax,word ptr cs:L$1[bx]
+       mov             word ptr -4[bp],ax
+       mov             ds,word ptr 16H[bp]
+       xor             ax,ax
+       mov             word ptr -12H[bp],ax
+L$6:
+       mov             si,word ptr 14H[bp]
+       mov             ah,byte ptr -14H[bp]
+       and             ah,0fH
+       mov             al,2
+       mov             dx,3c4H
+       out             dx,ax
+       mov             ah,byte ptr -6[bp]
+       and             ah,3
+       mov             al,4
+       mov             dx,3ceH
+       out             dx,ax
+       mov             cx,word ptr 8[bp]
+       mov             di,word ptr -2[bp]
+       mov             ah,byte ptr -8[bp]
+       xor             bx,bx
+       mov             dx,word ptr cs:MX_BYTESPERLINE
+       call            word ptr -4[bp]
+       inc             byte ptr -6[bp]
+       rol             byte ptr -14H[bp],1
+       adc             word ptr -2[bp],0
+       mov             dx,word ptr -0cH[bp]
+       mov             ax,word ptr -0aH[bp]
+       add             word ptr -12H[bp],dx
+       adc             word ptr 14H[bp],ax
+       dec             word ptr 0aH[bp]
+       jne             L$6
+L$7:
+       xor             ax,ax
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            12H
+L$8:
+       mov             al,byte ptr [si]
+       mov             byte ptr es:[di],al
+       add             di,dx
+       dec             cx
+       je              L$9
+       add             si,word ptr -0eH[bp]
+       add             bx,word ptr -10H[bp]
+       jae             L$8
+       add             si,word ptr 0eH[bp]
+       jmp             L$8
+L$9:
+       ret
+L$10:
+       mov             al,byte ptr [si]
+       and             byte ptr es:[di],al
+       add             di,dx
+       dec             cx
+       je              L$11
+       add             si,word ptr -0eH[bp]
+       add             bx,word ptr -10H[bp]
+       jae             L$10
+       add             si,word ptr 0eH[bp]
+       jmp             L$10
+L$11:
+       ret
+L$12:
+       mov             al,byte ptr [si]
+       or              byte ptr es:[di],al
+       add             di,dx
+       dec             cx
+       je              L$13
+       add             si,word ptr -0eH[bp]
+       add             bx,word ptr -10H[bp]
+       jae             L$12
+       add             si,word ptr 0eH[bp]
+       jmp             L$12
+L$13:
+       ret
+L$14:
+       mov             al,byte ptr [si]
+       xor             byte ptr es:[di],al
+       add             di,dx
+       dec             cx
+       je              L$15
+       add             si,word ptr -0eH[bp]
+       add             bx,word ptr -10H[bp]
+       jae             L$14
+       add             si,word ptr 0eH[bp]
+       jmp             L$14
+L$15:
+       ret
+L$16:
+       mov             al,byte ptr [si]
+       cmp             al,ah
+       je              L$17
+       mov             byte ptr es:[di],al
+L$17:
+       add             di,dx
+       dec             cx
+       je              L$18
+       add             si,word ptr -0eH[bp]
+       add             bx,word ptr -10H[bp]
+       jae             L$16
+       add             si,word ptr 0eH[bp]
+       jmp             L$16
+L$18:
+       ret
+L$19:
+       mov             al,byte ptr [si]
+       add             byte ptr es:[di],al
+       add             di,dx
+       dec             cx
+       je              L$20
+       add             si,word ptr -0eH[bp]
+       add             bx,word ptr -10H[bp]
+       jae             L$19
+       add             si,word ptr 0eH[bp]
+       jmp             L$19
+L$20:
+       ret
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxsl.asm b/16/xw__/mxsl.asm
new file mode 100755 (executable)
index 0000000..2b25844
--- /dev/null
@@ -0,0 +1,37 @@
+.387
+               PUBLIC  MXSTARTLINE
+               EXTRN   MX_BYTESPERLINE:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXSTARTLINE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       mov             ax,word ptr 6[bp]
+       mul             word ptr cs:MX_BYTESPERLINE
+       xchg            ax,bx
+       mov             dx,3daH
+L$1:
+       in              al,dx
+       test            al,8
+       jne             L$1
+       mov             dx,3d4H
+       mov             al,0cH
+       mov             ah,bh
+       cli
+       out             dx,ax
+       mov             al,0dH
+       mov             ah,bl
+       out             dx,ax
+       sti
+       mov             dx,3daH
+L$2:
+       in              al,dx
+       test            al,8
+       je              L$2
+       xor             ax,ax
+       mov             sp,bp
+       pop             bp
+       retf            2
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxsm.asm b/16/xw__/mxsm.asm
new file mode 100755 (executable)
index 0000000..ccad79e
--- /dev/null
@@ -0,0 +1,450 @@
+.387
+               PUBLIC  MX_SCREENWIDTH
+               PUBLIC  MX_SCREENHEIGHT
+               PUBLIC  MX_BYTESPERLINE
+               PUBLIC  MXSETMODE
+               PUBLIC  MXCHANGEMODE
+               PUBLIC  MXGETASPECT
+               PUBLIC  MXGETSCREENSIZE
+               EXTRN   MX_CODESEGMENT:BYTE
+               EXTRN   MXSETSYSCLIPREGION:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MX_SCREENWIDTH:
+       add             byte ptr [bx+si],al
+MX_SCREENHEIGHT:
+       add             byte ptr [bx+si],al
+L$1:
+       add             byte ptr [bx+si],al
+L$2:
+       add             byte ptr [bx+si],al
+MX_BYTESPERLINE:
+       add             byte ptr [bx+si],al
+L$3:
+       or              word ptr 14H[bx+si],ax
+       add             byte ptr [bx],dl
+       jcxz            L$4
+L$4:
+    DB 0
+L$5:
+       or              word ptr 14H[bx+di],ax
+       add             byte ptr [bx],dl
+       jcxz            L$6
+L$6:
+    DB 0
+L$7:
+       add             byte ptr 1[bx],bl
+       dec             di
+       add             dl,byte ptr 3[bx+si]
+       add             byte ptr [si],54H
+       add             ax,1380H
+       sub             byte ptr [bx+si],al
+    DB 0
+L$8:
+       add             byte ptr 1[bp+di],ch
+       pop             cx
+       add             bl,byte ptr 3[bp+si]
+       mov             es,word ptr [si]
+       pop             si
+       add             ax,138aH
+       sub             ax,0
+       push            es
+       mov             di,1f07H
+       adc             byte ptr -7aefH[bp+di],al
+       adc             bl,byte ptr 15H[di]
+       arpl            word ptr ds:[0baH],dx
+    DB 0
+L$9:
+       push            es
+    DD ds:[7bfH]
+       pushf
+       adc             word ptr -70eeH[bp],cx
+       adc             ax,1696H
+       mov             cx,0
+L$10:
+       push            es
+       or              ax,3e07H
+       adc             dl,ch
+       adc             word ptr -20eeH[si],cx
+       adc             ax,16e7H
+       push            es
+       add             byte ptr [bx+si],al
+L$11:
+       add             byte ptr 1[si],dh
+       arpl            word ptr [bp+si],ax
+       add             dx,word ptr fs:6804H[bx]
+       add             ax,695H
+       xchg            byte ptr [bx],al
+       lock or         word ptr 0fH[bx+si],sp
+       xor             word ptr [bx+si],dx
+       pop             bx
+       adc             word ptr 5712H[di],cx
+       adc             si,word ptr [bp+si]
+       adc             al,0
+       adc             ax,1660H
+       adc             byte ptr [bx],0e3H
+       add             byte ptr [bx+si],al
+L$12:
+       arpl            word ptr ds:[500H],ax
+       add             byte ptr 1[bx+si],al
+       enter           1a00H,0
+    DW offset L$9
+    DW offset L$5
+       add             byte ptr [bx+si],al
+       xor             ax,word ptr [bp+di]
+L$13:
+       jcxz            L$14
+    DB 0
+L$14:
+       add             word ptr [bx+si],ax
+       inc             ax
+       add             ax,si
+       add             byte ptr [bp+si],bl
+       add             byte ptr [bp+si],bl
+    DW offset L$5
+       add             byte ptr [bx+si],al
+       xor             ax,word ptr [bp+di]
+L$15:
+       arpl            word ptr ds:[0a00H],ax
+       add             byte ptr 1[bx+si],al
+       nop
+       add             word ptr [bp+si],bx
+       add             byte ptr [bp+si],cl
+    DW offset L$3
+       add             byte ptr [bx+si],al
+       xor             ax,word ptr [bp+di]
+L$16:
+       jcxz            L$17
+    DB 0
+L$17:
+       add             al,byte ptr [bx+si]
+       inc             ax
+       add             ax,sp
+    DD L$18
+L$18:
+       add             byte ptr [bp+si],cl
+       add             byte ptr [bx+si],al
+       add             byte ptr [bp+di],dh
+    DB 3
+L$19:
+       sbb             ax,word ptr [eax]
+       adc             al,0
+       push            0c801H
+       add             byte ptr [bp+si],ch
+       add             byte ptr [bp+si],cl
+    DW offset L$5
+       add             byte ptr [bx+si],al
+       fadd            dword ptr [bp+si]
+L$20:
+       out             9,ax
+       add             byte ptr [bx+si],cl
+       add             byte ptr 1[bx+si],ch
+       lock add        byte ptr [bp+si],ch
+       add             byte ptr [bp+si],bl
+    DW offset L$5
+       add             byte ptr [bx+si],al
+       fadd            dword ptr [bp+si]
+L$21:
+       sbb             ax,word ptr [eax]
+       sub             byte ptr [bx+si],al
+       push            9001H
+       add             word ptr [bp+si],bp
+       add             byte ptr [bp+si],cl
+    DW offset L$3
+       add             byte ptr [bx+si],al
+       fadd            dword ptr [bp+si]
+L$22:
+       out             9,ax
+       add             byte ptr [bx+si],dl
+       add             byte ptr 1[bx+si],ch
+       loopnz          L$23
+    DW offset L$8
+L$23 equ $-1
+    DW offset L$10
+    DW offset L$3
+       add             byte ptr [bx+si],al
+       fadd            dword ptr [bp+si]
+L$24:
+       mov             word ptr ds:[0],ax
+       add             byte ptr [bx+si],al
+       inc             ax
+       add             word ptr 1a00H[bx],bp
+       add             byte ptr [bp+si],bh
+       add             byte ptr [bp+si],dl
+       add             byte ptr [bx+si],al
+       add             byte ptr [bp+di],dh
+    DB 3
+L$25:
+       mov             word ptr 0,ax
+       add             byte ptr [bx+si],al
+       inc             ax
+       add             word ptr 1a00H[bx],bp
+       add             byte ptr [bp+si],bh
+       add             byte ptr [bp+si],cl
+       add             byte ptr [bx+si],al
+       add             byte ptr [bp+di],dh
+    DB 3
+L$26:
+       cmpsw
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       push            0e001H
+       add             word ptr [bp+si],bp
+       add             byte ptr [bp+si],bh
+       add             byte ptr [bp+si],dl
+       add             byte ptr [bx+si],al
+       add             al,bl
+    DB 2
+L$27:
+       cmpsw
+       add             byte ptr [bx+si],al
+       add             byte ptr [bx+si],al
+       push            0e001H
+       add             word ptr [bp+si],bp
+       add             byte ptr [bp+si],bh
+       add             byte ptr [bp+si],cl
+       add             byte ptr [bx+si],al
+       add             al,bl
+    DB 2
+L$28:
+       out             1,ax
+       add             byte ptr [bp+si],al
+       add             byte ptr 5801H[bx+si],dl
+       add             ch,byte ptr [bp+si]
+       add             byte ptr [bx+si],al
+       pop             word ptr [bp+si]
+L$29:
+    DW offset L$24
+    DW offset L$12
+    DW offset L$13
+    DW offset L$25
+    DW offset L$15
+    DW offset L$16
+    DW offset L$26
+    DW offset L$19
+    DW offset L$20
+    DW offset L$27
+    DW offset L$21
+    DW offset L$22
+    DW offset L$28
+L$30:
+       mov             ax,3
+       int             10H
+       mov             word ptr MX_SCREENHEIGHT,0
+       mov             word ptr MX_BYTESPERLINE,0
+       ret
+MXSETMODE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       mov             si,word ptr 6[bp]
+       cmp             si,0dH
+       jbe             L$31
+       jmp             near ptr L$36
+L$31:
+       test            si,si
+       jne             L$32
+       call            near ptr L$30
+       jmp             near ptr L$36
+L$32:
+       dec             si
+       shl             si,1
+       mov             si,word ptr L$29[si]
+       cld
+       push            si
+       mov             ax,13H
+       int             10H
+       pop             si
+       mov             dx,3c4H
+       mov             ax,604H
+       out             dx,ax
+       mov             ax,100H
+       out             dx,ax
+       mov             dx,3c2H
+       lodsb
+       out             dx,al
+       mov             dx,3c4H
+       mov             ax,300H
+       out             dx,ax
+       mov             dx,3d4H
+       mov             al,11H
+       out             dx,al
+       inc             dx
+       in              al,dx
+       and             al,7fH
+       out             dx,al
+       lodsw
+       mov             word ptr L$1,ax
+       lodsw
+       mov             word ptr L$2,ax
+       lodsw
+       mov             word ptr MX_SCREENWIDTH,ax
+       shr             ax,1
+       shr             ax,1
+       mov             word ptr MX_BYTESPERLINE,ax
+       lodsw
+       mov             word ptr MX_SCREENHEIGHT,ax
+       mov             bx,si
+       mov             dx,3d4H
+L$33:
+       mov             si,word ptr [bx]
+       inc             bx
+       inc             bx
+       test            si,si
+       je              L$35
+L$34:
+       lodsw
+       test            ax,ax
+       je              L$33
+       out             dx,ax
+       jmp             L$34
+L$35:
+       push            word ptr MX_SCREENWIDTH
+       push            word ptr [bx]
+       push            cs
+       call            near ptr MX_TEXT:MXSETSYSCLIPREGION
+       mov             dx,3c4H
+       mov             ax,0f02H
+       out             dx,ax
+       mov             es,word ptr MX_TEXT:MX_VIDEOSEGMENT
+       xor             di,di
+       mov             cx,8000H
+       xor             ax,ax
+       rep stosw
+       mov             dx,3d4H
+       mov             al,11H
+       out             dx,al
+       inc             dx
+       in              al,dx
+       or              al,80H
+       out             dx,al
+L$36:
+       xor             ax,ax
+       mov             ax,word ptr MX_SCREENWIDTH
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            2
+MXCHANGEMODE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       mov             si,word ptr 6[bp]
+       cmp             si,0dH
+       ja              L$40
+       test            si,si
+       je              L$40
+       dec             si
+       shl             si,1
+       mov             si,word ptr L$29[si]
+       cld
+       mov             dx,3c4H
+       mov             ax,604H
+       out             dx,ax
+       mov             ax,100H
+       out             dx,ax
+       mov             dx,3c2H
+       lodsb
+       out             dx,al
+       mov             dx,3c4H
+       mov             ax,300H
+       out             dx,ax
+       mov             dx,3d4H
+       mov             al,11H
+       out             dx,al
+       inc             dx
+       in              al,dx
+       and             al,7fH
+       out             dx,al
+       lodsw
+       mov             word ptr L$1,ax
+       lodsw
+       mov             word ptr L$2,ax
+       lodsw
+       mov             word ptr MX_SCREENWIDTH,ax
+       lodsw
+       mov             word ptr MX_SCREENHEIGHT,ax
+       mov             bx,si
+       mov             dx,3d4H
+L$37:
+       mov             si,word ptr [bx]
+       inc             bx
+       inc             bx
+       test            si,si
+       je              L$39
+L$38:
+       lodsw
+       test            ax,ax
+       je              L$37
+       cmp             al,13H
+       je              L$38
+       out             dx,ax
+       jmp             L$38
+L$39:
+       mov             dx,3d4H
+       mov             al,11H
+       out             dx,al
+       inc             dx
+       in              al,dx
+       or              al,80H
+       out             dx,al
+L$40:
+       xor             ax,ax
+       mov             ax,word ptr MX_SCREENWIDTH
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            2
+MXGETASPECT:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       lds             si,dword ptr 0aH[bp]
+       mov             ax,word ptr cs:L$1
+       mov             word ptr [si],ax
+       lds             si,dword ptr 6[bp]
+       mov             ax,word ptr cs:L$2
+       mov             word ptr [si],ax
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+MXGETSCREENSIZE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       lds             si,dword ptr 0aH[bp]
+       mov             ax,word ptr cs:MX_SCREENWIDTH
+       mov             word ptr [si],ax
+       lds             si,dword ptr 6[bp]
+       mov             ax,word ptr cs:MX_SCREENHEIGHT
+       mov             word ptr [si],ax
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxsp.asm b/16/xw__/mxsp.asm
new file mode 100755 (executable)
index 0000000..7ed046f
--- /dev/null
@@ -0,0 +1,34 @@
+.387
+               PUBLIC  MXSETPALETTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXSETPALETTE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       lds             si,dword ptr 0aH[bp]
+       mov             cx,word ptr 6[bp]
+       mov             ax,word ptr 8[bp]
+       mov             dx,3c8H
+       out             dx,al
+       inc             dx
+       cld
+       cli
+L$1:
+       lodsb
+       out             dx,al
+       lodsb
+       out             dx,al
+       lodsb
+       out             dx,al
+       loop            L$1
+       sti
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxss.asm b/16/xw__/mxss.asm
new file mode 100755 (executable)
index 0000000..aba7db9
--- /dev/null
@@ -0,0 +1,45 @@
+.387
+               PUBLIC  MXSPLITSCREEN
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXSPLITSCREEN:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       mov             ax,word ptr 6[bp]
+       shl             ax,1
+       mov             bh,ah
+       mov             bl,ah
+       and             bx,201H
+       mov             cl,4
+       shl             bx,cl
+       shl             bh,1
+       mov             dx,3d4H
+       mov             ah,al
+       mov             al,18H
+       out             dx,ax
+       mov             al,7
+       out             dx,al
+       inc             dx
+       in              al,dx
+       dec             dx
+       mov             ah,al
+       and             ah,0efH
+       or              ah,bl
+       mov             al,7
+       out             dx,ax
+       mov             al,9
+       out             dx,al
+       inc             dx
+       in              al,dx
+       dec             dx
+       mov             ah,al
+       and             ah,0bfH
+       or              ah,bh
+       mov             al,9
+       out             dx,ax
+       mov             sp,bp
+       pop             bp
+       retf            2
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxtl.asm b/16/xw__/mxtl.asm
new file mode 100755 (executable)
index 0000000..e93aedf
--- /dev/null
@@ -0,0 +1,123 @@
+.387
+               PUBLIC  MXPUTTILE
+               PUBLIC  MXTRANSPUTTILE
+               EXTRN   MX_BYTESPERLINE:BYTE
+               EXTRN   MX_VIDEOSEGMENT:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXPUTTILE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             ax,word ptr 0aH[bp]
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             di,word ptr 0cH[bp]
+       shr             di,1
+       shr             di,1
+       add             di,ax
+       mov             es,word ptr cs:MX_VIDEOSEGMENT
+       lds             si,dword ptr 0eH[bp]
+       shr             word ptr 8[bp],1
+       shr             word ptr 8[bp],1
+       mov             cl,byte ptr 0cH[bp]
+       and             cl,3
+       mov             ah,11H
+       shl             ah,cl
+       mov             word ptr 0aH[bp],4
+       mov             bx,word ptr cs:MX_BYTESPERLINE
+       sub             bx,word ptr 8[bp]
+L$1:
+       mov             al,2
+       mov             dx,3c4H
+       out             dx,ax
+       mov             word ptr 0cH[bp],di
+       mov             dx,word ptr 6[bp]
+L$2:
+       mov             cx,word ptr 8[bp]
+       shr             cx,1
+       rep movsw
+       rcl             cx,1
+       rep movsb
+       add             di,bx
+       dec             dx
+       jne             L$2
+       mov             di,word ptr 0cH[bp]
+       rol             ah,1
+       adc             di,0
+       dec             word ptr 0aH[bp]
+       jne             L$1
+       xor             ax,ax
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0cH
+MXTRANSPUTTILE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       push            es
+       push            di
+       mov             ax,word ptr 0aH[bp]
+       mul             word ptr cs:MX_BYTESPERLINE
+       mov             di,word ptr 0cH[bp]
+       shr             di,1
+       shr             di,1
+       add             di,ax
+       mov             es,word ptr cs:MX_VIDEOSEGMENT
+       lds             si,dword ptr 0eH[bp]
+       shr             word ptr 8[bp],1
+       shr             word ptr 8[bp],1
+       mov             cl,byte ptr 0cH[bp]
+       and             cl,3
+       mov             ah,11H
+       shl             ah,cl
+       mov             word ptr 0aH[bp],4
+       mov             bx,word ptr cs:MX_BYTESPERLINE
+       sub             bx,word ptr 8[bp]
+L$3:
+       mov             al,2
+       mov             dx,3c4H
+       out             dx,ax
+       mov             word ptr 0cH[bp],di
+       mov             dx,word ptr 6[bp]
+L$4:
+       mov             cx,word ptr 8[bp]
+       jcxz            L$7
+L$5:
+       mov             al,byte ptr [si]
+       test            al,al
+       je              L$6
+       mov             byte ptr es:[di],al
+L$6:
+       inc             si
+       inc             di
+       dec             cx
+       jne             L$5
+L$7:
+       add             di,bx
+       dec             dx
+       jne             L$4
+       mov             di,word ptr 0cH[bp]
+       rol             ah,1
+       adc             di,0
+       dec             word ptr 0aH[bp]
+       jne             L$3
+       xor             ax,ax
+       pop             di
+       pop             es
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            0cH
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxvs.asm b/16/xw__/mxvs.asm
new file mode 100755 (executable)
index 0000000..feafb66
--- /dev/null
@@ -0,0 +1,69 @@
+.387
+               PUBLIC  MXSETVIRTUALSCREEN
+               PUBLIC  MXGETVIRTUALSCREEN
+               EXTRN   MX_CODESEGMENT:BYTE
+               EXTRN   MX_BYTESPERLINE:BYTE
+               EXTRN   MXROWADDRESS:BYTE
+               EXTRN   MXSETSYSCLIPREGION:BYTE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+L$1:
+       add             byte ptr [bx+si],al
+L$2:
+       add             byte ptr [bx+si],al
+MXSETVIRTUALSCREEN:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       mov             ds,word ptr cs:MX_CODESEGMENT
+       mov             ax,1
+       cmp             word ptr 8[bp],140H
+       jb              L$3
+       push            ax
+       mov             dx,4
+       xor             ax,ax
+       div             word ptr 8[bp]
+       cmp             word ptr 6[bp],ax
+       pop             ax
+       ja              L$3
+       mov             ax,word ptr 8[bp]
+       and             ax,0fff8H
+       mov             word ptr L$1,ax
+       shr             ax,1
+       shr             ax,1
+       mov             word ptr MX_TEXT:MX_BYTESPERLINE,ax
+       shr             ax,1
+       push            ax
+       call            far ptr MXROWADDRESS
+       mov             ax,word ptr 6[bp]
+       mov             word ptr L$2,ax
+       push            word ptr 8[bp]
+       push            word ptr 6[bp]
+       call            far ptr MXSETSYSCLIPREGION
+       xor             ax,ax
+L$3:
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            4
+MXGETVIRTUALSCREEN:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       push            ds
+       push            si
+       mov             ax,word ptr cs:L$1
+       lds             si,dword ptr 0aH[bp]
+       mov             word ptr [si],ax
+       mov             ax,word ptr cs:L$2
+       lds             si,dword ptr 6[bp]
+       mov             word ptr [si],ax
+       xor             ax,ax
+       pop             si
+       pop             ds
+       mov             sp,bp
+       pop             bp
+       retf            8
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxwd.asm b/16/xw__/mxwd.asm
new file mode 100755 (executable)
index 0000000..7f491f3
--- /dev/null
@@ -0,0 +1,13 @@
+.387
+               PUBLIC  MXWAITDISPLAY
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXWAITDISPLAY:
+       mov             dx,3daH
+L$1:
+       in              al,dx
+       test            al,8
+       jne             L$1
+       retf
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxwm.asm b/16/xw__/mxwm.asm
new file mode 100755 (executable)
index 0000000..271eeba
--- /dev/null
@@ -0,0 +1,19 @@
+.387
+               PUBLIC  MXWRITEMODE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXWRITEMODE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       mov             dx,3ceH
+       mov             ah,byte ptr 6[bp]
+       and             ah,3
+       or              ah,40H
+       mov             al,5
+       out             dx,ax
+       mov             sp,bp
+       pop             bp
+       retf            2
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxwp.asm b/16/xw__/mxwp.asm
new file mode 100755 (executable)
index 0000000..45e32f3
--- /dev/null
@@ -0,0 +1,31 @@
+.387
+               PUBLIC  MXWRITEPLANE
+               PUBLIC  MXREADPLANE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXWRITEPLANE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       mov             ah,byte ptr 6[bp]
+       and             ah,0fH
+       mov             al,2
+       mov             dx,3c4H
+       out             dx,ax
+       mov             sp,bp
+       pop             bp
+       retf            2
+MXREADPLANE:
+       push            bp
+       mov             bp,sp
+       sub             sp,0
+       mov             al,4
+       mov             ah,byte ptr 6[bp]
+       and             ah,3
+       mov             dx,3ceH
+       out             dx,ax
+       mov             sp,bp
+       pop             bp
+       retf            2
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/mxwr.asm b/16/xw__/mxwr.asm
new file mode 100755 (executable)
index 0000000..5fccb47
--- /dev/null
@@ -0,0 +1,13 @@
+.387
+               PUBLIC  MXWAITRETRACE
+MX_TEXT                SEGMENT PARA PUBLIC USE16 'CODE'
+               ASSUME CS:MX_TEXT, DS:DGROUP, SS:DGROUP
+MXWAITRETRACE:
+       mov             dx,3daH
+L$1:
+       in              al,dx
+       test            al,8
+       je              L$1
+       retf
+MX_TEXT                ENDS
+               END
diff --git a/16/xw__/readme.txt b/16/xw__/readme.txt
new file mode 100755 (executable)
index 0000000..306e8b9
--- /dev/null
@@ -0,0 +1,8 @@
+ModeX - A graphical library for DOS programs\r
+Copyright (c) 1993-1994 Alessandro Scotti\r
+http://www.ascotti.org/\r
+\r
+Please look at the above site in the "Art of..." and\r
+then in the "Old programs" section for more information.\r
+\r
+\r
diff --git a/16/xw__/xw.bat b/16/xw__/xw.bat
new file mode 100755 (executable)
index 0000000..1fd2439
--- /dev/null
@@ -0,0 +1,39 @@
+@echo off\r
+wdis -a MXBB.OBJ > mxbb.asm\r
+wdis -a MXCC.OBJ > mxcc.asm\r
+wdis -a MXCG.OBJ > mxcg.asm\r
+wdis -a MXCL.OBJ > mxcl.asm\r
+wdis -a MXCR.OBJ > mxcl.asm\r
+wdis -a MXFB.OBJ > mxfb.asm\r
+wdis -a MXFP.OBJ > mxfp.asm\r
+wdis -a MXGC.OBJ > mxgc.asm\r
+wdis -a MXGI.OBJ > mxgi.asm\r
+wdis -a MXGM.OBJ > mxgm.asm\r
+wdis -a MXGP.OBJ > mxgp.asm\r
+wdis -a MXGV.OBJ > mxgv.asm\r
+wdis -a MXHL.OBJ > mxhl.asm\r
+wdis -a MXIT.OBJ > mxit.asm\r
+wdis -a MXLL.OBJ > mxll.asm\r
+wdis -a MXLN.OBJ > mxln.asm\r
+wdis -a MXOT.OBJ > mxot.asm\r
+wdis -a MXPB.OBJ > mxpb.asm\r
+wdis -a MXPF.OBJ > mxpf.asm\r
+wdis -a MXPG.OBJ > mxpg.asm\r
+wdis -a MXPI.OBJ > mxpi.asm\r
+wdis -a MXPN.OBJ > mxpn.asm\r
+wdis -a MXPP.OBJ > mxpp.asm\r
+wdis -a MXRA.OBJ > mxra.asm\r
+wdis -a MXRP.OBJ > mxrp.asm\r
+wdis -a MXSA.OBJ > mxsa.asm\r
+wdis -a MXSC.OBJ > mxsc.asm\r
+wdis -a MXSI.OBJ > mxsi.asm\r
+wdis -a MXSL.OBJ > mxsl.asm\r
+wdis -a MXSM.OBJ > mxsm.asm\r
+wdis -a MXSP.OBJ > mxsp.asm\r
+wdis -a MXSS.OBJ > mxss.asm\r
+wdis -a MXTL.OBJ > mxtl.asm\r
+wdis -a MXVS.OBJ > mxvs.asm\r
+wdis -a MXWD.OBJ > mxwd.asm\r
+wdis -a MXWM.OBJ > mxwm.asm\r
+wdis -a MXWP.OBJ > mxwp.asm\r
+wdis -a MXWR.OBJ > mxwr.asm\r
diff --git a/awoo.sh b/awoo.sh
index 5073f2bf14d16907d07aa714921fc92afa322534..f5b766ec3c8874cb6404d68005d9e38b6e8d8a5e 100755 (executable)
--- a/awoo.sh
+++ b/awoo.sh
@@ -1,6 +1,12 @@
 #!/bin/bash
+if [ -z "$*" ]; then
+               pee="wwww"
+       else
+               pee="$*"
+fi
+##echo "$pee"
 git add .
-. ./boop.sh "$*"
+. ./boop.sh "$pee"
 cp -fp *.exe /var/www/
 scp -rp -P 26 *.exe 4ch.mooo.com:/var/www/16/
 #if [ -f "*.exe" ]
index 12a74beaa89c65432d15a945a513b52f8aaa10e3..fee866d459ea0db41a0293ec699420ee03b387b9 100755 (executable)
Binary files a/bakapi.exe and b/bakapi.exe differ
index 2e41b42300f0c9682879fb8699e320a79be7e876..beb8f6e23bf50c31b01a9d0d013e75948b0522f0 100755 (executable)
Binary files a/exmmtest.exe and b/exmmtest.exe differ
index c88212abf6af8315621abd78613afc60175f8178..f7f7ff4deca7d685618cf173f82597c8555d3d46 100755 (executable)
Binary files a/fmemtest.exe and b/fmemtest.exe differ
index 577a02f48eff05042a7423c322a9f57059a60f73..ed49d78ab4ec2e9c0176f5aa640d4a85dcc7ca9f 100755 (executable)
Binary files a/fontgfx.exe and b/fontgfx.exe differ
index c59b86a554e7326206db41e5dc13539591fe8c4c..882c4d8f93d5736f633507d0ff7a58b043764c14 100755 (executable)
Binary files a/fonttest.exe and b/fonttest.exe differ
index 09cb3893242693857946b66b1f6a34c677c05d9d..ed7e43c8c65fec6d352bd63d759e71422dab29bf 100755 (executable)
Binary files a/inputest.exe and b/inputest.exe differ
index 6c388c71f96fff09e1224c685f9f688ae62d342d..723216e76b4f3ca58b5321408974bfaf2840280c 100755 (executable)
--- a/makefile
+++ b/makefile
 # -0    8088/8086 class code generation
 # -s    disable stack overflow checking
 
+# -zk0u        translate kanji to unicode... wwww
+# -zk0 kanji support~
+# -zkl         current codepage
+
 #%.C
 #192x144
 #wwww will add these
@@ -42,9 +46,6 @@ OBJ=obj
 #!endif
 
 TARGET_OS = dos
-#-zk0u = translate kanji to unicode... wwww
-#-zk0 = kanji support~
-#-zkl = current codepage
 
 #EXMMTESTDIR=16$(DIRSEP)exmmtest$(DIRSEP)
 SRC=src$(DIRSEP)
@@ -53,19 +54,22 @@ JSMNLIB=$(SRCLIB)jsmn$(DIRSEP)
 NYANLIB=$(SRCLIB)nyan$(DIRSEP)
 #EXMMLIB=$(SRCLIB)exmm$(DIRSEP)
 MODEXLIB=$(SRCLIB)modex16$(DIRSEP)
+MODEXLIB_=$(SRCLIB)modex$(DIRSEP)
 VGMSNDLIB=$(SRCLIB)vgmsnd$(DIRSEP)
 DOSLIB=$(SRCLIB)doslib$(DIRSEP)
 WCPULIB=$(SRCLIB)wcpu$(DIRSEP)
 
+AFLAGS=-mh -0 -d1
 16FLAGS=-fh=16.hed
 BAKAPIFLAGS=-fh=bakapi.hed
 SFLAGS=-sg -st -of+ -zu -zdf -zff -zgf -k55808#60000#32768
 DFLAGS=-DTARGET_MSDOS=16 -DMSDOS=1 $(SFLAGS)
 ZFLAGS=-zk0 -zq -zc -zp8# -zm
-CFLAGS=$(IFLAGS) -mh -lr -l=dos -wo# -d2##wwww
-OFLAGS=-obmiler -out -oh -ei -zp8 -0 -fpi87  -onac -ol+ -ok####x
+CFLAGS=$(AFLAGS) $(IFLAGS)-lr -l=dos -wo##wwww
+OFLAGS=-obmiler -out -oh -ei -zp8 -fpi87  -onac -ol+ -ok####x
 FLAGS=$(CFLAGS) $(OFLAGS) $(DFLAGS) $(ZFLAGS)
 
+
 DOSLIBEXMMOBJ = himemsys.$(OBJ) emm.$(OBJ)
 VGMSNDOBJ = vgmSnd.$(OBJ) 16_snd.$(OBJ)
 DOSLIBOBJ = adlib.$(OBJ) 8254.$(OBJ) 8259.$(OBJ) dos.$(OBJ) cpu.$(OBJ)
@@ -87,8 +91,8 @@ all: $(EXEC) comp
 16.exe: 16.$(OBJ) mapread.$(OBJ) jsmn.$(OBJ) $(16LIBOBJS) gfx.lib
        wcl $(FLAGS) $(16FLAGS) 16.$(OBJ) mapread.$(OBJ) jsmn.$(OBJ) $(16LIBOBJS) gfx.lib -fm=16.map
 
-bakapi.exe: bakapi.$(OBJ) $(16LIBOBJS) gfx.lib
-       wcl $(FLAGS) $(BAKAPIFLAGS) bakapi.$(OBJ) $(16LIBOBJS) gfx.lib -fm=bakapi.map
+bakapi.exe: bakapi.$(OBJ) $(16LIBOBJS) gfx.lib modex.lib
+       wcl $(FLAGS) $(BAKAPIFLAGS) bakapi.$(OBJ) $(16LIBOBJS) gfx.lib modex.lib -fm=bakapi.map
 #
 #Test Executables!
 #
@@ -372,13 +376,21 @@ vgmSnd.$(OBJ): $(VGMSNDLIB)vgmSnd.h $(VGMSNDLIB)vgmSnd.c
 #memory.$(OBJ): $(EXMMLIB)memory.h $(EXMMLIB)memory.c
 #      wcl $(FLAGS) $(MFLAGS) -c $(EXMMLIB)memory.c
 
+c_utils.$(OBJ): $(MODEXLIB_)c_utils.asm
+       wcl -c $(AFLAGS) $(MODEXLIB_)c_utils.asm
+modex.$(OBJ): $(MODEXLIB_)modex.asm
+       wcl -c $(AFLAGS) $(MODEXLIB_)modex.asm
+
 #
 #other~
 #
 clean: .symbolic
        @$(REMOVECOMMAND) $(EXEC)
        @$(REMOVECOMMAND) *.$(OBJ)
-       @$(REMOVECOMMAND) *.lib
+       @$(REMOVECOMMAND) 16.lib
+       @$(REMOVECOMMAND) gfx.lib
+       @$(REMOVECOMMAND) doslib.lib
+       @$(REMOVECOMMAND) vgmsnd.lib
        @wlib -n 16.lib
        @wlib -n  gfx.lib
        @wlib -n  doslib.lib
@@ -411,8 +423,27 @@ clean: .symbolic
 
 comp: .symbolic
        @upx -9 -qqq $(EXEC)
+       @upx -9 -qqq x-demo.exe
 
 updatelibs: .symbolic
-       cd $(JSMNLIB)
-       git pull
-       cd ../../../
+       @cd $(JSMNLIB)
+       @git pull
+       @cd ../../../
+
+xlib: .symbolic
+       @cd 16/xlib
+       @wmake clean
+       @wmake all
+       @cd ../../
+
+mx: .symbolic
+       @cd 16/xw
+#      @wmake clean
+       @wmake all
+       @cd ../../
+
+mx_: .symbolic
+       @cd 16/xw_
+       @wmake -f makefile all
+       @cd ../../
+
index 648302a2abf164660ac59f96d488b31c44a60a9e..34a080b33044904719d53b89dec2d78504041df8 100755 (executable)
Binary files a/maptest.exe and b/maptest.exe differ
index a357fa6f0a4318911858789e69243c6bb63f8361..42f7a095fda1df04589e3701133dbf379debcf1e 100755 (executable)
Binary files a/palettec.exe and b/palettec.exe differ
index 1ced8d499687a00d410417764ff3919ba3548bef..bd3308a941f45872965469e17b3d01dc10f035b5 100755 (executable)
Binary files a/palettel.exe and b/palettel.exe differ
index bfbd9f6399b118051408b6e2a8c7524005bb903b..e9ccd81f4afe462b4e2a011aa81f9eb2c4d41d63 100755 (executable)
Binary files a/pcxtest.exe and b/pcxtest.exe differ
index e77b814032938219925c3cdf6a11a7b19aa241d1..ea2e98bbb0a5b58419d992093b822501e536bd12 100755 (executable)
Binary files a/pcxtest2.exe and b/pcxtest2.exe differ
index 89919c9898dda5122619240f022119b022243ce3..2a242c93835d2922ff3c022e62f6182a5d8bf9f2 100755 (executable)
Binary files a/planrpcx.exe and b/planrpcx.exe differ
index 8b04afe2e8a9e8d4ad2f9299a0a2e7cc73cebcb4..ee058e2881bd93d5875a765dc227790a4c75167f 100755 (executable)
Binary files a/scroll.exe and b/scroll.exe differ
index e9602c623fac90e415fb8a94f05964e023b51f85..8c5dc8213aba4e05b2b79782f0216f5bd02c655e 100755 (executable)
@@ -5,7 +5,15 @@ code it!
 
 what?
 
-planar function from pcx must be made~
+
+
+test which modex library is faster!
+edit input and switch unecessary words to bytes
+
+
+
+
+planar function from pcx must be made~ ok
 
 font! ok
 jis! ...
index 5022f0dafb17e64a3435783a0496e7366261f3d4..16a0c77f07b49f2f79ca54072774cad219f70ddd 100755 (executable)
@@ -41,7 +41,11 @@ main(int argc, char *argvar[])
        xdir=1;
        ydir=1;
 
+#ifdef MXLIB
        VGAmodeX(1, &gvar);
+#else
+       mxSetMode(3);
+#endif
        bakapee.xx = rand()&0%gvar.video.page[0].width;
        bakapee.yy = rand()&0%gvar.video.page[0].height;
        bakapee.gq = 0;
@@ -73,9 +77,14 @@ main(int argc, char *argvar[])
                }
                else
                {
+                       #ifndef MXLIB
+                       mxChangeMode(0);
+#else
                        VGAmodeX(0, &gvar);
+#endif
                        //modexLeave();
                        // user imput switch
+                       fprintf(stderr, "xx=%d  yy=%d\n", bakapee.xx, bakapee.yy);
                        printf("Enter 1, 2, 3, 4, or 6 to run a screensaver, or enter 0 to quit.\n", getch());  // prompt the user
                        scanf("%d", &key);
                        //if(key==3){xx=yy=0;} // crazy screen saver wwww
@@ -83,7 +92,11 @@ main(int argc, char *argvar[])
                                gvar.video.page[0] = modexDefaultPage(&gvar.video.page[0]);
                                gvar.video.page[0].width += (TILEWH*2);
                                gvar.video.page[0].height += (TILEWH*2);
+#ifdef MXLIB
                                VGAmodeX(1, &gvar);
+#else
+                               mxChangeMode(3);
+#endif
                                modexShowPage(&gvar.video.page[0]);
                        }
                }
index bb11c095eab2567a2fede1ef4a4a112445d24dcb..84804f6cb9e1cda1338dbc19b63daa3bb6a85a83 100755 (executable)
@@ -849,17 +849,18 @@ register  KeyboardDef     *def;
                                mx = motion_Left,my = motion_Down;\r
                        else if (Keyboard[def->downright])\r
                                mx = motion_Right,my = motion_Down;*/\r
-                       //if(!inpu.Keyboard[def->left] && !inpu.Keyboard[def->right]){\r
+                       if(!inpu.Keyboard[def->left] && !inpu.Keyboard[def->right]){\r
                        if((inpu.Keyboard[def->up] && !inpu.Keyboard[def->down] && player[playnum].d == 2))// || player[playnum].info.dir == 0)\r
                                my = motion_Up;\r
                        if((inpu.Keyboard[def->down] && !inpu.Keyboard[def->up] && player[playnum].d == 2))// || player[playnum].info.dir == 4)\r
                                my = motion_Down;\r
-                       //}else if(!inpu.Keyboard[def->up] && !inpu.Keyboard[def->down]){\r
+                       }else if(!inpu.Keyboard[def->up] && !inpu.Keyboard[def->down]){\r
                        if((inpu.Keyboard[def->left] && !inpu.Keyboard[def->right] && player[playnum].d == 2))// || player[playnum].info.dir == 1)\r
                                mx = motion_Left;\r
                        if((inpu.Keyboard[def->right] && !inpu.Keyboard[def->left] && player[playnum].d == 2))// || player[playnum].info.dir == 3)\r
                                mx = motion_Right;\r
-                       //}\r
+                       }\r
+                       //input from player\r
                        if (inpu.Keyboard[def->button0])\r
                                buttons += 1 << 0;\r
                        if (inpu.Keyboard[def->button1])\r
index 040db6f9f9782c91c350df182eef02affaf7ddb1..000ac84a1e5075b4300f5b7215c1b077d6a5ba5e 100755 (executable)
@@ -63,11 +63,16 @@ void ssd(page_t *page, bakapee_t *pee, word svq)
        }else pee->sy = 0;
 }
 
-//plot pixel
+//plot pixel or plot tile
 void dingpp(page_t *page, bakapee_t *pee)
 {
 #ifdef TILE
+#ifndef MXLIB
+       //fill_block(pee->xx, pee->yy, pee->xx+TILEWH, pee->yy+TILEWH, pee->coor);
+       mxFillBox(pee->xx, pee->yy, TILEWH, TILEWH, pee->coor, OP_SET);
+#else
        modexClearRegion(page, pee->xx, pee->yy, TILEWH, TILEWH, pee->coor);
+#endif
 #else
        modexputPixel(page, pee->xx, pee->yy, pee->coor);
 #endif
index 3e228a4af6bcd76bc0ffe5fcb545075b28979df4..df74c1bda3018df4e17596da2f3161a58ea3e349 100755 (executable)
@@ -25,6 +25,8 @@
 \r
 #include "src/lib/16_head.h"\r
 #include "src/lib/modex16.h"\r
+//#include "src/lib/modex/modex.h"\r
+#include "16/x/modex.h"\r
 \r
 #define TILEWH 16\r
 #define QUADWH                 TILEWH/2\r
 #define LGQ         32\r
 #define HGQ         55\r
 \r
-//#define TILE\r
+#define TILE\r
+\r
+//which lib?\r
+#define MXLIB\r
 \r
 typedef struct {\r
        word gq;\r
diff --git a/src/lib/modex/asm.bat b/src/lib/modex/asm.bat
new file mode 100755 (executable)
index 0000000..2e5785f
--- /dev/null
@@ -0,0 +1 @@
+MASM modex,modex,modex,nul
\ No newline at end of file
diff --git a/src/lib/modex/c_utils.asm b/src/lib/modex/c_utils.asm
new file mode 100755 (executable)
index 0000000..0118201
--- /dev/null
@@ -0,0 +1,456 @@
+;=======================================================\r
+;===  C_UTILS.ASM  - Asm Utilities for C/C++         ===\r
+;=======================================================\r
+\r
+       PAGE    255, 132\r
+\r
+       .MODEL Huge\r
+;      .286\r
+\r
+       ; ==== MACROS ====\r
+\r
+       ; macros to PUSH and POP multiple registers\r
+\r
+; PUSHx MACRO R1, R2, R3, R4;, R5, R6, R7, R8\r
+;      IFNB <R1>\r
+;              push    R1                              ; Save R1\r
+;              PUSHx   R2, R3, R4;, R5, R6, R7, R8\r
+;      ENDIF\r
+; ENDM\r
+;\r
+; POPx MACRO R1, R2, R3, R4;, R5, R6, R7, R8\r
+;      IFNB <R1>\r
+;              pop             R1                              ; Restore R1\r
+;              POPx    R2, R3, R4;, R5, R6, R7, R8\r
+;      ENDIF\r
+; ENDM\r
+\r
+       ; Macro to Clear a Register to 0\r
+\r
+CLR MACRO Register\r
+       xor             Register, Register              ; Set Register = 0\r
+ENDM\r
+\r
+       ; Macros to Decrement Counter & Jump on Condition\r
+\r
+LOOPx MACRO Register, Destination\r
+       dec             Register                                ; Counter--\r
+       jnz             Destination                             ; Jump if not 0\r
+ENDM\r
+\r
+LOOPjz MACRO Register, Destination\r
+       dec             Register                                ; Counter--\r
+       jz              Destination                             ; Jump if 0\r
+ENDM\r
+\r
+\r
+       ; ==== General Constants ====\r
+\r
+       False   EQU     0\r
+       True    EQU     -1\r
+       nil             EQU 0\r
+\r
+       b               EQU     BYTE PTR\r
+       w               EQU     WORD PTR\r
+       d               EQU     DWORD PTR\r
+       o               EQU     OFFSET\r
+       f               EQU FAR PTR\r
+       s               EQU     SHORT\r
+       ?x4             EQU <?,?,?,?>\r
+       ?x3             EQU <?,?,?>\r
+       ?x2             EQU <?,?>\r
+       ?x1             EQU <?>\r
+\r
+\r
+       .Data\r
+\r
+       EVEN\r
+\r
+RND_Seed       DW      7397, 29447, 802\r
+RND_Mult       DW      179, 183, 182\r
+RND_ModV       DW      32771, 32779, 32783\r
+\r
+CR_LF          DB      13, 10                  ; the CRLF data\r
+\r
+       .Code\r
+\r
+;===========================================\r
+;void far pascal dos_print  (far char *Text)\r
+;===========================================\r
+;\r
+; - Print Text Directly to DOS console w/ CR/LF\r
+;\r
+\r
+       PUBLIC  DOS_PRINT\r
+\r
+DP_Stack       STRUC\r
+                               DW      ?x1     ; DI, SI, DS, BP\r
+                               DW      ?x1     ; DI, SI, DS, BP\r
+                               DW      ?x1     ; DI, SI, DS, BP\r
+                               DW      ?x1     ; DI, SI, DS, BP\r
+                               DD      ?       ; Caller\r
+       DP_Text         DD      ?       ; Far Address of Text to print\r
+DP_Stack       ENDS\r
+\r
+\r
+DOS_PRINT       PROC    FAR\r
+\r
+       ;PUSHx  BP, DS, SI, DI          ; Preserve Important Registers\r
+       push bp\r
+       push ds\r
+       push si\r
+       push di\r
+       mov             BP, SP                          ; Set up Stack Frame\r
+\r
+       lds     DX, [BP].DP_Text        ; Get Addr of Text$ descriptor\r
+\r
+       ; Compute Length of string\r
+\r
+       CLR             CX                                      ; Length = 0\r
+       mov             SI, DX                          ; DS:SI = String data\r
+\r
+@@DP_Scan_it:\r
+\r
+       cmp             b [SI], 0                       ; Null Byte found?\r
+       je              @@DP_Got_Len            ; exit loop if so\r
+\r
+       inc             CX                                      ; Len++\r
+       inc             SI                                      ; Point to next char\r
+       jmp             s @@DP_Scan_it          ; check again...\r
+\r
+@@DP_Got_len:\r
+\r
+       jcxz    @No_Print                       ; Don't Print if empty\r
+\r
+       mov             BX, 1                           ; 1= DOS Handle for Display\r
+       mov             AH, 40h                         ; Write Text Function\r
+       int             21h                                     ; Call DOS to do it\r
+\r
+@No_Print:\r
+       mov             AX, SEG DGROUP          ; Restore DGroup\r
+       mov             DS, AX\r
+\r
+       mov             DX, o CR_LF                     ; Get Addr of CR/LF pair\r
+       mov             CX, 2                           ; 2 Characters to Write\r
+       mov             BX, 1                           ; 1= DOS Handle for Display\r
+\r
+       mov             AH, 40h                         ; Write Text Function\r
+       int             21h                                     ; Call DOS to do it\r
+\r
+       cld                                                     ; Reset Direction Flag\r
+       ;POPx   DI, SI, DS, BP          ; Restore Saved Registers\r
+       pop di\r
+       pop si\r
+       pop ds\r
+       pop bp\r
+       ret             4                                       ; Exit & Clean Up Stack\r
+\r
+DOS_PRINT       ENDP\r
+\r
+\r
+;===========================================\r
+;void far pascal dos_prints (char far *Text)\r
+;===========================================\r
+;\r
+; Print Text Directly to DOS console\r
+; without a trailing CR/LF\r
+;\r
+\r
+       PUBLIC  DOS_PRINTS\r
+\r
+DOS_PRINTS      PROC    FAR\r
+\r
+       ;PUSHx  BP, DS, SI, DI          ; Preserve Important Registers\r
+       push bp\r
+       push ds\r
+       push si\r
+       push di\r
+       mov             BP, SP                          ; Set up Stack Frame\r
+\r
+       lds     DX, [BP].DP_Text        ; Get Addr of Text$ descriptor\r
+\r
+       ; Compute Length of string\r
+\r
+       CLR             CX                                      ; Length = 0\r
+       mov             SI, DX                          ; DS:SI = String data\r
+\r
+@@DPS_Scan_it:\r
+\r
+       cmp             b [SI], 0                       ; Null Byte found?\r
+       je              @@DPS_Got_Len           ; exit loop if so\r
+\r
+       inc             CX                                      ; Len++\r
+       inc             SI                                      ; Point to next char\r
+       jmp             s @@DPS_Scan_it         ; check again...\r
+\r
+@@DPS_Got_len:\r
+\r
+       jcxz    @DPS_Exit                       ; Don't Print if empty\r
+\r
+       mov             BX, 1                           ; 1= DOS Handle for Display\r
+       mov             AH, 40h                         ; Write Text Function\r
+       int             21h                                     ; Call DOS to do it\r
+\r
+@DPS_Exit:\r
+       cld                                                     ; Reset Direction Flag\r
+       ;POPx   DI, SI, DS, BP          ; Restore Saved Registers\r
+       pop di\r
+       pop si\r
+       pop ds\r
+       pop bp\r
+       ret             2                                       ; Exit & Clean Up Stack\r
+\r
+DOS_PRINTS      ENDP\r
+\r
+\r
+;=========================================\r
+;void far pascal set_video_mode (int Mode)\r
+;=========================================\r
+;\r
+; Sets the Video Mode through the BIOS\r
+;\r
+\r
+       PUBLIC  SET_VIDEO_MODE\r
+\r
+SVM_Stack      STRUC\r
+                               DW      ?x1     ; DI, SI, DS, BP\r
+                               DW      ?x1     ; DI, SI, DS, BP\r
+                               DW      ?x1     ; DI, SI, DS, BP\r
+                               DW      ?x1     ; DI, SI, DS, BP\r
+                               DD      ?       ; Caller\r
+       SVM_Mode        DB      ?,? ; Desired Video Mode\r
+SVM_Stack      ENDS\r
+\r
+\r
+SET_VIDEO_MODE PROC    FAR\r
+\r
+       ;PUSHx  BP, DS, SI, DI          ; Preserve Important Registers\r
+       push bp\r
+       push ds\r
+       push si\r
+       push di\r
+       mov             BP, SP                          ; Set up Stack Frame\r
+\r
+       CLR             AH                                      ; Function 0\r
+       mov             AL, [BP].SVM_Mode       ; Get Mode #\r
+\r
+       int             10H                                     ; Change Video Modes\r
+\r
+@SVM_Exit:\r
+       ;POPx   DI, SI, DS, BP          ; Restore Saved Registers\r
+       pop di\r
+       pop si\r
+       pop ds\r
+       pop bp\r
+       ret             2                                       ; Exit & Clean Up Stack\r
+\r
+SET_VIDEO_MODE ENDP\r
+\r
+\r
+;===================================\r
+;int far pascal scan_keyboard (void)\r
+;===================================\r
+;\r
+; Function to scan keyboard for a pressed key\r
+;\r
+\r
+       PUBLIC  SCAN_KEYBOARD\r
+\r
+SCAN_KEYBOARD  PROC    FAR\r
+\r
+       ;PUSHx  BP, DS, SI, DI          ; Preserve Important Registers\r
+       push bp\r
+       push ds\r
+       push si\r
+       push di\r
+\r
+       mov             AH, 01H                         ; Function #1\r
+       INT             16H                                     ; Call Keyboard Driver\r
+       JZ              @SK_NO_KEY                      ; Exit if Zero flag set\r
+\r
+       mov             AH,     00H                             ; Remove Key from Buffer\r
+       INT             16H                                     ; Get Keycode in AX\r
+\r
+       OR              AL, AL                          ; Low Byte Set (Ascii?)\r
+       JZ              @SK_Exit                        ; if not, it's a F-Key\r
+\r
+       CLR             AH                                      ; Clear ScanCode if Ascii\r
+       JMP             s @SK_Exit                      ; Return Key in AX\r
+\r
+@SK_NO_KEY:\r
+       CLR             AX                                      ; Return Nil (no Keypress)\r
+\r
+@SK_Exit:\r
+       cld                                                     ; Reset Direction Flag\r
+       ;POPx   DI, SI, DS, BP          ; Restore Saved Registers\r
+       pop di\r
+       pop si\r
+       pop ds\r
+       pop bp\r
+       ret                                                     ; Exit & Clean Up Stack\r
+\r
+SCAN_KEYBOARD  ENDP\r
+\r
+\r
+;========================================\r
+;int far pascal random_int (int MaxValue)\r
+;========================================\r
+;\r
+; Returns a pseudo-random number in the range of (0.. MaxInt-1)\r
+;\r
+\r
+\r
+       PUBLIC  RANDOM_INT\r
+\r
+RI_Stack       STRUC\r
+                               DW      ?       ; BP\r
+                               DD      ?       ; Caller\r
+       RI_MaxVal       DW      ?       ; Maximum Value to Return + 1\r
+RI_Stack       ENDS\r
+\r
+\r
+RANDOM_INT     PROC    FAR\r
+\r
+       push    BP                                      ; Preserve Important Registers\r
+       mov             BP, SP                          ; Set up Stack Frame\r
+\r
+       CLR             BX                                      ; BX is the data index\r
+       CLR             CX                              ; CX is the accumulator\r
+\r
+REPT 3\r
+       mov             AX, RND_Seed[BX]        ; load the initial seed\r
+       mul             RND_Mult[BX]            ; multiply it\r
+       div             RND_ModV[BX]            ; and obtain the Mod value\r
+       mov             RND_Seed[BX], DX        ; save that for the next time\r
+\r
+       add             CX, DX                          ; add it into the accumulator\r
+       inc             BX\r
+       inc             BX                      ; point to the next set of values\r
+ENDM\r
+\r
+       mov             AX, CX                          ; AX = Random #\r
+       CLR             DX                                      ; DX = 0\r
+       div             [BP].RI_MaxVal          ; DX = DX:AX / MAxVal Remainder\r
+\r
+       mov             AX, DX\r
+\r
+       pop             BP                                      ; Restore BP\r
+       ret             2                               ; back to BASIC with AX holding the result\r
+\r
+RANDOM_INT     ENDP\r
+\r
+\r
+;==================================\r
+;void far pascal init_random (void)\r
+;==================================\r
+;\r
+; Scrambles the psuedo-random number sequence\r
+; (XOR's the seed value with the timer)\r
+;\r
+\r
+       PUBLIC  INIT_RANDOM\r
+\r
+INIT_RANDOM    PROC    FAR\r
+\r
+       CLR             AX                                      ; Segment = 0000\r
+       mov             ES, AX\r
+       mov             AX, ES:[046Ch]      ; Get Timer Lo Word\r
+\r
+       xor             RND_Seed, AX            ; Scramble 1st Seed\r
+\r
+       ret                                                     ; Exit & Clean Up Stack\r
+\r
+INIT_RANDOM    ENDP\r
+\r
+;=========================================\r
+;int far pascal int_sqr (int X, int Round)\r
+;=========================================\r
+;\r
+; Returns the Integer Square Root of (X)\r
+; Round allows the return value to be rounded to the\r
+; nearest integer value by passing 0x80.  Passing 0\r
+; return the Integer Portion only.  The rounding amound is\r
+; a number from 0 to 1 multiplied by 256, thus\r
+; 0.5 * 0x100 = 0x80!\r
+;\r
+\r
+ISQ_Stack      STRUC\r
+                                       DW      ?,?     ; BP, DI\r
+                                       DD      ?       ; Caller\r
+       ISQ_Round               DW      ?       ; Amount to Round Result * 256\r
+       ISQ_X                   DW      ?       ; "X"\r
+ISQ_Stack      ENDS\r
+\r
+       PUBLIC  INT_SQR\r
+\r
+INT_SQR                PROC    FAR\r
+\r
+    ;PUSHx   BP, DI                            ; Save BP\r
+       push bp\r
+       push di\r
+    mov     BP, SP                             ; Set up Stack Frame\r
+\r
+       xor     AX, AX                          ; {xor eax,eax}\r
+       xor     DX, DX                          ; {xor edx,edx}\r
+       mov     DI, [BP].ISQ_X          ; {mov edi,x}\r
+\r
+       mov     CX, 16                          ; {mov cx, 32}\r
+\r
+@ISQ_L:\r
+\r
+       shl     DI, 1                           ; {shl edi,1}\r
+       rcl     DX, 1                           ; {rcl edx,1}\r
+       shl     DI, 1                           ; {shl edi,1}\r
+       rcl     DX, 1                           ; {rcl edx,1}\r
+       shl     AX, 1                           ; {shl eax,1}\r
+       mov     BX, AX                          ; {mov ebx,eax}\r
+       shl     BX, 1                           ; {shl ebx,1}\r
+       inc     BX                                      ; {inc ebx}\r
+       cmp     DX, BX                          ; {cmp edx,ebx}\r
+       jl              @ISQ_S\r
+\r
+       sub     DX, BX                          ; {sub edx,ebx}\r
+       inc     AX                                      ; {inc eax}\r
+\r
+@ISQ_S:\r
+       loop    @ISQ_L\r
+\r
+       add     ax, [BP].ISQ_Round      ; {add eax,$00008000}\r
+                                                               ; {*round* result in hi word: ie. +0.5}\r
+       shr     ax, 1                           ; {shr eax,16}  {to ax (result)}\r
+       shr     ax, 1                           ; {shr eax,16}  {to ax (result)}\r
+       shr     ax, 1                           ; {shr eax,16}  {to ax (result)}\r
+       shr     ax, 1                           ; {shr eax,16}  {to ax (result)}\r
+       shr     ax, 1                           ; {shr eax,16}  {to ax (result)}\r
+       shr     ax, 1                           ; {shr eax,16}  {to ax (result)}\r
+       shr     ax, 1                           ; {shr eax,16}  {to ax (result)}\r
+       shr     ax, 1                           ; {shr eax,16}  {to ax (result)}\r
+\r
+       ;POPx   DI, BP                          ; Restore Registers\r
+       pop di\r
+       pop bp\r
+       ret             4                                       ; Exit\r
+\r
+INT_SQR                ENDP\r
+\r
+;=================================\r
+;int far pascal timer_count (void)\r
+;=================================\r
+;\r
+; Returns the current timer value as an integer/long integer\r
+;\r
+\r
+       PUBLIC  TIMER_COUNT\r
+\r
+TIMER_COUNT      PROC    FAR\r
+\r
+       CLR             AX                                      ; Segment = 0000\r
+       mov             ES, AX\r
+       mov             AX, ES:[046Ch]      ; Get Timer Lo Word\r
+       mov             DX, ES:[046Eh]          ; Get Timer Hi Word\r
+       ret                                                     ; Exit & Clean Up Stack\r
+\r
+TIMER_COUNT      ENDP\r
+\r
+\r
+       END\r
diff --git a/src/lib/modex/c_utils.h b/src/lib/modex/c_utils.h
new file mode 100755 (executable)
index 0000000..9be6ba2
--- /dev/null
@@ -0,0 +1,117 @@
+\r
+#ifndef __C_UTILS_H\r
+#define __C_UTILS_H\r
+\r
+\r
+       /* Misc Constants */\r
+\r
+#define True     -1\r
+#define False    0\r
+#define nil      0\r
+\r
+       /* Color Constants */\r
+\r
+#define c_BLACK   0\r
+#define c_BLUE    1\r
+#define c_GREEN   2\r
+#define c_CYAN    3\r
+#define c_RED     4\r
+#define c_PURPLE  5\r
+#define c_BROWN   6\r
+#define c_WHITE   7\r
+#define c_GREY    8\r
+#define c_bBLUE   9\r
+#define c_bGREEN  10\r
+#define c_bCYAN   11\r
+#define c_bRED    12\r
+#define c_bPURPLE 13\r
+#define c_YELLOW  14\r
+#define c_bWHITE  15\r
+#define c_BRIGHT  16\r
+\r
+\r
+#define Ky_F1     0x3B00\r
+#define Ky_F2     0x3C00\r
+#define Ky_F3     0x3D00\r
+#define Ky_F4     0x3E00\r
+#define Ky_F5     0x3F00\r
+#define Ky_F6     0x4000\r
+#define Ky_F7     0x4100\r
+#define Ky_F8     0x4200\r
+#define Ky_F9     0x4300\r
+#define Ky_F10    0x4400\r
+\r
+#define Ky_Up     0x4800\r
+#define Ky_Left   0x4B00\r
+#define Ky_Right  0x4D00\r
+#define Ky_Down   0x5000\r
+#define Ky_SUp    0xC800\r
+#define Ky_SLeft  0xCB00\r
+#define Ky_SRight 0xCD00\r
+#define Ky_SDown  0xD000\r
+\r
+#define Ky_Home   0x4700\r
+#define Ky_End    0x4F00\r
+#define Ky_PgUp   0x4900\r
+#define Ky_PgDn   0x5100\r
+#define Ky_SHome  0xC700\r
+#define Ky_SEnd   0xCF00\r
+#define Ky_SPgUp  0xC900\r
+#define Ky_SPgDn  0xD100\r
+\r
+#define Ky_Ins    0x5200\r
+#define Ky_Del    0x5300\r
+#define Ky_SIns   0xC200\r
+#define Ky_SDel   0xC300\r
+\r
+#define Ky_Tab    0x0009\r
+#define Ky_RvsTab 0x8F00\r
+#define Ky_STab   0x8F00\r
+\r
+#define Ky_BS     0x0008\r
+#define Ky_CR     0x000D\r
+#define Ky_ESC    0x001B\r
+#define Ky_Clr    0x007F\r
+\r
+#define Ky_Plus   0x002D\r
+#define Ky_Minus  0x002B\r
+\r
+#define Ky_AltA   0x1E00\r
+#define Ky_AltB   0x3000\r
+#define Ky_AltC   0x2E00\r
+#define Ky_AltD   0x2000\r
+#define Ky_AltE   0x1200\r
+#define Ky_AltF   0x2100\r
+#define Ky_AltG   0x2200\r
+#define Ky_AltH   0x2300\r
+#define Ky_AltI   0x1700\r
+#define Ky_AltJ   0x2400\r
+#define Ky_AltK   0x2500\r
+#define Ky_AltL   0x2600\r
+#define Ky_AltM   0x3200\r
+#define Ky_AltN   0x3100\r
+#define Ky_AltO   0x1800\r
+#define Ky_AltP   0x1900\r
+#define Ky_AltQ   0x1000\r
+#define Ky_AltR   0x1300\r
+#define Ky_AltS   0x1F00\r
+#define Ky_AltT   0x1400\r
+#define Ky_AltU   0x1600\r
+#define Ky_AltV   0x2F00\r
+#define Ky_AltW   0x1100\r
+#define Ky_AltX   0x2D00\r
+#define Ky_AltY   0x1500\r
+#define Ky_AltZ   0x2C00\r
+\r
+       /* .ASM Functions From C_UTILS.ASM */\r
+\r
+void far pascal dos_print (char far *Text);\r
+void far pascal dos_prints (char far *Text);\r
+void far pascal set_video_mode (int Mode);\r
+int  far pascal scan_keyboard (void);\r
+int  far pascal random_int (int MaxValue);\r
+void far pascal init_random (void);\r
+int  far pascal int_sqr (int X, int Round);\r
+int  far pascal timer_count (void);\r
+\r
+#endif\r
diff --git a/src/lib/modex/c_utils.lst b/src/lib/modex/c_utils.lst
new file mode 100755 (executable)
index 0000000..f9664ba
--- /dev/null
@@ -0,0 +1,597 @@
+Microsoft (R) Macro Assembler Version 6.11                 07/03/14 12:38:18\r
+c_utils.asm                                                 Page 1 - 1\r
+\r
+\r
+                               ;=======================================================\r
+                               ;===  C_UTILS.ASM  - Asm Utilities for C/C++         ===\r
+                               ;=======================================================\r
+\r
+                                       PAGE    255, 132\r
+\r
+                                       .MODEL Medium\r
+                                       .286\r
+\r
+                                       ; ==== MACROS ====\r
+\r
+                                       ; macros to PUSH and POP multiple registers\r
+\r
+                               PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+                                       IFNB <R1>\r
+                                               push    R1                              ; Save R1\r
+                                               PUSHx   R2, R3, R4, R5, R6, R7, R8\r
+                                       ENDIF\r
+                               ENDM\r
+\r
+                               POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+                                       IFNB <R1>\r
+                                               pop             R1                              ; Restore R1\r
+                                               POPx    R2, R3, R4, R5, R6, R7, R8\r
+                                       ENDIF\r
+                               ENDM\r
+\r
+                                       ; Macro to Clear a Register to 0\r
+\r
+                               CLR MACRO Register\r
+                                       xor             Register, Register              ; Set Register = 0\r
+                               ENDM\r
+\r
+                                       ; Macros to Decrement Counter & Jump on Condition\r
+\r
+                               LOOPx MACRO Register, Destination\r
+                                       dec             Register                                ; Counter--\r
+                                       jnz             Destination                             ; Jump if not 0\r
+                               ENDM\r
+\r
+                               LOOPjz MACRO Register, Destination\r
+                                       dec             Register                                ; Counter--\r
+                                       jz              Destination                             ; Jump if 0\r
+                               ENDM\r
+\r
+\r
+                                       ; ==== General Constants ====\r
+\r
+ = 0000                                        False   EQU     0\r
+ =-0001                                        True    EQU     -1\r
+ = 0000                                        nil             EQU 0\r
+\r
+ = BYTE PTR                            b               EQU     BYTE PTR\r
+ = WORD PTR                            w               EQU     WORD PTR\r
+ = DWORD PTR                           d               EQU     DWORD PTR\r
+ = OFFSET                              o               EQU     OFFSET\r
+ = FAR PTR                             f               EQU FAR PTR\r
+ = SHORT                               s               EQU     SHORT\r
+ = ?,?,?,?                             ?x4             EQU <?,?,?,?>\r
+ = ?,?,?                               ?x3             EQU <?,?,?>\r
+\r
+\r
+ 0000                                  .Data\r
+\r
+                                       EVEN\r
+\r
+ 0000 1CE5 7307 0322           RND_Seed        DW      7397, 29447, 802\r
+ 0006 00B3 00B7 00B6           RND_Mult        DW      179, 183, 182\r
+ 000C 8003 800B 800F           RND_ModV        DW      32771, 32779, 32783\r
+\r
+ 0012 0D 0A                    CR_LF           DB      13, 10                  ; the CRLF data\r
+\r
+ 0000                                  .Code\r
+\r
+                               ;===========================================\r
+                               ;void far pascal dos_print  (far char *Text)\r
+                               ;===========================================\r
+                               ;\r
+                               ; - Print Text Directly to DOS console w/ CR/LF\r
+                               ;\r
+\r
+                                       PUBLIC  DOS_PRINT\r
+\r
+ 0010                          DP_Stack        STRUC\r
+ 0000  0000 0000 0000                                          DW      ?x4     ; DI, SI, DS, BP\r
+       0000\r
+ 0008  00000000                                                        DD      ?       ; Caller\r
+ 000C  00000000                                DP_Text         DD      ?       ; Far Address of Text to print\r
+                               DP_Stack        ENDS\r
+\r
+\r
+ 0000                          DOS_PRINT        PROC    FAR\r
+                                                          \r
+                                       PUSHx   BP, DS, SI, DI          ; Preserve Important Registers\r
+ 0000  55                   1                  push    BP                              ; Save R1\r
+ 0001  1E                   2                  push    DS                              ; Save R1\r
+ 0002  56                   3                  push    SI                              ; Save R1\r
+ 0003  57                   4                  push    DI                              ; Save R1\r
+ 0004  8B EC                           mov             BP, SP                          ; Set up Stack Frame\r
+\r
+ 0006  C5 56 0C                                lds     DX, [BP].DP_Text        ; Get Addr of Text$ descriptor\r
+\r
+                                       ; Compute Length of string\r
+\r
+                                       CLR             CX                                      ; Length = 0\r
+ 0009  33 C9                1          xor             CX, CX          ; Set Register = 0\r
+ 000B  8B F2                           mov             SI, DX                          ; DS:SI = String data\r
+\r
+ 000D                          @@DP_Scan_it:\r
+                                       \r
+ 000D  80 3C 00                                cmp             b [SI], 0                       ; Null Byte found?\r
+ 0010  74 04                           je              @@DP_Got_Len            ; exit loop if so\r
+\r
+ 0012  41                              inc             CX                                      ; Len++\r
+ 0013  46                              inc             SI                                      ; Point to next char\r
+ 0014  EB F7                           jmp             s @@DP_Scan_it          ; check again...\r
+\r
+ 0016                          @@DP_Got_len:\r
+\r
+ 0016  E3 07                           jcxz    @No_Print                       ; Don't Print if empty\r
+\r
+ 0018  BB 0001                         mov             BX, 1                           ; 1= DOS Handle for Display\r
+ 001B  B4 40                           mov             AH, 40h                         ; Write Text Function\r
+ 001D  CD 21                           int             21h                                     ; Call DOS to do it\r
+\r
+ 001F                          @No_Print:\r
+ 001F  B8 ---- R                       mov             AX, SEG DGROUP          ; Restore DGroup\r
+ 0022  8E D8                           mov             DS, AX\r
+\r
+ 0024  BA 0012 R                       mov             DX, o CR_LF                     ; Get Addr of CR/LF pair\r
+ 0027  B9 0002                         mov             CX, 2                           ; 2 Characters to Write         \r
+ 002A  BB 0001                         mov             BX, 1                           ; 1= DOS Handle for Display\r
+\r
+ 002D  B4 40                           mov             AH, 40h                         ; Write Text Function\r
+ 002F  CD 21                           int             21h                                     ; Call DOS to do it\r
+\r
+ 0031  FC                              cld                                                     ; Reset Direction Flag          \r
+                                       POPx    DI, SI, DS, BP          ; Restore Saved Registers\r
+ 0032  5F                   1                  pop             DI                              ; Restore R1\r
+ 0033  5E                   2                  pop             SI                              ; Restore R1\r
+ 0034  1F                   3                  pop             DS                              ; Restore R1\r
+ 0035  5D                   4                  pop             BP                              ; Restore R1\r
+ 0036  CA 0004                         ret             4                                       ; Exit & Clean Up Stack\r
+\r
+ 0039                          DOS_PRINT        ENDP\r
+\r
+\r
+                               ;===========================================\r
+                               ;void far pascal dos_prints (char far *Text)\r
+                               ;===========================================\r
+                               ; \r
+                               ; Print Text Directly to DOS console \r
+                               ; without a trailing CR/LF\r
+                               ;\r
+\r
+                                       PUBLIC  DOS_PRINTS\r
+\r
+ 0039                          DOS_PRINTS       PROC    FAR\r
+\r
+                                       PUSHx   BP, DS, SI, DI          ; Preserve Important Registers\r
+ 0039  55                   1                  push    BP                              ; Save R1\r
+ 003A  1E                   2                  push    DS                              ; Save R1\r
+ 003B  56                   3                  push    SI                              ; Save R1\r
+ 003C  57                   4                  push    DI                              ; Save R1\r
+ 003D  8B EC                           mov             BP, SP                          ; Set up Stack Frame\r
+\r
+ 003F  C5 56 0C                                lds     DX, [BP].DP_Text        ; Get Addr of Text$ descriptor\r
+\r
+                                       ; Compute Length of string\r
+\r
+                                       CLR             CX                                      ; Length = 0\r
+ 0042  33 C9                1          xor             CX, CX          ; Set Register = 0\r
+ 0044  8B F2                           mov             SI, DX                          ; DS:SI = String data\r
+\r
+ 0046                          @@DPS_Scan_it:\r
+                                       \r
+ 0046  80 3C 00                                cmp             b [SI], 0                       ; Null Byte found?\r
+ 0049  74 04                           je              @@DPS_Got_Len           ; exit loop if so\r
+\r
+ 004B  41                              inc             CX                                      ; Len++\r
+ 004C  46                              inc             SI                                      ; Point to next char\r
+ 004D  EB F7                           jmp             s @@DPS_Scan_it         ; check again...\r
+\r
+ 004F                          @@DPS_Got_len:\r
+\r
+ 004F  E3 07                           jcxz    @DPS_Exit                       ; Don't Print if empty\r
+\r
+ 0051  BB 0001                         mov             BX, 1                           ; 1= DOS Handle for Display\r
+ 0054  B4 40                           mov             AH, 40h                         ; Write Text Function\r
+ 0056  CD 21                           int             21h                                     ; Call DOS to do it\r
+\r
+ 0058                          @DPS_Exit:\r
+ 0058  FC                              cld                                                     ; Reset Direction Flag          \r
+                                       POPx    DI, SI, DS, BP          ; Restore Saved Registers\r
+ 0059  5F                   1                  pop             DI                              ; Restore R1\r
+ 005A  5E                   2                  pop             SI                              ; Restore R1\r
+ 005B  1F                   3                  pop             DS                              ; Restore R1\r
+ 005C  5D                   4                  pop             BP                              ; Restore R1\r
+ 005D  CA 0002                         ret             2                                       ; Exit & Clean Up Stack\r
+\r
+ 0060                          DOS_PRINTS       ENDP\r
+\r
+\r
+                               ;=========================================\r
+                               ;void far pascal set_video_mode (int Mode)\r
+                               ;=========================================\r
+                               ;\r
+                               ; Sets the Video Mode through the BIOS\r
+                               ;\r
+\r
+                                       PUBLIC  SET_VIDEO_MODE\r
+\r
+ 000E                          SVM_Stack       STRUC\r
+ 0000  0000 0000 0000                                          DW      ?x4     ; DI, SI, DS, BP\r
+       0000\r
+ 0008  00000000                                                        DD      ?       ; Caller\r
+ 000C  00 00                           SVM_Mode        DB      ?,? ; Desired Video Mode\r
+                               SVM_Stack       ENDS\r
+\r
+\r
+ 0060                          SET_VIDEO_MODE  PROC    FAR\r
+\r
+                                       PUSHx   BP, DS, SI, DI          ; Preserve Important Registers\r
+ 0060  55                   1                  push    BP                              ; Save R1\r
+ 0061  1E                   2                  push    DS                              ; Save R1\r
+ 0062  56                   3                  push    SI                              ; Save R1\r
+ 0063  57                   4                  push    DI                              ; Save R1\r
+ 0064  8B EC                           mov             BP, SP                          ; Set up Stack Frame\r
+\r
+                                       CLR             AH                                      ; Function 0\r
+ 0066  32 E4                1          xor             AH, AH          ; Set Register = 0\r
+ 0068  8A 46 0C                                mov             AL, [BP].SVM_Mode       ; Get Mode #\r
+\r
+ 006B  CD 10                           int             10H                                     ; Change Video Modes\r
+\r
+ 006D                          @SVM_Exit:\r
+                                       POPx    DI, SI, DS, BP          ; Restore Saved Registers\r
+ 006D  5F                   1                  pop             DI                              ; Restore R1\r
+ 006E  5E                   2                  pop             SI                              ; Restore R1\r
+ 006F  1F                   3                  pop             DS                              ; Restore R1\r
+ 0070  5D                   4                  pop             BP                              ; Restore R1\r
+ 0071  CA 0002                         ret             2                                       ; Exit & Clean Up Stack\r
+\r
+ 0074                          SET_VIDEO_MODE  ENDP\r
+\r
+\r
+                               ;===================================\r
+                               ;int far pascal scan_keyboard (void)\r
+                               ;===================================\r
+                               ;\r
+                               ; Function to scan keyboard for a pressed key\r
+                               ;\r
+\r
+                                       PUBLIC  SCAN_KEYBOARD\r
+\r
+ 0074                          SCAN_KEYBOARD   PROC    FAR\r
+\r
+                                       PUSHx   BP, DS, SI, DI          ; Preserve Important Registers\r
+ 0074  55                   1                  push    BP                              ; Save R1\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/03/14 12:38:18\r
+c_utils.asm                                                 Page 2 - 1\r
+\r
+\r
+ 0075  1E                   2                  push    DS                              ; Save R1\r
+ 0076  56                   3                  push    SI                              ; Save R1\r
+ 0077  57                   4                  push    DI                              ; Save R1\r
+\r
+ 0078  B4 01                           mov             AH, 01H                         ; Function #1\r
+ 007A  CD 16                           INT             16H                                     ; Call Keyboard Driver\r
+ 007C  74 0C                           JZ              @SK_NO_KEY                      ; Exit if Zero flag set\r
+\r
+ 007E  B4 00                           mov             AH,     00H                             ; Remove Key from Buffer\r
+ 0080  CD 16                           INT             16H                                     ; Get Keycode in AX\r
+\r
+ 0082  0A C0                           OR              AL, AL                          ; Low Byte Set (Ascii?)\r
+ 0084  74 06                           JZ              @SK_Exit                        ; if not, it's a F-Key\r
+\r
+                                       CLR             AH                                      ; Clear ScanCode if Ascii\r
+ 0086  32 E4                1          xor             AH, AH          ; Set Register = 0\r
+ 0088  EB 02                           JMP             s @SK_Exit                      ; Return Key in AX\r
+\r
+ 008A                          @SK_NO_KEY:\r
+                                       CLR             AX                                      ; Return Nil (no Keypress)\r
+ 008A  33 C0                1          xor             AX, AX          ; Set Register = 0\r
+\r
+ 008C                          @SK_Exit:\r
+ 008C  FC                              cld                                                     ; Reset Direction Flag          \r
+                                       POPx    DI, SI, DS, BP          ; Restore Saved Registers\r
+ 008D  5F                   1                  pop             DI                              ; Restore R1\r
+ 008E  5E                   2                  pop             SI                              ; Restore R1\r
+ 008F  1F                   3                  pop             DS                              ; Restore R1\r
+ 0090  5D                   4                  pop             BP                              ; Restore R1\r
+ 0091  CB                              ret                                                     ; Exit & Clean Up Stack\r
+\r
+ 0092                          SCAN_KEYBOARD   ENDP\r
+\r
+\r
+                               ;========================================\r
+                               ;int far pascal random_int (int MaxValue)\r
+                               ;========================================\r
+                               ;\r
+                               ; Returns a pseudo-random number in the range of (0.. MaxInt-1)\r
+                               ;\r
+\r
+\r
+                                       PUBLIC  RANDOM_INT\r
+\r
+ 0008                          RI_Stack        STRUC\r
+ 0000  0000                                                    DW      ?       ; BP\r
+ 0002  00000000                                                        DD      ?       ; Caller\r
+ 0006  0000                            RI_MaxVal       DW      ?       ; Maximum Value to Return + 1\r
+                               RI_Stack        ENDS\r
+\r
+\r
+ 0092                          RANDOM_INT      PROC    FAR\r
+\r
+ 0092  55                              push    BP                                      ; Preserve Important Registers\r
+ 0093  8B EC                           mov             BP, SP                          ; Set up Stack Frame\r
+\r
+                                       CLR             BX                                      ; BX is the data index\r
+ 0095  33 DB                1          xor             BX, BX          ; Set Register = 0\r
+                                       CLR             CX                              ; CX is the accumulator\r
+ 0097  33 C9                1          xor             CX, CX          ; Set Register = 0\r
+\r
+                               REPT 3\r
+                                       mov             AX, RND_Seed[BX]        ; load the initial seed\r
+                                       mul             RND_Mult[BX]            ; multiply it\r
+                                       div             RND_ModV[BX]            ; and obtain the Mod value\r
+                                       mov             RND_Seed[BX], DX        ; save that for the next time\r
+\r
+                                       add             CX, DX                          ; add it into the accumulator\r
+                                       inc             BX\r
+                                       inc             BX                      ; point to the next set of values\r
+                               ENDM\r
+ 0099  8B 87 0000 R         1          mov             AX, RND_Seed[BX]        ; load the initial seed\r
+ 009D  F7 A7 0006 R         1          mul             RND_Mult[BX]            ; multiply it\r
+ 00A1  F7 B7 000C R         1          div             RND_ModV[BX]            ; and obtain the Mod value\r
+ 00A5  89 97 0000 R         1          mov             RND_Seed[BX], DX        ; save that for the next time\r
+ 00A9  03 CA                1          add             CX, DX                          ; add it into the accumulator\r
+ 00AB  43                   1          inc             BX\r
+ 00AC  43                   1          inc             BX                      ; point to the next set of values\r
+ 00AD  8B 87 0000 R         1          mov             AX, RND_Seed[BX]        ; load the initial seed\r
+ 00B1  F7 A7 0006 R         1          mul             RND_Mult[BX]            ; multiply it\r
+ 00B5  F7 B7 000C R         1          div             RND_ModV[BX]            ; and obtain the Mod value\r
+ 00B9  89 97 0000 R         1          mov             RND_Seed[BX], DX        ; save that for the next time\r
+ 00BD  03 CA                1          add             CX, DX                          ; add it into the accumulator\r
+ 00BF  43                   1          inc             BX\r
+ 00C0  43                   1          inc             BX                      ; point to the next set of values\r
+ 00C1  8B 87 0000 R         1          mov             AX, RND_Seed[BX]        ; load the initial seed\r
+ 00C5  F7 A7 0006 R         1          mul             RND_Mult[BX]            ; multiply it\r
+ 00C9  F7 B7 000C R         1          div             RND_ModV[BX]            ; and obtain the Mod value\r
+ 00CD  89 97 0000 R         1          mov             RND_Seed[BX], DX        ; save that for the next time\r
+ 00D1  03 CA                1          add             CX, DX                          ; add it into the accumulator\r
+ 00D3  43                   1          inc             BX\r
+ 00D4  43                   1          inc             BX                      ; point to the next set of values\r
+\r
+ 00D5  8B C1                           mov             AX, CX                          ; AX = Random #\r
+                                       CLR             DX                                      ; DX = 0\r
+ 00D7  33 D2                1          xor             DX, DX          ; Set Register = 0\r
+ 00D9  F7 76 06                                div             [BP].RI_MaxVal          ; DX = DX:AX / MAxVal Remainder\r
+\r
+ 00DC  8B C2                           mov             AX, DX\r
+\r
+ 00DE  5D                              pop             BP                                      ; Restore BP\r
+ 00DF  CA 0002                         ret             2                               ; back to BASIC with AX holding the result\r
+\r
+ 00E2                          RANDOM_INT      ENDP\r
+\r
+\r
+                               ;==================================\r
+                               ;void far pascal init_random (void)\r
+                               ;==================================\r
+                               ;\r
+                               ; Scrambles the psuedo-random number sequence\r
+                               ; (XOR's the seed value with the timer)\r
+                               ;\r
+\r
+                                       PUBLIC  INIT_RANDOM\r
+\r
+ 00E2                          INIT_RANDOM     PROC    FAR\r
+\r
+                                       CLR             AX                                      ; Segment = 0000\r
+ 00E2  33 C0                1          xor             AX, AX          ; Set Register = 0\r
+ 00E4  8E C0                           mov             ES, AX\r
+ 00E6  26: A1 046C                     mov             AX, ES:[046Ch]      ; Get Timer Lo Word\r
+\r
+ 00EA  31 06 0000 R                    xor             RND_Seed, AX            ; Scramble 1st Seed\r
+\r
+ 00EE  CB                              ret                                                     ; Exit & Clean Up Stack\r
+\r
+ 00EF                          INIT_RANDOM     ENDP\r
+\r
+                               ;=========================================\r
+                               ;int far pascal int_sqr (int X, int Round)\r
+                               ;=========================================\r
+                               ;\r
+                               ; Returns the Integer Square Root of (X)\r
+                               ; Round allows the return value to be rounded to the \r
+                               ; nearest integer value by passing 0x80.  Passing 0\r
+                               ; return the Integer Portion only.  The rounding amound is\r
+                               ; a number from 0 to 1 multiplied by 256, thus \r
+                               ; 0.5 * 0x100 = 0x80!\r
+                               ;\r
+\r
+ 000C                          ISQ_Stack       STRUC\r
+ 0000  0000 0000                                                       DW      ?,?     ; BP, DI\r
+ 0004  00000000                                                                DD      ?       ; Caller\r
+ 0008  0000                            ISQ_Round               DW      ?       ; Amount to Round Result * 256\r
+ 000A  0000                            ISQ_X                   DW      ?       ; "X"\r
+                               ISQ_Stack       ENDS\r
+\r
+                                       PUBLIC  INT_SQR\r
+\r
+ 00EF                          INT_SQR         PROC    FAR\r
+\r
+                                   PUSHx   BP, DI                              ; Save BP\r
+ 00EF  55                   1                  push    BP                              ; Save R1\r
+ 00F0  57                   2                  push    DI                              ; Save R1\r
+ 00F1  8B EC                       mov     BP, SP                              ; Set up Stack Frame\r
+\r
+ 00F3  33 C0                           xor     AX, AX                          ; {xor eax,eax}\r
+ 00F5  33 D2                           xor     DX, DX                          ; {xor edx,edx}\r
+ 00F7  8B 7E 0A                                mov     DI, [BP].ISQ_X          ; {mov edi,x}\r
+\r
+ 00FA  B9 0010                         mov     CX, 16                          ; {mov cx, 32}\r
+\r
+ 00FD                          @ISQ_L:\r
+\r
+ 00FD  D1 E7                           shl     DI, 1                           ; {shl edi,1}\r
+ 00FF  D1 D2                           rcl     DX, 1                           ; {rcl edx,1}\r
+ 0101  D1 E7                           shl     DI, 1                           ; {shl edi,1}\r
+ 0103  D1 D2                           rcl     DX, 1                           ; {rcl edx,1}\r
+ 0105  D1 E0                           shl     AX, 1                           ; {shl eax,1}\r
+ 0107  8B D8                           mov     BX, AX                          ; {mov ebx,eax}\r
+ 0109  D1 E3                           shl     BX, 1                           ; {shl ebx,1}\r
+ 010B  43                              inc     BX                                      ; {inc ebx}\r
+ 010C  3B D3                           cmp     DX, BX                          ; {cmp edx,ebx}\r
+ 010E  7C 03                           jl              @ISQ_S\r
+\r
+ 0110  2B D3                           sub     DX, BX                          ; {sub edx,ebx}\r
+ 0112  40                              inc     AX                                      ; {inc eax}\r
+\r
+ 0113                          @ISQ_S: \r
+ 0113  E2 E8                           loop    @ISQ_L\r
+\r
+ 0115  03 46 08                                add     ax, [BP].ISQ_Round      ; {add eax,$00008000}  \r
+                                                                                               ; {*round* result in hi word: ie. +0\r
+                               .5}\r
+ 0118  C1 E8 08                                shr     ax, 8                           ; {shr eax,16}  {to ax (result)}\r
+\r
+                                       POPx    DI, BP                          ; Restore Registers     \r
+ 011B  5F                   1                  pop             DI                              ; Restore R1\r
+ 011C  5D                   2                  pop             BP                              ; Restore R1\r
+ 011D  CA 0004                         ret             4                                       ; Exit\r
+\r
+ 0120                          INT_SQR         ENDP\r
+\r
+                               ;=================================\r
+                               ;int far pascal timer_count (void)\r
+                               ;=================================\r
+                               ;\r
+                               ; Returns the current timer value as an integer/long integer\r
+                               ;\r
+\r
+                                       PUBLIC  TIMER_COUNT\r
+\r
+ 0120                          TIMER_COUNT      PROC    FAR\r
+\r
+                                       CLR             AX                                      ; Segment = 0000\r
+ 0120  33 C0                1          xor             AX, AX          ; Set Register = 0\r
+ 0122  8E C0                           mov             ES, AX\r
+ 0124  26: A1 046C                     mov             AX, ES:[046Ch]      ; Get Timer Lo Word\r
+ 0128  26: 8B 16 046E                  mov             DX, ES:[046Eh]          ; Get Timer Hi Word\r
+ 012D  CB                              ret                                                     ; Exit & Clean Up Stack\r
+\r
+ 012E                          TIMER_COUNT      ENDP\r
+\r
+\r
+                                       END\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/03/14 12:38:18\r
+c_utils.asm                                                 Symbols 3 - 1\r
+\r
+\r
+\r
+\r
+Macros:\r
+\r
+                N a m e                 Type\r
+\r
+CLR  . . . . . . . . . . . . . .       Proc\r
+LOOPjz . . . . . . . . . . . . .       Proc\r
+LOOPx  . . . . . . . . . . . . .       Proc\r
+POPx . . . . . . . . . . . . . .       Proc\r
+PUSHx  . . . . . . . . . . . . .       Proc\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/03/14 12:38:18\r
+c_utils.asm                                                 Symbols 4 - 1\r
+\r
+\r
+\r
+\r
+Structures and Unions:\r
+\r
+                N a m e                  Size\r
+                                         Offset      Type\r
+\r
+DP_Stack . . . . . . . . . . . .        0010\r
+  DP_Text  . . . . . . . . . . .        000C        DWord\r
+ISQ_Stack  . . . . . . . . . . .        000C\r
+  ISQ_Round  . . . . . . . . . .        0008        Word\r
+  ISQ_X  . . . . . . . . . . . .        000A        Word\r
+RI_Stack . . . . . . . . . . . .        0008\r
+  RI_MaxVal  . . . . . . . . . .        0006        Word\r
+SVM_Stack  . . . . . . . . . . .        000E\r
+  SVM_Mode . . . . . . . . . . .        000C        Byte\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/03/14 12:38:18\r
+c_utils.asm                                                 Symbols 5 - 1\r
+\r
+\r
+\r
+\r
+Segments and Groups:\r
+\r
+                N a m e                 Size     Length   Align   Combine Class\r
+\r
+C_UTILS_TEXT . . . . . . . . . .       16 Bit   012E     Word    Public  'CODE'        \r
+DGROUP . . . . . . . . . . . . .       GROUP\r
+_DATA  . . . . . . . . . . . . .       16 Bit   0014     Word    Public  'DATA'        \r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/03/14 12:38:18\r
+c_utils.asm                                                 Symbols 6 - 1\r
+\r
+\r
+\r
+\r
+Procedures,  parameters and locals:\r
+\r
+                N a m e                 Type     Value    Attr\r
+\r
+DOS_PRINTS . . . . . . . . . . .       P Far    0039     C_UTILS_TEXT  Length= 0027 Public\r
+DOS_PRINT  . . . . . . . . . . .       P Far    0000     C_UTILS_TEXT  Length= 0039 Public\r
+INIT_RANDOM  . . . . . . . . . .       P Far    00E2     C_UTILS_TEXT  Length= 000D Public\r
+INT_SQR  . . . . . . . . . . . .       P Far    00EF     C_UTILS_TEXT  Length= 0031 Public\r
+RANDOM_INT . . . . . . . . . . .       P Far    0092     C_UTILS_TEXT  Length= 0050 Public\r
+SCAN_KEYBOARD  . . . . . . . . .       P Far    0074     C_UTILS_TEXT  Length= 001E Public\r
+SET_VIDEO_MODE . . . . . . . . .       P Far    0060     C_UTILS_TEXT  Length= 0014 Public\r
+TIMER_COUNT  . . . . . . . . . .       P Far    0120     C_UTILS_TEXT  Length= 000E Public\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/03/14 12:38:18\r
+c_utils.asm                                                 Symbols 7 - 1\r
+\r
+\r
+\r
+\r
+Symbols:\r
+\r
+                N a m e                 Type     Value    Attr\r
+\r
+?x3  . . . . . . . . . . . . . .       Text     ?,?,?\r
+?x4  . . . . . . . . . . . . . .       Text     ?,?,?,?\r
+@@DPS_Got_len  . . . . . . . . .       L Near   004F     C_UTILS_TEXT  \r
+@@DPS_Scan_it  . . . . . . . . .       L Near   0046     C_UTILS_TEXT  \r
+@@DP_Got_len . . . . . . . . . .       L Near   0016     C_UTILS_TEXT  \r
+@@DP_Scan_it . . . . . . . . . .       L Near   000D     C_UTILS_TEXT  \r
+@CodeSize  . . . . . . . . . . .       Number   0001h   \r
+@DPS_Exit  . . . . . . . . . . .       L Near   0058     C_UTILS_TEXT  \r
+@DataSize  . . . . . . . . . . .       Number   0000h   \r
+@ISQ_L . . . . . . . . . . . . .       L Near   00FD     C_UTILS_TEXT  \r
+@ISQ_S . . . . . . . . . . . . .       L Near   0113     C_UTILS_TEXT  \r
+@Interface . . . . . . . . . . .       Number   0000h   \r
+@Model . . . . . . . . . . . . .       Number   0004h   \r
+@No_Print  . . . . . . . . . . .       L Near   001F     C_UTILS_TEXT  \r
+@SK_Exit . . . . . . . . . . . .       L Near   008C     C_UTILS_TEXT  \r
+@SK_NO_KEY . . . . . . . . . . .       L Near   008A     C_UTILS_TEXT  \r
+@SVM_Exit  . . . . . . . . . . .       L Near   006D     C_UTILS_TEXT  \r
+@code  . . . . . . . . . . . . .       Text     C_UTILS_TEXT\r
+@data  . . . . . . . . . . . . .       Text     DGROUP\r
+@fardata?  . . . . . . . . . . .       Text     FAR_BSS\r
+@fardata . . . . . . . . . . . .       Text     FAR_DATA\r
+@stack . . . . . . . . . . . . .       Text     DGROUP\r
+CR_LF  . . . . . . . . . . . . .       Byte     0012     _DATA \r
+False  . . . . . . . . . . . . .       Number   0000h   \r
+RND_ModV . . . . . . . . . . . .       Word     000C     _DATA \r
+RND_Mult . . . . . . . . . . . .       Word     0006     _DATA \r
+RND_Seed . . . . . . . . . . . .       Word     0000     _DATA \r
+True . . . . . . . . . . . . . .       Number   -0001h   \r
+b  . . . . . . . . . . . . . . .       Text     BYTE PTR\r
+d  . . . . . . . . . . . . . . .       Text     DWORD PTR\r
+f  . . . . . . . . . . . . . . .       Text     FAR PTR\r
+nil  . . . . . . . . . . . . . .       Number   0000h   \r
+o  . . . . . . . . . . . . . . .       Text     OFFSET\r
+s  . . . . . . . . . . . . . . .       Text     SHORT\r
+w  . . . . . . . . . . . . . . .       Text     WORD PTR\r
+\r
+          0 Warnings\r
+          0 Errors\r
diff --git a/src/lib/modex/c_utils.sbr b/src/lib/modex/c_utils.sbr
new file mode 100755 (executable)
index 0000000..0301171
Binary files /dev/null and b/src/lib/modex/c_utils.sbr differ
diff --git a/src/lib/modex/demos/basic7/chardemo.bas b/src/lib/modex/demos/basic7/chardemo.bas
new file mode 100755 (executable)
index 0000000..627e327
--- /dev/null
@@ -0,0 +1,164 @@
+DEFINT A-Z\r
+DECLARE SUB PRINT.STRING (Text$, Xpos%, Ypos%, Colour%)\r
+DECLARE FUNCTION MakePal$ (Red%, Green%, Blue%)\r
+DECLARE SUB LOAD.FONT (FontFile$, FontNum%)\r
+DECLARE SUB ERROR.OUT (Text$)\r
+\r
+       REM $INCLUDE: 'MODEX.BI'\r
+\r
+       REM $INCLUDE: 'UTILS.BI'\r
+\r
+TYPE FONT\r
+       SetData AS STRING * 1024\r
+END TYPE\r
+\r
+\r
+TYPE VGAPalette\r
+       PalData AS STRING * 768\r
+END TYPE\r
+\r
+\r
+       ' Alternate form of LOAD_DAC_REGISTERS so we can pass an offset into\r
+       ' a String instead of the Address of the String\r
+\r
+DECLARE SUB LOAD.DACS ALIAS "LOAD_DAC_REGISTERS" (BYVAL Addr&, BYVAL StartReg%, BYVAL EndReg%, BYVAL VSync%)\r
+\r
+\r
+       '\r
+       'MODE X DEMO of Multiple Character Sets and Block Color Cycling\r
+       '\r
+       'By Matt Pritchard\r
+       '\r
+\r
+COMMON SHARED CharSet() AS FONT\r
+\r
+DIM Pal AS VGAPalette\r
+\r
+       REM $DYNAMIC\r
+\r
+DIM SHARED CharSet(0 TO 3) AS FONT\r
+\r
+\r
+       LOAD.FONT "SYSTEM.FNT", 0\r
+       LOAD.FONT "ROM_8x8.FNT", 1\r
+       LOAD.FONT "SPACEAGE.FNT", 2\r
+\r
+\r
+       IF SET.MODEX(Mode320x240) = False THEN\r
+               ERROR.OUT "ERROR SETTING MODE X"\r
+       END IF\r
+\r
+\r
+       A$ = "": B$ = ""\r
+       FOR X = 0 TO 31: A$ = A$ + MakePal$(31 - X, X, 0): NEXT X\r
+       FOR X = 0 TO 31: A$ = A$ + MakePal$(0, 31 - X, X): NEXT X\r
+       FOR X = 0 TO 31: A$ = A$ + MakePal$(X, 0, 31 - X): NEXT X\r
+   \r
+       FOR X = 0 TO 31: B$ = B$ + MakePal$(31 - X, X, X): NEXT X\r
+       FOR X = 0 TO 31: B$ = B$ + MakePal$(X, 31 - X, X): NEXT X\r
+       FOR X = 0 TO 31: B$ = B$ + MakePal$(X, X, 31 - X): NEXT X\r
+\r
+       Black$ = STRING$(192, 0)\r
+       White$ = STRING$(128 * 3, 48)\r
+\r
+       Pal1$ = Black$ + A$ + A$ + B$ + B$ + A$\r
+\r
+       LOAD.DACS SSEGADD(Black$), 64, 127, 1\r
+       LOAD.DACS SSEGADD(Black$), 20, 63, 0\r
+\r
+       LOAD.DACS SSEGADD(White$), 128, 255, 0\r
+\r
+       '*** Background ***\r
+\r
+       FOR X = 0 TO 319\r
+               FOR Y = 0 TO 239\r
+                  IF ((X + Y) AND 1) = 1 THEN SET.POINT X, Y, 64 + X \ 5 ELSE SET.POINT X, Y, 20 + Y \ 6\r
+               NEXT Y\r
+       NEXT X\r
+\r
+       '*** Draw Font Displays ***\r
+\r
+       PRINT.STRING "FONT: SYSTEM.FNT", 11, 7, 15\r
+       PRINT.STRING "FONT: ROM_8x8.FNT", 11, 17, 15\r
+       PRINT.STRING "FONT: SPACEAGE.FNT", 11, 27, 15\r
+       PRINT.STRING "PRESS ANY KEY TO CONTINUE", 8, 29, 14\r
+       \r
+\r
+       FOR F = 0 TO 2\r
+               SET.DISPLAY.FONT CharSet(F), 1\r
+               Yp = F * 80 + 10\r
+               FOR Y = 0 TO 96 STEP 32\r
+                       FOR X = 0 TO 31\r
+                               TGPRINTC 128 + Y + X, X * 10 + 1, Yp, 128 + Y\r
+                       NEXT X\r
+               Yp = Yp + 10\r
+               NEXT Y\r
+       NEXT F\r
+\r
+       DO\r
+       LOOP UNTIL SCAN.KEYBOARD\r
+\r
+       Offset = 0\r
+       Restart = 192\r
+       MaxOfs = 192 + 96 * 6\r
+\r
+       Delay = 100\r
+\r
+       Offset2 = 0\r
+       Offset2Dir = 3\r
+       Offset2Min = 192\r
+       Offset2Max = Offset2Min + 192 * 6\r
+\r
+       DO\r
+               LOAD.DACS SSEGADD(Pal1$) + Offset, 64, 127, 1\r
+               Offset = Offset + 3\r
+               IF Offset >= MaxOfs THEN Offset = Restart\r
+               IF Delay THEN\r
+                       Delay = Delay - 1\r
+               ELSE\r
+                       LOAD.DACS SSEGADD(Pal1$) + Offset2, 20, 60, 0\r
+                       IF Offset2 = Offset2Max THEN Offset2Dir = -3\r
+                       IF Offset2 = Offset2Min THEN Offset2Dir = 3\r
+                       Offset2 = Offset2 + Offset2Dir\r
+               END IF\r
+\r
+       LOOP UNTIL SCAN.KEYBOARD\r
+\r
+       ERROR.OUT "DEMO OVER"\r
+\r
+REM $STATIC\r
+SUB ERROR.OUT (Text$)\r
+\r
+       SET.VIDEO.MODE 3\r
+\r
+       DOS.PRINT Text$\r
+\r
+       END\r
+\r
+END SUB\r
+\r
+SUB LOAD.FONT (FontFile$, FontNum) STATIC\r
+\r
+       IF LEN(DIR$(FontFile$)) = 0 THEN ERROR.OUT "FILE NOT FOUND: " + FontFile$\r
+\r
+       OPEN FontFile$ FOR BINARY AS #1\r
+\r
+               SEEK #1, 1\r
+               GET #1, , CharSet(FontNum)\r
+\r
+       CLOSE #1\r
+\r
+END SUB\r
+\r
+FUNCTION MakePal$ (Red, Green, Blue) STATIC\r
+\r
+       MakePal$ = CHR$(Red) + CHR$(Green) + CHR$(Blue)\r
+\r
+END FUNCTION\r
+\r
+SUB PRINT.STRING (Text$, Xpos, Ypos, Colour)\r
+\r
+       TPRINT.STR SSEG(Text$), SADD(Text$), LEN(Text$), Xpos * 8, Ypos * 8, Colour\r
+\r
+END SUB\r
+\r
diff --git a/src/lib/modex/demos/basic7/make-lib.bat b/src/lib/modex/demos/basic7/make-lib.bat
new file mode 100755 (executable)
index 0000000..fc0b3b5
--- /dev/null
@@ -0,0 +1,5 @@
+ECHO ... Building MODEX.QLB for BASIC PDS 7.1\r
+LIB MODEX -+MODEX,,\r
+LIB MODEX -+UTILS,,\r
+DEL MODEX.BAK\r
+LINK /Q MODEX+UTILS, MODEX.QLB, NUL, C:\BC7\LIB\QBXQLB.LIB;\1a\r
diff --git a/src/lib/modex/demos/basic7/modex.bi b/src/lib/modex/demos/basic7/modex.bi
new file mode 100755 (executable)
index 0000000..6b1d7af
--- /dev/null
@@ -0,0 +1,63 @@
\r
+    ' ===== SCREEN RESOLUTIONS =====\r
\r
+CONST Mode320x200 = 0, Mode320x400 = 1\r
+CONST Mode360x200 = 2, Mode360x400 = 3\r
+CONST Mode320x240 = 4, Mode320x480 = 5\r
+CONST Mode360x240 = 6, Mode360x480 = 7\r
\r
+    ' ===== MODE X SETUP ROUTINES =====\r
\r
+DECLARE FUNCTION SET.VGA.MODEX% ALIAS "SET_VGA_MODEX" (BYVAL ModeType%, BYVAL MaxXpos%, BYVAL MaxYpos%, BYVAL Pages%)\r
+DECLARE FUNCTION SET.MODEX% ALIAS "SET_MODEX" (BYVAL Mode%)\r
\r
+    ' ===== BASIC GRAPHICS PRIMITIVES =====\r
\r
+DECLARE SUB CLEAR.VGA.SCREEN ALIAS "CLEAR_VGA_SCREEN" (BYVAL ColorNum%)\r
+DECLARE SUB SET.POINT ALIAS "SET_POINT" (BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorNum%)\r
+DECLARE FUNCTION READ.POINT% ALIAS "READ_POINT" (BYVAL Xpos%, BYVAL Ypos%)\r
+DECLARE SUB FILL.BLOCK ALIAS "FILL_BLOCK" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
+DECLARE SUB DRAW.LINE ALIAS "DRAW_LINE" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
\r
+    ' ===== DAC COLOR REGISTER ROUTINES =====\r
\r
+DECLARE SUB SET.DAC.REGISTER ALIAS "SET_DAC_REGISTER" (BYVAL RegNo%, BYVAL Red%, BYVAL Green%, BYVAL Blue%)\r
+DECLARE SUB GET.DAC.REGISTER ALIAS "GET_DAC_REGISTER" (BYVAL RegNo%, Red%, Green%, Blue%)\r
+DECLARE SUB LOAD.DAC.REGISTERS ALIAS "LOAD_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%, BYVAL VSync%)\r
+DECLARE SUB READ.DAC.REGISTERS ALIAS "READ_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%)\r
\r
\r
+    ' ===== PAGE FLIPPING AND SCROLLING ROUTINES =====\r
\r
+DECLARE SUB SET.ACTIVE.PAGE ALIAS "SET_ACTIVE_PAGE" (BYVAL PageNo%)\r
+DECLARE FUNCTION GET.ACTIVE.PAGE% ALIAS "GET_ACTIVE_PAGE"\r
+DECLARE SUB SET.DISPLAY.PAGE ALIAS "SET_DISPLAY_PAGE" (BYVAL PageNo%)\r
+DECLARE FUNCTION GET.DISPLAY.PAGE% ALIAS "GET_DISPLAY_PAGE"\r
+DECLARE SUB SET.WINDOW ALIAS "SET_WINDOW" (BYVAL DisplayPage%, BYVAL XOffset%, BYVAL YOffset%)\r
+DECLARE FUNCTION GET.X.OFFSET% ALIAS "GET_X_OFFSET" ()\r
+DECLARE FUNCTION GET.Y.OFFSET% ALIAS "GET_Y_OFFSET" ()\r
+DECLARE SUB SYNC.DISPLAY ALIAS "SYNC_DISPLAY"\r
\r
+    ' ===== TEXT DISPLAY ROUTINES =====\r
\r
+DECLARE SUB GPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
+DECLARE SUB TGPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
+DECLARE SUB PRINT.STR ALIAS "PRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
+DECLARE SUB TPRINT.STR ALIAS "TPRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
+DECLARE SUB SET.DISPLAY.FONT ALIAS "SET_DISPLAY_FONT" (SEG FontData AS ANY, BYVAL FontNumber%)\r
\r
+    ' ===== BITMAP (SPRITE) DISPLAY ROUTINES =====\r
\r
+DECLARE SUB DRAW.BITMAP ALIAS "DRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
+DECLARE SUB TDRAW.BITMAP ALIAS "TDRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
\r
+    ' ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====\r
\r
+DECLARE SUB COPY.PAGE ALIAS "COPY_PAGE" (BYVAL SourcePage%, BYVAL DestPage%)\r
+DECLARE SUB COPY.BITMAP ALIAS "COPY_BITMAP" (BYVAL SourcePage%, BYVAL X1%, BYVAL Y1%, BYVAL X2%, BYVAL Y2%, BYVAL DestPage%, BYVAL DestX1%, BYVAL DestY1%)\r
\r
\r
\r
\r
\r
\r
diff --git a/src/lib/modex/demos/basic7/modex.qlb b/src/lib/modex/demos/basic7/modex.qlb
new file mode 100755 (executable)
index 0000000..70d22db
Binary files /dev/null and b/src/lib/modex/demos/basic7/modex.qlb differ
diff --git a/src/lib/modex/demos/basic7/test6.bas b/src/lib/modex/demos/basic7/test6.bas
new file mode 100755 (executable)
index 0000000..220a67b
--- /dev/null
@@ -0,0 +1,562 @@
+'File:     TEST6.BAS\r
+'Descp.:   A Mode "X" demonstration\r
+'Author:   Matt Pritchard\r
+'Date:     14 April, 1993\r
+'\r
+DECLARE SUB DEMO.RES (Mode%, Xmax%, Ymax%)\r
+DECLARE SUB ERROR.OUT (Message$)\r
+DECLARE FUNCTION GET.KEY% ()\r
+DECLARE SUB LOAD.SHAPES ()\r
+DECLARE SUB PAGE.DEMO ()\r
+DECLARE SUB PRINT.TEXT (Text$, Xpos%, Ypos%, ColorF%, ColorB%)\r
+DECLARE SUB TPRINT.TEXT (Text$, Xpos%, Ypos%, ColorF%)\r
+DEFINT A-Z\r
+\r
+\r
+TYPE ShapeType\r
+       ImgData AS STRING * 512\r
+       xWidth  AS INTEGER\r
+       yWidth  AS INTEGER\r
+END TYPE\r
+\r
+TYPE Sprite\r
+       Xpos    AS INTEGER\r
+       Ypos    AS INTEGER\r
+       XDir    AS INTEGER\r
+       YDir    AS INTEGER\r
+       Shape   AS INTEGER\r
+END TYPE\r
+\r
+\r
+CONST MaxShapes = 32\r
+\r
+       REM $INCLUDE: 'UTILS.BI'\r
+       REM $INCLUDE: 'MODEX.BI'\r
+\r
+DIM SHARED Img(32) AS ShapeType\r
+COMMON SHARED Img() AS ShapeType\r
+\r
+\r
+       CALL INIT.RANDOM\r
+\r
+       CALL LOAD.SHAPES\r
+\r
+       CALL DEMO.RES(Mode320x200, 320, 200)\r
+       CALL DEMO.RES(Mode320x400, 320, 400)\r
+\r
+       CALL DEMO.RES(Mode360x200, 360, 200)\r
+       CALL DEMO.RES(Mode360x400, 360, 400)\r
+\r
+       CALL DEMO.RES(Mode320x240, 320, 240)\r
+       CALL DEMO.RES(Mode320x480, 320, 480)\r
+\r
+       CALL DEMO.RES(Mode360x240, 360, 240)\r
+       CALL DEMO.RES(Mode360x480, 360, 480)\r
+\r
+       CALL PAGE.DEMO\r
+\r
+       SET.VIDEO.MODE 3\r
+       DOS.PRINT "THIS MODE X DEMO IS FINISHED"\r
+       END\r
+\r
+SUB DEMO.RES (Mode, Xmax, Ymax)\r
+\r
+       IF SET.MODEX%(Mode) = 0 THEN\r
+               ERROR.OUT "Unable to SET_MODEX" + STR$(Mode)\r
+       END IF\r
+\r
+       XCenter = Xmax \ 2\r
+       \r
+       X1 = 10\r
+       Y1 = 10\r
+       X2 = Xmax - 1\r
+       Y2 = Ymax - 1\r
+\r
+       FOR Z = 0 TO 3\r
+               Colr = 31 - Z * 2\r
+               DRAW.LINE X1 + Z, Y1 + Z, X2 - Z, Y1 + Z, Colr\r
+               DRAW.LINE X1 + Z, Y1 + Z, X1 + Z, Y2 - Z, Colr\r
+               DRAW.LINE X1 + Z, Y2 - Z, X2 - Z, Y2 - Z, Colr\r
+               DRAW.LINE X2 - Z, Y1 + Z, X2 - Z, Y2 - Z, Colr\r
+       NEXT Z\r
+\r
+       XChars = Xmax \ 10\r
+       YChars = Ymax \ 10\r
+\r
+       FOR X = 0 TO XChars - 1\r
+               TGPRINTC 48 + ((X + 1) MOD 10), X * 10 + 1, 1, 9 + ((X \ 8) MOD 7)\r
+               DRAW.LINE X * 10 + 9, 0, X * 10 + 9, 3, 15\r
+       NEXT X\r
+\r
+       FOR Y = 0 TO YChars - 1\r
+               TGPRINTC 48 + ((Y + 1) MOD 10), 1, Y * 10 + 1, 9 + ((Y \ 10) MOD 7)\r
+               DRAW.LINE 0, Y * 10 + 9, 3, Y * 10 + 9, 15\r
+       NEXT Y\r
+\r
+       ' Draw Lines\r
+\r
+       FOR X = 0 TO 63\r
+               N = 15 + X * .75\r
+               SET.DAC.REGISTER 64 + X, N, N, N\r
+               SET.DAC.REGISTER 128 + X, 0, N, N\r
+\r
+               DRAW.LINE 103 - X, 60, 40 + X, 123, 64 + X\r
+               DRAW.LINE 40, 60 + X, 103, 123 - X, 128 + X\r
+\r
+       NEXT X\r
+       TPRINT.TEXT "LINE TEST", 37, 130, c.BLUE\r
+\r
+       Y = 60: Gap = 0\r
+       FOR X = 0 TO 9\r
+               FILL.BLOCK 120, Y, 120 + X, Y + Gap, 64 + X\r
+               FILL.BLOCK 140 - (15 - X), Y, 150 + X, Y + Gap, 230 + X\r
+               FILL.BLOCK 170 - (15 - X), Y, 170, Y + Gap, 128 + X\r
+               Y = Y + Gap + 2\r
+               Gap = Gap + 1\r
+       NEXT X\r
+       TPRINT.TEXT "FILL TEST", 110, 46, c.GREEN\r
+\r
+\r
+       FOR X = 190 TO 250 STEP 2\r
+          FOR Y = 60 TO 122 STEP 2\r
+                 SET.POINT X, Y, X + Y + X + Y\r
+          NEXT Y\r
+       NEXT X\r
+\r
+       TPRINT.TEXT "PIXEL TEST", 182, 130, c.RED\r
+\r
+       FOR X = 190 TO 250 STEP 2\r
+          FOR Y = 60 TO 122 STEP 2\r
+                 IF READ.POINT(X, Y) <> ((X + Y + X + Y) AND 255) THEN\r
+                        ERROR.OUT "READ.PIXEL Failure"\r
+                 END IF\r
+          NEXT Y\r
+       NEXT X\r
+\r
+\r
+\r
+       Msg$ = " This is a MODE X demo "\r
+       PRINT.TEXT Msg$, XCenter - (LEN(Msg$) * 4), 20, c.bRED, c.BLUE\r
+       Msg$ = "Screen Resolution is     by    "\r
+       Xp = XCenter - (LEN(Msg$) * 4)\r
+       PRINT.TEXT Msg$, Xp, 30, c.bGREEN, c.BLACK\r
+\r
+       PRINT.TEXT LTRIM$(STR$(Xmax)), Xp + 8 * 21, 30, c.bPURPLE, c.BLACK\r
+       PRINT.TEXT LTRIM$(STR$(Ymax)), Xp + 8 * 28, 30, c.bWHITE, c.BLACK\r
+\r
+       FOR X = 0 TO 15\r
+               SET.DAC.REGISTER 230 + X, 63 - X * 4, 0, 15 + X * 3\r
+               DRAW.LINE 30 + X, Ymax - 6 - X, Xmax - 20 - X, Ymax - 6 - X, 230 + X\r
+       NEXT X\r
+       TPRINT.TEXT "Press <ANY KEY> to Continue", XCenter - (26 * 4), Ymax - 18, c.YELLOW\r
+\r
+       X = GET.KEY%\r
+       IF X = KyESC THEN ERROR.OUT "ABORT"\r
+\r
+END SUB\r
+\r
+SUB ERROR.OUT (Message$)\r
+\r
+       SET.VIDEO.MODE 3\r
+       DOS.PRINT Message$\r
+       END\r
+\r
+END SUB\r
+\r
+FUNCTION GET.KEY%\r
+\r
+       DO\r
+               X = SCAN.KEYBOARD\r
+       LOOP UNTIL X\r
+\r
+       GET.KEY% = X\r
+\r
+END FUNCTION\r
+\r
+SUB LOAD.SHAPES\r
+\r
+DIM Grid(1 TO 32, 1 TO 32)\r
+\r
+       FOR Shape = 0 TO MaxShapes - 1\r
+\r
+               FOR Y = 1 TO 32\r
+               FOR X = 1 TO 32\r
+                       Grid(X, Y) = 0\r
+               NEXT X\r
+               NEXT Y\r
+\r
+               Style = RANDOM.INT(6)\r
+               Colour = 1 + RANDOM.INT(15)\r
+               \r
+               SELECT CASE Style\r
+\r
+               CASE 0:         ' Solid Box\r
+\r
+                       DO\r
+                               xWidth = 3 + RANDOM.INT(30)\r
+                               yWidth = 3 + RANDOM.INT(30)\r
+                       LOOP UNTIL ((xWidth * yWidth) <= 512)\r
+\r
+                       FOR Y = 1 TO yWidth\r
+                               FOR X = 1 TO xWidth\r
+                                       Grid(X, Y) = Colour\r
+                               NEXT X\r
+                       NEXT Y\r
+\r
+               CASE 1:         ' Hollow Box\r
+\r
+                       DO\r
+                               xWidth = 5 + RANDOM.INT(28)\r
+                               yWidth = 5 + RANDOM.INT(28)\r
+                       LOOP UNTIL ((xWidth * yWidth) <= 512)\r
+\r
+                       FOR Y = 1 TO yWidth\r
+                               FOR X = 1 TO xWidth\r
+                                       Grid(X, Y) = Colour\r
+                               NEXT X\r
+                       NEXT Y\r
+\r
+                       HollowX = 1 + RANDOM.INT(xWidth \ 2 - 1)\r
+                       HollowY = 1 + RANDOM.INT(yWidth \ 2 - 1)\r
+\r
+                       FOR Y = HollowY + 1 TO yWidth - HollowY\r
+                               FOR X = HollowX + 1 TO xWidth - HollowX\r
+                                       Grid(X, Y) = nil\r
+                               NEXT X\r
+                       NEXT Y\r
+\r
+               CASE 2:         ' Solid Diamond\r
+\r
+                       xWidth = 3 + 2 * RANDOM.INT(10)\r
+                       yWidth = xWidth\r
+                       Centre = xWidth \ 2\r
+\r
+                       FOR Y = 0 TO Centre\r
+                               FOR X = 0 TO Y\r
+                                       Grid(Centre - X + 1, Y + 1) = Colour\r
+                                       Grid(Centre + X + 1, Y + 1) = Colour\r
+                                       Grid(Centre - X + 1, yWidth - Y) = Colour\r
+                                       Grid(Centre + X + 1, yWidth - Y) = Colour\r
+                               NEXT X\r
+                       NEXT Y\r
+\r
+\r
+               CASE 3:         ' Hollow Diamond\r
+\r
+\r
+                       xWidth = 3 + 2 * RANDOM.INT(10)\r
+                       yWidth = xWidth\r
+                       Centre = xWidth \ 2\r
+                       sWidth = RANDOM.INT(Centre)\r
+\r
+                       FOR Y = 0 TO Centre\r
+                               FOR X = 0 TO Y\r
+                                       IF X + (Centre - Y) >= sWidth THEN\r
+                                               Grid(Centre - X + 1, Y + 1) = Colour\r
+                                               Grid(Centre + X + 1, Y + 1) = Colour\r
+                                               Grid(Centre - X + 1, yWidth - Y) = Colour\r
+                                               Grid(Centre + X + 1, yWidth - Y) = Colour\r
+                                       END IF\r
+                               NEXT X\r
+                       NEXT Y\r
+\r
+               CASE 4:         ' Ball\r
+\r
+                       xWidth = 7 + 2 * RANDOM.INT(8)\r
+                       yWidth = xWidth\r
+                       Centre = 1 + xWidth \ 2\r
+\r
+                       FOR Y = 1 TO yWidth\r
+                               FOR X = 1 TO xWidth\r
+                                       D = SQR(((Centre - X) * (Centre - X)) + ((Centre - Y) * (Centre - Y)))\r
+                                       IF D < Centre THEN Grid(X, Y) = 150 + Colour * 2 + D * 3\r
+                               NEXT X\r
+                       NEXT Y\r
+\r
+               CASE 5:         ' Ball\r
+\r
+\r
+                       xWidth = 7 + 2 * RANDOM.INT(8)\r
+                       yWidth = xWidth\r
+                       Centre = 1 + xWidth \ 2\r
+                       sWidth = RANDOM.INT(xWidth)\r
+\r
+                       FOR Y = 1 TO yWidth\r
+                               FOR X = 1 TO xWidth\r
+                                       D = SQR(((Centre - X) * (Centre - X)) + ((Centre - Y) * (Centre - Y)))\r
+                                       IF D < Centre AND D >= sWidth THEN Grid(X, Y) = 150 + Colour * 2 + D * 3\r
+                               NEXT X\r
+                       NEXT Y\r
+\r
+               END SELECT\r
+\r
+               Img(Shape).xWidth = xWidth\r
+               Img(Shape).yWidth = yWidth\r
+\r
+               A$ = STRING$(xWidth * yWidth, nil)\r
+\r
+               c = 1\r
+               FOR Y = 1 TO yWidth\r
+                       FOR X = 1 TO xWidth\r
+                               MID$(A$, c, 1) = CHR$(Grid(X, Y))\r
+                               c = c + 1\r
+                       NEXT X\r
+               NEXT Y\r
+\r
+               Img(Shape).ImgData = A$\r
+               \r
+\r
+       NEXT Shape\r
+\r
+END SUB\r
+\r
+SUB PAGE.DEMO\r
+\r
+CONST MaxSprites = 64\r
+\r
+DIM Obj(MaxSprites) AS Sprite\r
+DIM LastX(MaxSprites, 1), LastY(MaxSprites, 1)\r
+DIM LastObjects(1)\r
+\r
+       ScreenX = 360: ScreenY = 240\r
+\r
+       IF SET.VGA.MODEX%(Mode320x200, ScreenX, ScreenY, 3) = 0 THEN\r
+               ERROR.OUT "Unable to SET_VGA_MODEX" + STR$(Mode)\r
+       END IF\r
+\r
+       SET.ACTIVE.PAGE 0\r
+\r
+       CLEAR.VGA.SCREEN c.BLACK\r
+                          \r
+       PRINT.TEXT "This is a Test of the Following Functions:", 10, 9, c.bWHITE, c.BLACK\r
+\r
+       DRAW.LINE 10, 18, 350, 18, c.YELLOW\r
+       PRINT.TEXT "SET_ACTIVE_PAGE", 10, 20, c.bBLUE, c.BLACK\r
+       PRINT.TEXT "SET_DISPLAY_PAGE", 10, 30, c.GREEN, c.BLACK\r
+       PRINT.TEXT "SET_DAC_REGISTER", 10, 40, c.RED, c.BLACK\r
+       PRINT.TEXT "CLEAR_VGA_SCREEN", 10, 50, c.CYAN, c.BLACK\r
+\r
+       PRINT.TEXT "TDRAW_BITMAP", 10, 60, c.PURPLE, c.BLACK\r
+       PRINT.TEXT "COPY_PAGE", 10, 70, c.GREEN, c.BLACK\r
+       PRINT.TEXT "COPY_BITMAP", 10, 80, c.CYAN, c.BLACK\r
+\r
+       PRINT.TEXT "GPRINTC", 10, 90, c.BLUE, c.BLACK\r
+       PRINT.TEXT "TGPRINTC", 10, 100, c.GREEN, c.BLACK\r
+       PRINT.TEXT "SET_WINDOW", 10, 110, c.RED, c.BLACK\r
+\r
+       PRINT.TEXT "VIRTUAL SCREEN SIZES", 190, 20, c.bBLUE, c.BLACK\r
+       PRINT.TEXT "    SMOOTH SCROLLING", 190, 30, c.GREEN, c.BLACK\r
+       PRINT.TEXT "    SPRITE ANIMATION", 190, 40, c.CYAN, c.BLACK\r
+       PRINT.TEXT "       PAGE FLIPPING", 190, 50, c.RED, c.BLACK\r
+       PRINT.TEXT "       COLOR CYCLING", 190, 60, c.PURPLE, c.BLACK\r
+\r
+\r
+       FOR X = 0 TO 60\r
+               SET.DAC.REGISTER 50 + X, 3 + X, 0, 60 - X\r
+               SET.DAC.REGISTER 150 + X, 3 + X, 0, 60 - X\r
+       NEXT X\r
+\r
+       c = 0: DC = 1\r
+       FOR X = 0 TO ScreenX \ 2\r
+               DRAW.LINE ScreenX \ 2 - 1, ScreenY \ 4, X, ScreenY - 1, c + 50\r
+               DRAW.LINE ScreenX \ 2, ScreenY \ 4, ScreenX - X - 1, ScreenY - 1, c + 50\r
+               c = c + DC\r
+               IF c = 0 OR c = 60 THEN DC = -DC\r
+       NEXT X\r
+                               \r
+       TPRINT.TEXT "Press <ANY KEY> to Continue", 72, 190, c.bWHITE\r
+       TPRINT.TEXT "< > = Faster   < > = Slower", 72, 204, c.bGREEN\r
+       TPRINT.TEXT "< > = Fewer Shapes  < > = More Shapes", 32, 218, c.bCYAN\r
+\r
+       TGPRINTC 43, 80, 204, c.YELLOW\r
+       TGPRINTC 45, 200, 204, c.YELLOW\r
+\r
+       TGPRINTC 25, 40, 218, c.YELLOW\r
+       TGPRINTC 24, 200, 218, c.YELLOW\r
+\r
+       COPY.PAGE 0, 1\r
+       COPY.PAGE 0, 2\r
+\r
+       FOR X = 1 TO MaxSprites\r
+               DO\r
+                       Obj(X).XDir = RANDOM.INT(7) - 3\r
+                       Obj(X).YDir = RANDOM.INT(7) - 3\r
+               LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0)\r
+\r
+               Obj(X).Shape = X MOD MaxShapes\r
+\r
+               SpriteX = Img(Obj(X).Shape).xWidth\r
+               SpriteY = Img(Obj(X).Shape).yWidth\r
+\r
+               Obj(X).Xpos = 1 + RANDOM.INT(ScreenX - SpriteX - 2)\r
+               Obj(X).Ypos = 1 + RANDOM.INT(ScreenY - SpriteY - 2)\r
+\r
+               LastX(X, 0) = Obj(X).Xpos\r
+               LastX(X, 1) = Obj(X).Xpos\r
+               LastY(X, 0) = Obj(X).Ypos\r
+               LastY(X, 1) = Obj(X).Ypos\r
+       NEXT X\r
+\r
+       CurrentPage = 0\r
+\r
+       'View Shift...\r
+\r
+       ViewX = 0\r
+       ViewY = 0\r
+       ViewMax = 3\r
+       ViewCnt = 0\r
+       ViewXD = 1\r
+       ViewYD = 1\r
+\r
+       SetColor = 3: SDir = 1\r
+       PrevColor = 0: PDir = 1\r
+\r
+       VisObjects = MaxSprites \ 2\r
+       LastObjects(0) = 0\r
+       LastObjects(1) = 0\r
+\r
+DRAW.LOOP:\r
+\r
+\r
+       SET.ACTIVE.PAGE CurrentPage\r
+\r
+       ' Erase Old Images\r
+\r
+       FOR X = 1 TO LastObjects(CurrentPage)\r
+       \r
+               X1 = LastX(X, CurrentPage) AND &HFFFC\r
+               Y1 = LastY(X, CurrentPage)\r
+               X2 = ((LastX(X, CurrentPage) + Img(Obj(X).Shape).xWidth)) OR 3\r
+               Y2 = Y1 + Img(Obj(X).Shape).yWidth - 1\r
+\r
+               COPY.BITMAP 2, X1, Y1, X2, Y2, CurrentPage, X1, Y1\r
+       \r
+       NEXT X\r
+\r
+       ' Draw new images\r
+\r
+       FOR X = 1 TO VisObjects\r
+\r
+               SpriteX = Img(Obj(X).Shape).xWidth\r
+               SpriteY = Img(Obj(X).Shape).yWidth\r
+\r
+               ' Move Sprite\r
+\r
+REDOX:\r
+               NewX = Obj(X).Xpos + Obj(X).XDir\r
+               IF NewX < 0 OR NewX + SpriteX > ScreenX THEN\r
+                       Obj(X).XDir = -Obj(X).XDir\r
+                       IF RANDOM.INT(20) = 1 THEN\r
+                               DO\r
+                                       Obj(X).XDir = RANDOM.INT(7) - 3\r
+                                       Obj(X).YDir = RANDOM.INT(7) - 3\r
+                               LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0)\r
+                               GOTO REDOX\r
+                       END IF\r
+               END IF\r
+               Obj(X).Xpos = Obj(X).Xpos + Obj(X).XDir\r
+\r
+REDOY:\r
+               NewY = Obj(X).Ypos + Obj(X).YDir\r
+               IF NewY < 0 OR NewY + SpriteY > ScreenY THEN\r
+                       Obj(X).YDir = -Obj(X).YDir\r
+                       IF RANDOM.INT(20) = 1 THEN\r
+                               DO\r
+                                       Obj(X).XDir = RANDOM.INT(7) - 3\r
+                                       Obj(X).YDir = RANDOM.INT(7) - 3\r
+                               LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0)\r
+                               GOTO REDOY\r
+                       END IF\r
+               END IF\r
+               Obj(X).Ypos = Obj(X).Ypos + Obj(X).YDir\r
+\r
+               'Draw Sprite\r
+\r
+               TDRAW.BITMAP Img(Obj(X).Shape), Obj(X).Xpos, Obj(X).Ypos, SpriteX, SpriteY\r
+\r
+               LastX(X, CurrentPage) = Obj(X).Xpos\r
+               LastY(X, CurrentPage) = Obj(X).Ypos\r
+\r
+       NEXT X\r
+\r
+       LastObjects(CurrentPage) = VisObjects\r
+\r
+       ' Pan Screen Back & Forth\r
+\r
+       ViewCnt = ViewCnt + 1\r
+       IF ViewCnt >= ViewMax THEN\r
+               ViewX = ViewX + ViewXD\r
+               IF ViewX = 0 OR ViewX = 39 THEN ViewXD = -ViewXD\r
+               IF ViewXD < 0 THEN\r
+                       ViewY = ViewY + ViewYD\r
+                       IF ViewY = 0 OR ViewY = 39 THEN ViewYD = -ViewYD\r
+               END IF\r
+   \r
+               SET.WINDOW CurrentPage, ViewX, ViewY\r
+\r
+               ViewCnt = 0\r
+       ELSE\r
+               SET.DISPLAY.PAGE CurrentPage\r
+       END IF\r
+\r
+       ' Cycle Colors\r
+\r
+       SET.DAC.REGISTER 50 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor\r
+       SET.DAC.REGISTER 50 + SetColor, SetColor, 10, 63 - SetColor\r
+\r
+       SET.DAC.REGISTER 150 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor\r
+       SET.DAC.REGISTER 150 + SetColor, 63, 63, SetColor\r
+\r
+       SetColor = SetColor + SDir\r
+       IF SetColor = 60 OR SetColor = 0 THEN SDir = -SDir\r
+\r
+       PrevColor = PrevColor + PDir\r
+       IF PrevColor = 60 OR PrevColor = 0 THEN PDir = -PDir\r
+\r
+       CurrentPage = 1 - CurrentPage\r
+\r
+       Code = SCAN.KEYBOARD\r
+\r
+       IF Code = False THEN GOTO DRAW.LOOP\r
+\r
+       IF Code = KyPlus THEN\r
+               IF ViewMax < 12 THEN ViewMax = ViewMax + 1\r
+               GOTO DRAW.LOOP\r
+       END IF\r
+\r
+       IF Code = KyMinus THEN\r
+               IF ViewMax > 1 THEN ViewMax = ViewMax - 1\r
+               IF ViewCnt >= ViewMax THEN ViewCnt = 0\r
+               GOTO DRAW.LOOP\r
+       END IF\r
+\r
+       IF Code = KyUp THEN\r
+               IF VisObjects < MaxSprites THEN VisObjects = VisObjects + 1\r
+               GOTO DRAW.LOOP\r
+       END IF\r
+               \r
+       IF Code = KyDown THEN\r
+               IF VisObjects > 1 THEN VisObjects = VisObjects - 1\r
+               GOTO DRAW.LOOP\r
+       END IF\r
+\r
+\r
+END SUB\r
+\r
+SUB PRINT.TEXT (Text$, Xpos, Ypos, ColorF, ColorB)\r
+\r
+       IF LEN(Text$) = 0 THEN EXIT SUB\r
+\r
+       PRINT.STR SSEG(Text$), SADD(Text$), LEN(Text$), Xpos, Ypos, ColorF, ColorB\r
+\r
+\r
+END SUB\r
+\r
+SUB TPRINT.TEXT (Text$, Xpos, Ypos, ColorF)\r
+\r
+       IF LEN(Text$) = 0 THEN EXIT SUB\r
+\r
+       TPRINT.STR SSEG(Text$), SADD(Text$), LEN(Text$), Xpos, Ypos, ColorF\r
+\r
+END SUB\r
+\r
diff --git a/src/lib/modex/demos/basic7/uasm-bc7.bat b/src/lib/modex/demos/basic7/uasm-bc7.bat
new file mode 100755 (executable)
index 0000000..5ad67fb
--- /dev/null
@@ -0,0 +1 @@
+MASM /DFARSTRINGS utils, utils, utils, nul;
\ No newline at end of file
diff --git a/src/lib/modex/demos/basic7/utils.asm b/src/lib/modex/demos/basic7/utils.asm
new file mode 100755 (executable)
index 0000000..811b8f8
--- /dev/null
@@ -0,0 +1,406 @@
+;=======================================================\r
+;===  UTILS.ASM  - Asm Utilities for QuickBasic/BC7  ===\r
+;=======================================================\r
+\r
+       PAGE    255, 132\r
+\r
+       .MODEL Medium\r
+       .286\r
+\r
+       ; ==== MACROS ====\r
+\r
+       ; macros to PUSH and POP multiple registers\r
+\r
+PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+       IFNB <R1>\r
+               push    R1                              ; Save R1\r
+               PUSHx   R2, R3, R4, R5, R6, R7, R8\r
+       ENDIF\r
+ENDM\r
+\r
+POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+       IFNB <R1>\r
+               pop             R1                              ; Restore R1\r
+               POPx    R2, R3, R4, R5, R6, R7, R8\r
+       ENDIF\r
+ENDM\r
+\r
+       ; Macro to Clear a Register to 0\r
+\r
+CLR MACRO Register\r
+       xor             Register, Register              ; Set Register = 0\r
+ENDM\r
+\r
+       ; Macros to Decrement Counter & Jump on Condition\r
+\r
+LOOPx MACRO Register, Destination\r
+       dec             Register                                ; Counter--\r
+       jnz             Destination                             ; Jump if not 0\r
+ENDM\r
+\r
+LOOPjz MACRO Register, Destination\r
+       dec             Register                                ; Counter--\r
+       jz              Destination                             ; Jump if 0\r
+ENDM\r
+\r
+\r
+       ; ==== General Constants ====\r
+\r
+       False   EQU     0\r
+       True    EQU     -1\r
+       nil             EQU 0\r
+\r
+       b               EQU     BYTE PTR\r
+       w               EQU     WORD PTR\r
+       d               EQU     DWORD PTR\r
+       o               EQU     OFFSET\r
+       f               EQU FAR PTR\r
+       s               EQU     SHORT\r
+       ?x4             EQU <?,?,?,?>\r
+       ?x3             EQU <?,?,?>\r
+\r
+\r
+IFDEF FARSTRINGS\r
+\r
+       EXTRN   stringaddress:far\r
+       EXTRN   stringlength:far\r
+\r
+ENDIF\r
+\r
+\r
+       .Data\r
+\r
+       EVEN\r
+\r
+RND_Seed       DW      7397, 29447, 802\r
+RND_Mult       DW      179, 183, 182\r
+RND_ModV       DW      32771, 32779, 32783\r
+\r
+CR_LF          DB      13, 10                  ; the CRLF data\r
+\r
+       .Code\r
+\r
+;=================\r
+;DOS_PRINT (Text$)\r
+;=================\r
+;\r
+; Prints Text Directly to DOS console w/ CR/LF\r
+;\r
+\r
+       PUBLIC  DOS_PRINT\r
+\r
+DP_Stack       STRUC\r
+                               DW      ?x4     ; DI, SI, DS, BP\r
+                               DD      ?       ; Caller\r
+       DP_Text         DW      ?       ; Address of Text$ Descriptor\r
+DP_Stack       ENDS\r
+\r
+\r
+DOS_PRINT       PROC    FAR\r
+\r
+       PUSHx   BP, DS, SI, DI          ; Preserve Important Registers\r
+       mov             BP, SP                          ; Set up Stack Frame\r
+\r
+       mov     SI, [BP].DP_Text                ; Get Addr of Text$ descriptor\r
+\r
+IFDEF FARSTRINGS\r
+       push    SI                                      ; Push Addr of BC7 Decriptor Ptr\r
+       call    stringaddress           ; Get Address + Len of string!!!\r
+                                                               ; DX:AX = Addr  CX = Len\r
+       mov             DS, DX                          ; DS = DX = Segment of string\r
+       mov             DX, AX                          ; DX = AX = Offset of String\r
+ELSE\r
+       mov     CX, [SI]                ; put its length into CX\r
+    mov     DX, [SI+02]        ; now DS:DX points to the String\r
+ENDIF\r
+\r
+       jcxz    @No_Print                       ; Don't Print if empty\r
+\r
+       mov             BX, 1                           ; 1= DOS Handle for Display\r
+       mov             AH, 40h                         ; Write Text Function\r
+       int             21h                                     ; Call DOS to do it\r
+\r
+@No_Print:\r
+       mov             AX, SEG DGROUP          ; Restore DGroup\r
+       mov             DS, AX\r
+\r
+       mov             DX, o CR_LF                     ; Get Addr of CR/LF pair\r
+       mov             CX, 2                           ; 2 Characters to Write         \r
+       mov             BX, 1                           ; 1= DOS Handle for Display\r
+\r
+       mov             AH, 40h                         ; Write Text Function\r
+       int             21h                                     ; Call DOS to do it\r
+\r
+       cld                                                     ; Reset Direction Flag          \r
+       POPx    DI, SI, DS, BP          ; Restore Saved Registers\r
+       ret             2                                       ; Exit & Clean Up Stack\r
+\r
+DOS_PRINT       ENDP\r
+\r
+\r
+;==================\r
+;DOS_PRINTS (Text$)\r
+;==================\r
+; \r
+; Print Text$ Directly to DOS console \r
+; without a trailing CR/LF\r
+;\r
+\r
+       PUBLIC  DOS_PRINTS\r
+\r
+DOS_PRINTS      PROC    FAR\r
+\r
+       PUSHx   BP, DS, SI, DI          ; Preserve Important Registers\r
+       mov             BP, SP                          ; Set up Stack Frame\r
+\r
+    mov     SI, [BP].DP_Text   ; Get Addr of Text$ descriptor\r
+\r
+IFDEF FARSTRINGS\r
+       push    SI                                      ; Push Addr of BC7 Decriptor Ptr\r
+       call    stringaddress           ; Get Address + Len of string!!!\r
+                                                               ; DX:AX = Addr  CX = Len\r
+       mov             DS, DX                          ; DS = DX = Segment of string\r
+       mov             DX, AX                          ; DX = AX = Offset of String\r
+ELSE\r
+       mov     CX, [SI]                ; put its length into CX\r
+    mov     DX, [SI+02]        ; now DS:DX points to the String\r
+ENDIF\r
+\r
+       jcxz    @DPS_Exit                       ; Don't Print if empty\r
+\r
+       mov             BX, 1                           ; 1= DOS Handle for Display\r
+       mov             AH, 40h                         ; Write Text Function\r
+       int             21h                                     ; Call DOS to do it\r
+\r
+@DPS_Exit:\r
+       cld                                                     ; Reset Direction Flag          \r
+       POPx    DI, SI, DS, BP          ; Restore Saved Registers\r
+       ret             2                                       ; Exit & Clean Up Stack\r
+\r
+DOS_PRINTS      ENDP\r
+\r
+\r
+;======================\r
+;SET_VIDEO_MODE (Mode%) \r
+;======================\r
+;\r
+; Sets the Video Mode through the BIOS\r
+;\r
+\r
+       PUBLIC  SET_VIDEO_MODE\r
+\r
+SVM_Stack      STRUC\r
+                               DW      ?x4     ; DI, SI, DS, BP\r
+                               DD      ?       ; Caller\r
+       SVM_Mode        DB      ?,? ; Desired Video Mode\r
+SVM_Stack      ENDS\r
+\r
+\r
+SET_VIDEO_MODE PROC    FAR\r
+\r
+       PUSHx   BP, DS, SI, DI          ; Preserve Important Registers\r
+       mov             BP, SP                          ; Set up Stack Frame\r
+\r
+       CLR             AH                                      ; Function 0\r
+       mov             AL, [BP].SVM_Mode       ; Get Mode #\r
+\r
+       int             10H                                     ; Change Video Modes\r
+\r
+@SVM_Exit:\r
+       POPx    DI, SI, DS, BP          ; Restore Saved Registers\r
+       ret             2                                       ; Exit & Clean Up Stack\r
+\r
+SET_VIDEO_MODE ENDP\r
+\r
+\r
+;==============\r
+;SCAN_KEYBOARD%\r
+;==============\r
+;\r
+; Function to scan keyboard for a pressed key\r
+;\r
+\r
+       PUBLIC  SCAN_KEYBOARD\r
+\r
+SCAN_KEYBOARD  PROC    FAR\r
+\r
+       PUSHx   BP, DS, SI, DI          ; Preserve Important Registers\r
+\r
+       mov             AH, 01H                         ; Function #1\r
+       int             16H                                     ; Call Keyboard Driver\r
+       jz              @SK_NO_KEY                      ; Exit if Zero flag set\r
+\r
+       mov             AH,     00H                             ; Remove Key from Buffer\r
+       int             16H                                     ; Get Keycode in AX\r
+\r
+       or              AL, AL                          ; Low Byte Set (Ascii?)\r
+       jz              @SK_Exit                        ; if not, it's a F-Key\r
+\r
+       CLR             AH                                      ; Clear ScanCode if Ascii\r
+       jmp             s @SK_Exit                      ; Return Key in AX\r
+\r
+@SK_NO_KEY:\r
+       CLR             AX                                      ; Return Nil (no Keypress)\r
+\r
+@SK_Exit:\r
+       cld                                                     ; Reset Direction Flag          \r
+       POPx    DI, SI, DS, BP          ; Restore Saved Registers\r
+       ret                                                     ; Exit & Clean Up Stack\r
+\r
+SCAN_KEYBOARD  ENDP\r
+\r
+\r
+;====================\r
+;RANDOM_INT (MaxInt%)\r
+;====================\r
+;\r
+; Returns a pseudo-random number in the range of (0.. MaxInt-1)\r
+;\r
+\r
+\r
+       PUBLIC  RANDOM_INT\r
+\r
+RI_Stack       STRUC\r
+                               DW      ?       ; BP\r
+                               DD      ?       ; Caller\r
+       RI_MaxVal       DW      ?       ; Maximum Value to Return + 1\r
+RI_Stack       ENDS\r
+\r
+\r
+RANDOM_INT     PROC    FAR\r
+\r
+       push    BP                                      ; Preserve Important Registers\r
+       mov             BP, SP                          ; Set up Stack Frame\r
+\r
+       CLR             BX                                      ; BX is the data index\r
+       CLR             CX                              ; CX is the accumulator\r
+\r
+REPT 3\r
+       mov             AX, RND_Seed[BX]        ; load the initial seed\r
+       mul             RND_Mult[BX]            ; multiply it\r
+       div             RND_ModV[BX]            ; and obtain the Mod value\r
+       mov             RND_Seed[BX], DX        ; save that for the next time\r
+\r
+       add             CX, DX                          ; add it into the accumulator\r
+       inc             BX\r
+       inc             BX                      ; point to the next set of values\r
+ENDM\r
+\r
+       mov             AX, CX                          ; AX = Random #\r
+       CLR             DX                                      ; DX = 0\r
+       div             [BP].RI_MaxVal          ; DX = DX:AX / MAxVal Remainder\r
+\r
+       mov             AX, DX\r
+\r
+       pop             BP                                      ; Restore BP\r
+       ret             2                               ; back to BASIC with AX holding the result\r
+\r
+RANDOM_INT     ENDP\r
+\r
+\r
+;===========\r
+;INIT_RANDOM\r
+;===========\r
+;\r
+; Scrambles the psuedo-random number sequence\r
+; (XOR's the seed value with the timer)\r
+;\r
+\r
+       PUBLIC  INIT_RANDOM\r
+\r
+INIT_RANDOM    PROC    FAR\r
+\r
+       clr             AX                                      ; Segment = 0000\r
+       mov             ES, AX\r
+       mov             AX, ES:[046Ch]      ; Get Timer Lo Word\r
+\r
+       xor             RND_Seed, AX            ; Scramble 1st Seed\r
+\r
+       ret                                                     ; Exit & Clean Up Stack\r
+\r
+INIT_RANDOM    ENDP\r
+\r
+\r
+;====================\r
+;INT_SQR (X%, Round%)\r
+;====================\r
+;\r
+; Returns the Integer Square Root of (X)\r
+; Round allows the return value to be rounded to the \r
+; nearest integer value by passing 0x80.  Passing 0\r
+; return the Integer Portion only.  The rounding amound is\r
+; a number from 0 to 1 multiplied by 256, thus \r
+; 0.5 * 0x100 = 0x80!\r
+;\r
+\r
+ISQ_Stack      STRUC\r
+                                       DW      ?,?     ; BP, DI\r
+                                       DD      ?       ; Caller\r
+       ISQ_Round               DW      ?       ; Amount to Round Result * 256\r
+       ISQ_X                   DW      ?       ; "X"\r
+ISQ_Stack      ENDS\r
+\r
+       PUBLIC  INT_SQR\r
+\r
+INT_SQR                PROC    FAR\r
+\r
+    PUSHx   BP, DI                             ; Save BP\r
+    mov     BP, SP                             ; Set up Stack Frame\r
+\r
+       xor     AX, AX                          ; {xor eax,eax}\r
+       xor     DX, DX                          ; {xor edx,edx}\r
+       mov     DI, [BP].ISQ_X          ; {mov edi,x}\r
+\r
+       mov     CX, 16                          ; {mov cx, 32}\r
+\r
+@ISQ_L:\r
+\r
+       shl     DI, 1                           ; {shl edi,1}\r
+       rcl     DX, 1                           ; {rcl edx,1}\r
+       shl     DI, 1                           ; {shl edi,1}\r
+       rcl     DX, 1                           ; {rcl edx,1}\r
+       shl     AX, 1                           ; {shl eax,1}\r
+       mov     BX, AX                          ; {mov ebx,eax}\r
+       shl     BX, 1                           ; {shl ebx,1}\r
+       inc     BX                                      ; {inc ebx}\r
+       cmp     DX, BX                          ; {cmp edx,ebx}\r
+       jl              @ISQ_S\r
+\r
+       sub     DX, BX                          ; {sub edx,ebx}\r
+       inc     AX                                      ; {inc eax}\r
+\r
+@ISQ_S: \r
+       loop    @ISQ_L\r
+\r
+       add     ax, [BP].ISQ_Round      ; {add eax,$00008000}  \r
+                                                               ; {*round* result in hi word: ie. +0.5}\r
+       shr     ax, 8                           ; {shr eax,16}  {to ax (result)}\r
+\r
+       POPx    DI, BP                          ; Restore Registers     \r
+       ret             4                                       ; Exit\r
+\r
+INT_SQR                ENDP\r
+\r
+\r
+;============\r
+;TIMER_COUNT&\r
+;============\r
+;\r
+; Returns the current timer value as an integer/long integer\r
+;\r
+\r
+\r
+       PUBLIC  TIMER_COUNT\r
+\r
+TIMER_COUNT      PROC    FAR\r
+\r
+       clr             AX                                      ; Segment = 0000\r
+       mov             ES, AX                          ; use ES to get at data\r
+       mov             AX, ES:[046Ch]      ; Get Timer Lo Word\r
+       mov             DX, ES:[046Eh]          ; Get Timer Hi Word\r
+       ret                                                     ; Exit & Return value in DX:AX\r
+\r
+TIMER_COUNT      ENDP\r
+\r
+\r
+       END\r
diff --git a/src/lib/modex/demos/basic7/utils.bi b/src/lib/modex/demos/basic7/utils.bi
new file mode 100755 (executable)
index 0000000..aeafeef
--- /dev/null
@@ -0,0 +1,51 @@
+\r
+       ' Misc Constants\r
+\r
+CONST True = -1, False = 0, nil = 0\r
+\r
+       ' Keyboard Codes: Extended\r
+\r
+CONST KyF1 = &H3B00, KyF2 = &H3C00, KyF3 = &H3D00, KyF4 = &H3E00, KyF5 = &H3F00\r
+CONST KyF6 = &H4000, KyF7 = &H4100, KyF8 = &H4200, KyF9 = &H4300, KyF10 = &H4400\r
+\r
+CONST KyUp = &H4800, KyLeft = &H4B00, KyRight = &H4D00, KyDown = &H5000\r
+CONST KySLeft = &HCB00, KySRight = &HCD00, KySUp = &HC800, KySDown = &HD000\r
+\r
+CONST KyHome = &H4700, KyPgUp = &H4900, KyEnd = &H4F00, KyPgDn = &H5100\r
+CONST KySHome = &HC700, KySPgUp = &HC900, KySEnd = &HCF00, KySPgDn = &HD100\r
+\r
+CONST KyIns = &H5200, KyDel = &H5300, KyRvsTab = &H8F00\r
+CONST KySIns = &HC200, KySDel = &HC300\r
+\r
+CONST KyAltA = &H1E00, KyAltB = &H3000, KyAltC = &H2E00, KyAltD = &H2000\r
+CONST KyAltE = &H1200, KyAltF = &H2100, KyAltG = &H2200, KyAltH = &H2300\r
+CONST KyAltI = &H1700, KyAltJ = &H2400, KyAltK = &H2500, KyAltL = &H2600\r
+CONST KyAltM = &H3200, KyAltN = &H3100, KyAltO = &H1800, KyAltP = &H1900\r
+CONST KyAltQ = &H1000, KyAltR = &H1300, KyAltS = &H1F00, KyAltT = &H1400\r
+CONST KyAltU = &H1600, KyAltV = &H2F00, KyAltW = &H1100, KyAltX = &H2D00\r
+CONST KyAltY = &H1500, KyAltZ = &H2C00\r
+\r
+       ' Keyboard Codes: Ascii\r
+\r
+CONST KyBS = 8, KyTab = 9, KyCR = 13, KyESC = &H1B, KyClr = &H7F\r
+CONST KyPlus = 45, KyMinus = 43\r
+\r
+       ' Color Constants\r
+\r
+CONST c.BLACK = 0, c.BLUE = 1, c.GREEN = 2, c.CYAN = 3\r
+CONST c.RED = 4, c.PURPLE = 5, c.BROWN = 6, c.WHITE = 7\r
+CONST c.GREY = 8, c.bBLUE = 9, c.bGREEN = 10, c.bCYAN = 11\r
+CONST c.bRED = 12, c.bPURPLE = 13, c.YELLOW = 14, c.bWHITE = 15\r
+CONST c.BRIGHT = 8\r
+\r
+       ' From UTILS.ASM\r
+\r
+DECLARE SUB DOS.PRINT ALIAS "DOS_PRINT" (Text$)\r
+DECLARE SUB DOS.PRINTS ALIAS "DOS_PRINTS" (Text$)\r
+DECLARE SUB SET.VIDEO.MODE ALIAS "SET_VIDEO_MODE" (BYVAL Mode%)\r
+DECLARE FUNCTION SCAN.KEYBOARD% ALIAS "SCAN_KEYBOARD"\r
+DECLARE FUNCTION RANDOM.INT ALIAS "RANDOM_INT" (BYVAL MaxInt%)\r
+DECLARE SUB INIT.RANDOM ALIAS "INIT_RANDOM"\r
+DECLARE FUNCTION TIMER.COUNT& ALIAS "TIMER_COUNT"\r
+DECLARE FUNCTION INT.SQR ALIAS "INT_SQR" (BYVAL X%, BYVAL Round%)\r
+\r
diff --git a/src/lib/modex/demos/c/c_utils.asm b/src/lib/modex/demos/c/c_utils.asm
new file mode 100755 (executable)
index 0000000..0118201
--- /dev/null
@@ -0,0 +1,456 @@
+;=======================================================\r
+;===  C_UTILS.ASM  - Asm Utilities for C/C++         ===\r
+;=======================================================\r
+\r
+       PAGE    255, 132\r
+\r
+       .MODEL Huge\r
+;      .286\r
+\r
+       ; ==== MACROS ====\r
+\r
+       ; macros to PUSH and POP multiple registers\r
+\r
+; PUSHx MACRO R1, R2, R3, R4;, R5, R6, R7, R8\r
+;      IFNB <R1>\r
+;              push    R1                              ; Save R1\r
+;              PUSHx   R2, R3, R4;, R5, R6, R7, R8\r
+;      ENDIF\r
+; ENDM\r
+;\r
+; POPx MACRO R1, R2, R3, R4;, R5, R6, R7, R8\r
+;      IFNB <R1>\r
+;              pop             R1                              ; Restore R1\r
+;              POPx    R2, R3, R4;, R5, R6, R7, R8\r
+;      ENDIF\r
+; ENDM\r
+\r
+       ; Macro to Clear a Register to 0\r
+\r
+CLR MACRO Register\r
+       xor             Register, Register              ; Set Register = 0\r
+ENDM\r
+\r
+       ; Macros to Decrement Counter & Jump on Condition\r
+\r
+LOOPx MACRO Register, Destination\r
+       dec             Register                                ; Counter--\r
+       jnz             Destination                             ; Jump if not 0\r
+ENDM\r
+\r
+LOOPjz MACRO Register, Destination\r
+       dec             Register                                ; Counter--\r
+       jz              Destination                             ; Jump if 0\r
+ENDM\r
+\r
+\r
+       ; ==== General Constants ====\r
+\r
+       False   EQU     0\r
+       True    EQU     -1\r
+       nil             EQU 0\r
+\r
+       b               EQU     BYTE PTR\r
+       w               EQU     WORD PTR\r
+       d               EQU     DWORD PTR\r
+       o               EQU     OFFSET\r
+       f               EQU FAR PTR\r
+       s               EQU     SHORT\r
+       ?x4             EQU <?,?,?,?>\r
+       ?x3             EQU <?,?,?>\r
+       ?x2             EQU <?,?>\r
+       ?x1             EQU <?>\r
+\r
+\r
+       .Data\r
+\r
+       EVEN\r
+\r
+RND_Seed       DW      7397, 29447, 802\r
+RND_Mult       DW      179, 183, 182\r
+RND_ModV       DW      32771, 32779, 32783\r
+\r
+CR_LF          DB      13, 10                  ; the CRLF data\r
+\r
+       .Code\r
+\r
+;===========================================\r
+;void far pascal dos_print  (far char *Text)\r
+;===========================================\r
+;\r
+; - Print Text Directly to DOS console w/ CR/LF\r
+;\r
+\r
+       PUBLIC  DOS_PRINT\r
+\r
+DP_Stack       STRUC\r
+                               DW      ?x1     ; DI, SI, DS, BP\r
+                               DW      ?x1     ; DI, SI, DS, BP\r
+                               DW      ?x1     ; DI, SI, DS, BP\r
+                               DW      ?x1     ; DI, SI, DS, BP\r
+                               DD      ?       ; Caller\r
+       DP_Text         DD      ?       ; Far Address of Text to print\r
+DP_Stack       ENDS\r
+\r
+\r
+DOS_PRINT       PROC    FAR\r
+\r
+       ;PUSHx  BP, DS, SI, DI          ; Preserve Important Registers\r
+       push bp\r
+       push ds\r
+       push si\r
+       push di\r
+       mov             BP, SP                          ; Set up Stack Frame\r
+\r
+       lds     DX, [BP].DP_Text        ; Get Addr of Text$ descriptor\r
+\r
+       ; Compute Length of string\r
+\r
+       CLR             CX                                      ; Length = 0\r
+       mov             SI, DX                          ; DS:SI = String data\r
+\r
+@@DP_Scan_it:\r
+\r
+       cmp             b [SI], 0                       ; Null Byte found?\r
+       je              @@DP_Got_Len            ; exit loop if so\r
+\r
+       inc             CX                                      ; Len++\r
+       inc             SI                                      ; Point to next char\r
+       jmp             s @@DP_Scan_it          ; check again...\r
+\r
+@@DP_Got_len:\r
+\r
+       jcxz    @No_Print                       ; Don't Print if empty\r
+\r
+       mov             BX, 1                           ; 1= DOS Handle for Display\r
+       mov             AH, 40h                         ; Write Text Function\r
+       int             21h                                     ; Call DOS to do it\r
+\r
+@No_Print:\r
+       mov             AX, SEG DGROUP          ; Restore DGroup\r
+       mov             DS, AX\r
+\r
+       mov             DX, o CR_LF                     ; Get Addr of CR/LF pair\r
+       mov             CX, 2                           ; 2 Characters to Write\r
+       mov             BX, 1                           ; 1= DOS Handle for Display\r
+\r
+       mov             AH, 40h                         ; Write Text Function\r
+       int             21h                                     ; Call DOS to do it\r
+\r
+       cld                                                     ; Reset Direction Flag\r
+       ;POPx   DI, SI, DS, BP          ; Restore Saved Registers\r
+       pop di\r
+       pop si\r
+       pop ds\r
+       pop bp\r
+       ret             4                                       ; Exit & Clean Up Stack\r
+\r
+DOS_PRINT       ENDP\r
+\r
+\r
+;===========================================\r
+;void far pascal dos_prints (char far *Text)\r
+;===========================================\r
+;\r
+; Print Text Directly to DOS console\r
+; without a trailing CR/LF\r
+;\r
+\r
+       PUBLIC  DOS_PRINTS\r
+\r
+DOS_PRINTS      PROC    FAR\r
+\r
+       ;PUSHx  BP, DS, SI, DI          ; Preserve Important Registers\r
+       push bp\r
+       push ds\r
+       push si\r
+       push di\r
+       mov             BP, SP                          ; Set up Stack Frame\r
+\r
+       lds     DX, [BP].DP_Text        ; Get Addr of Text$ descriptor\r
+\r
+       ; Compute Length of string\r
+\r
+       CLR             CX                                      ; Length = 0\r
+       mov             SI, DX                          ; DS:SI = String data\r
+\r
+@@DPS_Scan_it:\r
+\r
+       cmp             b [SI], 0                       ; Null Byte found?\r
+       je              @@DPS_Got_Len           ; exit loop if so\r
+\r
+       inc             CX                                      ; Len++\r
+       inc             SI                                      ; Point to next char\r
+       jmp             s @@DPS_Scan_it         ; check again...\r
+\r
+@@DPS_Got_len:\r
+\r
+       jcxz    @DPS_Exit                       ; Don't Print if empty\r
+\r
+       mov             BX, 1                           ; 1= DOS Handle for Display\r
+       mov             AH, 40h                         ; Write Text Function\r
+       int             21h                                     ; Call DOS to do it\r
+\r
+@DPS_Exit:\r
+       cld                                                     ; Reset Direction Flag\r
+       ;POPx   DI, SI, DS, BP          ; Restore Saved Registers\r
+       pop di\r
+       pop si\r
+       pop ds\r
+       pop bp\r
+       ret             2                                       ; Exit & Clean Up Stack\r
+\r
+DOS_PRINTS      ENDP\r
+\r
+\r
+;=========================================\r
+;void far pascal set_video_mode (int Mode)\r
+;=========================================\r
+;\r
+; Sets the Video Mode through the BIOS\r
+;\r
+\r
+       PUBLIC  SET_VIDEO_MODE\r
+\r
+SVM_Stack      STRUC\r
+                               DW      ?x1     ; DI, SI, DS, BP\r
+                               DW      ?x1     ; DI, SI, DS, BP\r
+                               DW      ?x1     ; DI, SI, DS, BP\r
+                               DW      ?x1     ; DI, SI, DS, BP\r
+                               DD      ?       ; Caller\r
+       SVM_Mode        DB      ?,? ; Desired Video Mode\r
+SVM_Stack      ENDS\r
+\r
+\r
+SET_VIDEO_MODE PROC    FAR\r
+\r
+       ;PUSHx  BP, DS, SI, DI          ; Preserve Important Registers\r
+       push bp\r
+       push ds\r
+       push si\r
+       push di\r
+       mov             BP, SP                          ; Set up Stack Frame\r
+\r
+       CLR             AH                                      ; Function 0\r
+       mov             AL, [BP].SVM_Mode       ; Get Mode #\r
+\r
+       int             10H                                     ; Change Video Modes\r
+\r
+@SVM_Exit:\r
+       ;POPx   DI, SI, DS, BP          ; Restore Saved Registers\r
+       pop di\r
+       pop si\r
+       pop ds\r
+       pop bp\r
+       ret             2                                       ; Exit & Clean Up Stack\r
+\r
+SET_VIDEO_MODE ENDP\r
+\r
+\r
+;===================================\r
+;int far pascal scan_keyboard (void)\r
+;===================================\r
+;\r
+; Function to scan keyboard for a pressed key\r
+;\r
+\r
+       PUBLIC  SCAN_KEYBOARD\r
+\r
+SCAN_KEYBOARD  PROC    FAR\r
+\r
+       ;PUSHx  BP, DS, SI, DI          ; Preserve Important Registers\r
+       push bp\r
+       push ds\r
+       push si\r
+       push di\r
+\r
+       mov             AH, 01H                         ; Function #1\r
+       INT             16H                                     ; Call Keyboard Driver\r
+       JZ              @SK_NO_KEY                      ; Exit if Zero flag set\r
+\r
+       mov             AH,     00H                             ; Remove Key from Buffer\r
+       INT             16H                                     ; Get Keycode in AX\r
+\r
+       OR              AL, AL                          ; Low Byte Set (Ascii?)\r
+       JZ              @SK_Exit                        ; if not, it's a F-Key\r
+\r
+       CLR             AH                                      ; Clear ScanCode if Ascii\r
+       JMP             s @SK_Exit                      ; Return Key in AX\r
+\r
+@SK_NO_KEY:\r
+       CLR             AX                                      ; Return Nil (no Keypress)\r
+\r
+@SK_Exit:\r
+       cld                                                     ; Reset Direction Flag\r
+       ;POPx   DI, SI, DS, BP          ; Restore Saved Registers\r
+       pop di\r
+       pop si\r
+       pop ds\r
+       pop bp\r
+       ret                                                     ; Exit & Clean Up Stack\r
+\r
+SCAN_KEYBOARD  ENDP\r
+\r
+\r
+;========================================\r
+;int far pascal random_int (int MaxValue)\r
+;========================================\r
+;\r
+; Returns a pseudo-random number in the range of (0.. MaxInt-1)\r
+;\r
+\r
+\r
+       PUBLIC  RANDOM_INT\r
+\r
+RI_Stack       STRUC\r
+                               DW      ?       ; BP\r
+                               DD      ?       ; Caller\r
+       RI_MaxVal       DW      ?       ; Maximum Value to Return + 1\r
+RI_Stack       ENDS\r
+\r
+\r
+RANDOM_INT     PROC    FAR\r
+\r
+       push    BP                                      ; Preserve Important Registers\r
+       mov             BP, SP                          ; Set up Stack Frame\r
+\r
+       CLR             BX                                      ; BX is the data index\r
+       CLR             CX                              ; CX is the accumulator\r
+\r
+REPT 3\r
+       mov             AX, RND_Seed[BX]        ; load the initial seed\r
+       mul             RND_Mult[BX]            ; multiply it\r
+       div             RND_ModV[BX]            ; and obtain the Mod value\r
+       mov             RND_Seed[BX], DX        ; save that for the next time\r
+\r
+       add             CX, DX                          ; add it into the accumulator\r
+       inc             BX\r
+       inc             BX                      ; point to the next set of values\r
+ENDM\r
+\r
+       mov             AX, CX                          ; AX = Random #\r
+       CLR             DX                                      ; DX = 0\r
+       div             [BP].RI_MaxVal          ; DX = DX:AX / MAxVal Remainder\r
+\r
+       mov             AX, DX\r
+\r
+       pop             BP                                      ; Restore BP\r
+       ret             2                               ; back to BASIC with AX holding the result\r
+\r
+RANDOM_INT     ENDP\r
+\r
+\r
+;==================================\r
+;void far pascal init_random (void)\r
+;==================================\r
+;\r
+; Scrambles the psuedo-random number sequence\r
+; (XOR's the seed value with the timer)\r
+;\r
+\r
+       PUBLIC  INIT_RANDOM\r
+\r
+INIT_RANDOM    PROC    FAR\r
+\r
+       CLR             AX                                      ; Segment = 0000\r
+       mov             ES, AX\r
+       mov             AX, ES:[046Ch]      ; Get Timer Lo Word\r
+\r
+       xor             RND_Seed, AX            ; Scramble 1st Seed\r
+\r
+       ret                                                     ; Exit & Clean Up Stack\r
+\r
+INIT_RANDOM    ENDP\r
+\r
+;=========================================\r
+;int far pascal int_sqr (int X, int Round)\r
+;=========================================\r
+;\r
+; Returns the Integer Square Root of (X)\r
+; Round allows the return value to be rounded to the\r
+; nearest integer value by passing 0x80.  Passing 0\r
+; return the Integer Portion only.  The rounding amound is\r
+; a number from 0 to 1 multiplied by 256, thus\r
+; 0.5 * 0x100 = 0x80!\r
+;\r
+\r
+ISQ_Stack      STRUC\r
+                                       DW      ?,?     ; BP, DI\r
+                                       DD      ?       ; Caller\r
+       ISQ_Round               DW      ?       ; Amount to Round Result * 256\r
+       ISQ_X                   DW      ?       ; "X"\r
+ISQ_Stack      ENDS\r
+\r
+       PUBLIC  INT_SQR\r
+\r
+INT_SQR                PROC    FAR\r
+\r
+    ;PUSHx   BP, DI                            ; Save BP\r
+       push bp\r
+       push di\r
+    mov     BP, SP                             ; Set up Stack Frame\r
+\r
+       xor     AX, AX                          ; {xor eax,eax}\r
+       xor     DX, DX                          ; {xor edx,edx}\r
+       mov     DI, [BP].ISQ_X          ; {mov edi,x}\r
+\r
+       mov     CX, 16                          ; {mov cx, 32}\r
+\r
+@ISQ_L:\r
+\r
+       shl     DI, 1                           ; {shl edi,1}\r
+       rcl     DX, 1                           ; {rcl edx,1}\r
+       shl     DI, 1                           ; {shl edi,1}\r
+       rcl     DX, 1                           ; {rcl edx,1}\r
+       shl     AX, 1                           ; {shl eax,1}\r
+       mov     BX, AX                          ; {mov ebx,eax}\r
+       shl     BX, 1                           ; {shl ebx,1}\r
+       inc     BX                                      ; {inc ebx}\r
+       cmp     DX, BX                          ; {cmp edx,ebx}\r
+       jl              @ISQ_S\r
+\r
+       sub     DX, BX                          ; {sub edx,ebx}\r
+       inc     AX                                      ; {inc eax}\r
+\r
+@ISQ_S:\r
+       loop    @ISQ_L\r
+\r
+       add     ax, [BP].ISQ_Round      ; {add eax,$00008000}\r
+                                                               ; {*round* result in hi word: ie. +0.5}\r
+       shr     ax, 1                           ; {shr eax,16}  {to ax (result)}\r
+       shr     ax, 1                           ; {shr eax,16}  {to ax (result)}\r
+       shr     ax, 1                           ; {shr eax,16}  {to ax (result)}\r
+       shr     ax, 1                           ; {shr eax,16}  {to ax (result)}\r
+       shr     ax, 1                           ; {shr eax,16}  {to ax (result)}\r
+       shr     ax, 1                           ; {shr eax,16}  {to ax (result)}\r
+       shr     ax, 1                           ; {shr eax,16}  {to ax (result)}\r
+       shr     ax, 1                           ; {shr eax,16}  {to ax (result)}\r
+\r
+       ;POPx   DI, BP                          ; Restore Registers\r
+       pop di\r
+       pop bp\r
+       ret             4                                       ; Exit\r
+\r
+INT_SQR                ENDP\r
+\r
+;=================================\r
+;int far pascal timer_count (void)\r
+;=================================\r
+;\r
+; Returns the current timer value as an integer/long integer\r
+;\r
+\r
+       PUBLIC  TIMER_COUNT\r
+\r
+TIMER_COUNT      PROC    FAR\r
+\r
+       CLR             AX                                      ; Segment = 0000\r
+       mov             ES, AX\r
+       mov             AX, ES:[046Ch]      ; Get Timer Lo Word\r
+       mov             DX, ES:[046Eh]          ; Get Timer Hi Word\r
+       ret                                                     ; Exit & Clean Up Stack\r
+\r
+TIMER_COUNT      ENDP\r
+\r
+\r
+       END\r
diff --git a/src/lib/modex/demos/c/c_utils.h b/src/lib/modex/demos/c/c_utils.h
new file mode 100755 (executable)
index 0000000..9be6ba2
--- /dev/null
@@ -0,0 +1,117 @@
+\r
+#ifndef __C_UTILS_H\r
+#define __C_UTILS_H\r
+\r
+\r
+       /* Misc Constants */\r
+\r
+#define True     -1\r
+#define False    0\r
+#define nil      0\r
+\r
+       /* Color Constants */\r
+\r
+#define c_BLACK   0\r
+#define c_BLUE    1\r
+#define c_GREEN   2\r
+#define c_CYAN    3\r
+#define c_RED     4\r
+#define c_PURPLE  5\r
+#define c_BROWN   6\r
+#define c_WHITE   7\r
+#define c_GREY    8\r
+#define c_bBLUE   9\r
+#define c_bGREEN  10\r
+#define c_bCYAN   11\r
+#define c_bRED    12\r
+#define c_bPURPLE 13\r
+#define c_YELLOW  14\r
+#define c_bWHITE  15\r
+#define c_BRIGHT  16\r
+\r
+\r
+#define Ky_F1     0x3B00\r
+#define Ky_F2     0x3C00\r
+#define Ky_F3     0x3D00\r
+#define Ky_F4     0x3E00\r
+#define Ky_F5     0x3F00\r
+#define Ky_F6     0x4000\r
+#define Ky_F7     0x4100\r
+#define Ky_F8     0x4200\r
+#define Ky_F9     0x4300\r
+#define Ky_F10    0x4400\r
+\r
+#define Ky_Up     0x4800\r
+#define Ky_Left   0x4B00\r
+#define Ky_Right  0x4D00\r
+#define Ky_Down   0x5000\r
+#define Ky_SUp    0xC800\r
+#define Ky_SLeft  0xCB00\r
+#define Ky_SRight 0xCD00\r
+#define Ky_SDown  0xD000\r
+\r
+#define Ky_Home   0x4700\r
+#define Ky_End    0x4F00\r
+#define Ky_PgUp   0x4900\r
+#define Ky_PgDn   0x5100\r
+#define Ky_SHome  0xC700\r
+#define Ky_SEnd   0xCF00\r
+#define Ky_SPgUp  0xC900\r
+#define Ky_SPgDn  0xD100\r
+\r
+#define Ky_Ins    0x5200\r
+#define Ky_Del    0x5300\r
+#define Ky_SIns   0xC200\r
+#define Ky_SDel   0xC300\r
+\r
+#define Ky_Tab    0x0009\r
+#define Ky_RvsTab 0x8F00\r
+#define Ky_STab   0x8F00\r
+\r
+#define Ky_BS     0x0008\r
+#define Ky_CR     0x000D\r
+#define Ky_ESC    0x001B\r
+#define Ky_Clr    0x007F\r
+\r
+#define Ky_Plus   0x002D\r
+#define Ky_Minus  0x002B\r
+\r
+#define Ky_AltA   0x1E00\r
+#define Ky_AltB   0x3000\r
+#define Ky_AltC   0x2E00\r
+#define Ky_AltD   0x2000\r
+#define Ky_AltE   0x1200\r
+#define Ky_AltF   0x2100\r
+#define Ky_AltG   0x2200\r
+#define Ky_AltH   0x2300\r
+#define Ky_AltI   0x1700\r
+#define Ky_AltJ   0x2400\r
+#define Ky_AltK   0x2500\r
+#define Ky_AltL   0x2600\r
+#define Ky_AltM   0x3200\r
+#define Ky_AltN   0x3100\r
+#define Ky_AltO   0x1800\r
+#define Ky_AltP   0x1900\r
+#define Ky_AltQ   0x1000\r
+#define Ky_AltR   0x1300\r
+#define Ky_AltS   0x1F00\r
+#define Ky_AltT   0x1400\r
+#define Ky_AltU   0x1600\r
+#define Ky_AltV   0x2F00\r
+#define Ky_AltW   0x1100\r
+#define Ky_AltX   0x2D00\r
+#define Ky_AltY   0x1500\r
+#define Ky_AltZ   0x2C00\r
+\r
+       /* .ASM Functions From C_UTILS.ASM */\r
+\r
+void far pascal dos_print (char far *Text);\r
+void far pascal dos_prints (char far *Text);\r
+void far pascal set_video_mode (int Mode);\r
+int  far pascal scan_keyboard (void);\r
+int  far pascal random_int (int MaxValue);\r
+void far pascal init_random (void);\r
+int  far pascal int_sqr (int X, int Round);\r
+int  far pascal timer_count (void);\r
+\r
+#endif\r
diff --git a/src/lib/modex/demos/c/c_utils.lst b/src/lib/modex/demos/c/c_utils.lst
new file mode 100755 (executable)
index 0000000..f9664ba
--- /dev/null
@@ -0,0 +1,597 @@
+Microsoft (R) Macro Assembler Version 6.11                 07/03/14 12:38:18\r
+c_utils.asm                                                 Page 1 - 1\r
+\r
+\r
+                               ;=======================================================\r
+                               ;===  C_UTILS.ASM  - Asm Utilities for C/C++         ===\r
+                               ;=======================================================\r
+\r
+                                       PAGE    255, 132\r
+\r
+                                       .MODEL Medium\r
+                                       .286\r
+\r
+                                       ; ==== MACROS ====\r
+\r
+                                       ; macros to PUSH and POP multiple registers\r
+\r
+                               PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+                                       IFNB <R1>\r
+                                               push    R1                              ; Save R1\r
+                                               PUSHx   R2, R3, R4, R5, R6, R7, R8\r
+                                       ENDIF\r
+                               ENDM\r
+\r
+                               POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+                                       IFNB <R1>\r
+                                               pop             R1                              ; Restore R1\r
+                                               POPx    R2, R3, R4, R5, R6, R7, R8\r
+                                       ENDIF\r
+                               ENDM\r
+\r
+                                       ; Macro to Clear a Register to 0\r
+\r
+                               CLR MACRO Register\r
+                                       xor             Register, Register              ; Set Register = 0\r
+                               ENDM\r
+\r
+                                       ; Macros to Decrement Counter & Jump on Condition\r
+\r
+                               LOOPx MACRO Register, Destination\r
+                                       dec             Register                                ; Counter--\r
+                                       jnz             Destination                             ; Jump if not 0\r
+                               ENDM\r
+\r
+                               LOOPjz MACRO Register, Destination\r
+                                       dec             Register                                ; Counter--\r
+                                       jz              Destination                             ; Jump if 0\r
+                               ENDM\r
+\r
+\r
+                                       ; ==== General Constants ====\r
+\r
+ = 0000                                        False   EQU     0\r
+ =-0001                                        True    EQU     -1\r
+ = 0000                                        nil             EQU 0\r
+\r
+ = BYTE PTR                            b               EQU     BYTE PTR\r
+ = WORD PTR                            w               EQU     WORD PTR\r
+ = DWORD PTR                           d               EQU     DWORD PTR\r
+ = OFFSET                              o               EQU     OFFSET\r
+ = FAR PTR                             f               EQU FAR PTR\r
+ = SHORT                               s               EQU     SHORT\r
+ = ?,?,?,?                             ?x4             EQU <?,?,?,?>\r
+ = ?,?,?                               ?x3             EQU <?,?,?>\r
+\r
+\r
+ 0000                                  .Data\r
+\r
+                                       EVEN\r
+\r
+ 0000 1CE5 7307 0322           RND_Seed        DW      7397, 29447, 802\r
+ 0006 00B3 00B7 00B6           RND_Mult        DW      179, 183, 182\r
+ 000C 8003 800B 800F           RND_ModV        DW      32771, 32779, 32783\r
+\r
+ 0012 0D 0A                    CR_LF           DB      13, 10                  ; the CRLF data\r
+\r
+ 0000                                  .Code\r
+\r
+                               ;===========================================\r
+                               ;void far pascal dos_print  (far char *Text)\r
+                               ;===========================================\r
+                               ;\r
+                               ; - Print Text Directly to DOS console w/ CR/LF\r
+                               ;\r
+\r
+                                       PUBLIC  DOS_PRINT\r
+\r
+ 0010                          DP_Stack        STRUC\r
+ 0000  0000 0000 0000                                          DW      ?x4     ; DI, SI, DS, BP\r
+       0000\r
+ 0008  00000000                                                        DD      ?       ; Caller\r
+ 000C  00000000                                DP_Text         DD      ?       ; Far Address of Text to print\r
+                               DP_Stack        ENDS\r
+\r
+\r
+ 0000                          DOS_PRINT        PROC    FAR\r
+                                                          \r
+                                       PUSHx   BP, DS, SI, DI          ; Preserve Important Registers\r
+ 0000  55                   1                  push    BP                              ; Save R1\r
+ 0001  1E                   2                  push    DS                              ; Save R1\r
+ 0002  56                   3                  push    SI                              ; Save R1\r
+ 0003  57                   4                  push    DI                              ; Save R1\r
+ 0004  8B EC                           mov             BP, SP                          ; Set up Stack Frame\r
+\r
+ 0006  C5 56 0C                                lds     DX, [BP].DP_Text        ; Get Addr of Text$ descriptor\r
+\r
+                                       ; Compute Length of string\r
+\r
+                                       CLR             CX                                      ; Length = 0\r
+ 0009  33 C9                1          xor             CX, CX          ; Set Register = 0\r
+ 000B  8B F2                           mov             SI, DX                          ; DS:SI = String data\r
+\r
+ 000D                          @@DP_Scan_it:\r
+                                       \r
+ 000D  80 3C 00                                cmp             b [SI], 0                       ; Null Byte found?\r
+ 0010  74 04                           je              @@DP_Got_Len            ; exit loop if so\r
+\r
+ 0012  41                              inc             CX                                      ; Len++\r
+ 0013  46                              inc             SI                                      ; Point to next char\r
+ 0014  EB F7                           jmp             s @@DP_Scan_it          ; check again...\r
+\r
+ 0016                          @@DP_Got_len:\r
+\r
+ 0016  E3 07                           jcxz    @No_Print                       ; Don't Print if empty\r
+\r
+ 0018  BB 0001                         mov             BX, 1                           ; 1= DOS Handle for Display\r
+ 001B  B4 40                           mov             AH, 40h                         ; Write Text Function\r
+ 001D  CD 21                           int             21h                                     ; Call DOS to do it\r
+\r
+ 001F                          @No_Print:\r
+ 001F  B8 ---- R                       mov             AX, SEG DGROUP          ; Restore DGroup\r
+ 0022  8E D8                           mov             DS, AX\r
+\r
+ 0024  BA 0012 R                       mov             DX, o CR_LF                     ; Get Addr of CR/LF pair\r
+ 0027  B9 0002                         mov             CX, 2                           ; 2 Characters to Write         \r
+ 002A  BB 0001                         mov             BX, 1                           ; 1= DOS Handle for Display\r
+\r
+ 002D  B4 40                           mov             AH, 40h                         ; Write Text Function\r
+ 002F  CD 21                           int             21h                                     ; Call DOS to do it\r
+\r
+ 0031  FC                              cld                                                     ; Reset Direction Flag          \r
+                                       POPx    DI, SI, DS, BP          ; Restore Saved Registers\r
+ 0032  5F                   1                  pop             DI                              ; Restore R1\r
+ 0033  5E                   2                  pop             SI                              ; Restore R1\r
+ 0034  1F                   3                  pop             DS                              ; Restore R1\r
+ 0035  5D                   4                  pop             BP                              ; Restore R1\r
+ 0036  CA 0004                         ret             4                                       ; Exit & Clean Up Stack\r
+\r
+ 0039                          DOS_PRINT        ENDP\r
+\r
+\r
+                               ;===========================================\r
+                               ;void far pascal dos_prints (char far *Text)\r
+                               ;===========================================\r
+                               ; \r
+                               ; Print Text Directly to DOS console \r
+                               ; without a trailing CR/LF\r
+                               ;\r
+\r
+                                       PUBLIC  DOS_PRINTS\r
+\r
+ 0039                          DOS_PRINTS       PROC    FAR\r
+\r
+                                       PUSHx   BP, DS, SI, DI          ; Preserve Important Registers\r
+ 0039  55                   1                  push    BP                              ; Save R1\r
+ 003A  1E                   2                  push    DS                              ; Save R1\r
+ 003B  56                   3                  push    SI                              ; Save R1\r
+ 003C  57                   4                  push    DI                              ; Save R1\r
+ 003D  8B EC                           mov             BP, SP                          ; Set up Stack Frame\r
+\r
+ 003F  C5 56 0C                                lds     DX, [BP].DP_Text        ; Get Addr of Text$ descriptor\r
+\r
+                                       ; Compute Length of string\r
+\r
+                                       CLR             CX                                      ; Length = 0\r
+ 0042  33 C9                1          xor             CX, CX          ; Set Register = 0\r
+ 0044  8B F2                           mov             SI, DX                          ; DS:SI = String data\r
+\r
+ 0046                          @@DPS_Scan_it:\r
+                                       \r
+ 0046  80 3C 00                                cmp             b [SI], 0                       ; Null Byte found?\r
+ 0049  74 04                           je              @@DPS_Got_Len           ; exit loop if so\r
+\r
+ 004B  41                              inc             CX                                      ; Len++\r
+ 004C  46                              inc             SI                                      ; Point to next char\r
+ 004D  EB F7                           jmp             s @@DPS_Scan_it         ; check again...\r
+\r
+ 004F                          @@DPS_Got_len:\r
+\r
+ 004F  E3 07                           jcxz    @DPS_Exit                       ; Don't Print if empty\r
+\r
+ 0051  BB 0001                         mov             BX, 1                           ; 1= DOS Handle for Display\r
+ 0054  B4 40                           mov             AH, 40h                         ; Write Text Function\r
+ 0056  CD 21                           int             21h                                     ; Call DOS to do it\r
+\r
+ 0058                          @DPS_Exit:\r
+ 0058  FC                              cld                                                     ; Reset Direction Flag          \r
+                                       POPx    DI, SI, DS, BP          ; Restore Saved Registers\r
+ 0059  5F                   1                  pop             DI                              ; Restore R1\r
+ 005A  5E                   2                  pop             SI                              ; Restore R1\r
+ 005B  1F                   3                  pop             DS                              ; Restore R1\r
+ 005C  5D                   4                  pop             BP                              ; Restore R1\r
+ 005D  CA 0002                         ret             2                                       ; Exit & Clean Up Stack\r
+\r
+ 0060                          DOS_PRINTS       ENDP\r
+\r
+\r
+                               ;=========================================\r
+                               ;void far pascal set_video_mode (int Mode)\r
+                               ;=========================================\r
+                               ;\r
+                               ; Sets the Video Mode through the BIOS\r
+                               ;\r
+\r
+                                       PUBLIC  SET_VIDEO_MODE\r
+\r
+ 000E                          SVM_Stack       STRUC\r
+ 0000  0000 0000 0000                                          DW      ?x4     ; DI, SI, DS, BP\r
+       0000\r
+ 0008  00000000                                                        DD      ?       ; Caller\r
+ 000C  00 00                           SVM_Mode        DB      ?,? ; Desired Video Mode\r
+                               SVM_Stack       ENDS\r
+\r
+\r
+ 0060                          SET_VIDEO_MODE  PROC    FAR\r
+\r
+                                       PUSHx   BP, DS, SI, DI          ; Preserve Important Registers\r
+ 0060  55                   1                  push    BP                              ; Save R1\r
+ 0061  1E                   2                  push    DS                              ; Save R1\r
+ 0062  56                   3                  push    SI                              ; Save R1\r
+ 0063  57                   4                  push    DI                              ; Save R1\r
+ 0064  8B EC                           mov             BP, SP                          ; Set up Stack Frame\r
+\r
+                                       CLR             AH                                      ; Function 0\r
+ 0066  32 E4                1          xor             AH, AH          ; Set Register = 0\r
+ 0068  8A 46 0C                                mov             AL, [BP].SVM_Mode       ; Get Mode #\r
+\r
+ 006B  CD 10                           int             10H                                     ; Change Video Modes\r
+\r
+ 006D                          @SVM_Exit:\r
+                                       POPx    DI, SI, DS, BP          ; Restore Saved Registers\r
+ 006D  5F                   1                  pop             DI                              ; Restore R1\r
+ 006E  5E                   2                  pop             SI                              ; Restore R1\r
+ 006F  1F                   3                  pop             DS                              ; Restore R1\r
+ 0070  5D                   4                  pop             BP                              ; Restore R1\r
+ 0071  CA 0002                         ret             2                                       ; Exit & Clean Up Stack\r
+\r
+ 0074                          SET_VIDEO_MODE  ENDP\r
+\r
+\r
+                               ;===================================\r
+                               ;int far pascal scan_keyboard (void)\r
+                               ;===================================\r
+                               ;\r
+                               ; Function to scan keyboard for a pressed key\r
+                               ;\r
+\r
+                                       PUBLIC  SCAN_KEYBOARD\r
+\r
+ 0074                          SCAN_KEYBOARD   PROC    FAR\r
+\r
+                                       PUSHx   BP, DS, SI, DI          ; Preserve Important Registers\r
+ 0074  55                   1                  push    BP                              ; Save R1\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/03/14 12:38:18\r
+c_utils.asm                                                 Page 2 - 1\r
+\r
+\r
+ 0075  1E                   2                  push    DS                              ; Save R1\r
+ 0076  56                   3                  push    SI                              ; Save R1\r
+ 0077  57                   4                  push    DI                              ; Save R1\r
+\r
+ 0078  B4 01                           mov             AH, 01H                         ; Function #1\r
+ 007A  CD 16                           INT             16H                                     ; Call Keyboard Driver\r
+ 007C  74 0C                           JZ              @SK_NO_KEY                      ; Exit if Zero flag set\r
+\r
+ 007E  B4 00                           mov             AH,     00H                             ; Remove Key from Buffer\r
+ 0080  CD 16                           INT             16H                                     ; Get Keycode in AX\r
+\r
+ 0082  0A C0                           OR              AL, AL                          ; Low Byte Set (Ascii?)\r
+ 0084  74 06                           JZ              @SK_Exit                        ; if not, it's a F-Key\r
+\r
+                                       CLR             AH                                      ; Clear ScanCode if Ascii\r
+ 0086  32 E4                1          xor             AH, AH          ; Set Register = 0\r
+ 0088  EB 02                           JMP             s @SK_Exit                      ; Return Key in AX\r
+\r
+ 008A                          @SK_NO_KEY:\r
+                                       CLR             AX                                      ; Return Nil (no Keypress)\r
+ 008A  33 C0                1          xor             AX, AX          ; Set Register = 0\r
+\r
+ 008C                          @SK_Exit:\r
+ 008C  FC                              cld                                                     ; Reset Direction Flag          \r
+                                       POPx    DI, SI, DS, BP          ; Restore Saved Registers\r
+ 008D  5F                   1                  pop             DI                              ; Restore R1\r
+ 008E  5E                   2                  pop             SI                              ; Restore R1\r
+ 008F  1F                   3                  pop             DS                              ; Restore R1\r
+ 0090  5D                   4                  pop             BP                              ; Restore R1\r
+ 0091  CB                              ret                                                     ; Exit & Clean Up Stack\r
+\r
+ 0092                          SCAN_KEYBOARD   ENDP\r
+\r
+\r
+                               ;========================================\r
+                               ;int far pascal random_int (int MaxValue)\r
+                               ;========================================\r
+                               ;\r
+                               ; Returns a pseudo-random number in the range of (0.. MaxInt-1)\r
+                               ;\r
+\r
+\r
+                                       PUBLIC  RANDOM_INT\r
+\r
+ 0008                          RI_Stack        STRUC\r
+ 0000  0000                                                    DW      ?       ; BP\r
+ 0002  00000000                                                        DD      ?       ; Caller\r
+ 0006  0000                            RI_MaxVal       DW      ?       ; Maximum Value to Return + 1\r
+                               RI_Stack        ENDS\r
+\r
+\r
+ 0092                          RANDOM_INT      PROC    FAR\r
+\r
+ 0092  55                              push    BP                                      ; Preserve Important Registers\r
+ 0093  8B EC                           mov             BP, SP                          ; Set up Stack Frame\r
+\r
+                                       CLR             BX                                      ; BX is the data index\r
+ 0095  33 DB                1          xor             BX, BX          ; Set Register = 0\r
+                                       CLR             CX                              ; CX is the accumulator\r
+ 0097  33 C9                1          xor             CX, CX          ; Set Register = 0\r
+\r
+                               REPT 3\r
+                                       mov             AX, RND_Seed[BX]        ; load the initial seed\r
+                                       mul             RND_Mult[BX]            ; multiply it\r
+                                       div             RND_ModV[BX]            ; and obtain the Mod value\r
+                                       mov             RND_Seed[BX], DX        ; save that for the next time\r
+\r
+                                       add             CX, DX                          ; add it into the accumulator\r
+                                       inc             BX\r
+                                       inc             BX                      ; point to the next set of values\r
+                               ENDM\r
+ 0099  8B 87 0000 R         1          mov             AX, RND_Seed[BX]        ; load the initial seed\r
+ 009D  F7 A7 0006 R         1          mul             RND_Mult[BX]            ; multiply it\r
+ 00A1  F7 B7 000C R         1          div             RND_ModV[BX]            ; and obtain the Mod value\r
+ 00A5  89 97 0000 R         1          mov             RND_Seed[BX], DX        ; save that for the next time\r
+ 00A9  03 CA                1          add             CX, DX                          ; add it into the accumulator\r
+ 00AB  43                   1          inc             BX\r
+ 00AC  43                   1          inc             BX                      ; point to the next set of values\r
+ 00AD  8B 87 0000 R         1          mov             AX, RND_Seed[BX]        ; load the initial seed\r
+ 00B1  F7 A7 0006 R         1          mul             RND_Mult[BX]            ; multiply it\r
+ 00B5  F7 B7 000C R         1          div             RND_ModV[BX]            ; and obtain the Mod value\r
+ 00B9  89 97 0000 R         1          mov             RND_Seed[BX], DX        ; save that for the next time\r
+ 00BD  03 CA                1          add             CX, DX                          ; add it into the accumulator\r
+ 00BF  43                   1          inc             BX\r
+ 00C0  43                   1          inc             BX                      ; point to the next set of values\r
+ 00C1  8B 87 0000 R         1          mov             AX, RND_Seed[BX]        ; load the initial seed\r
+ 00C5  F7 A7 0006 R         1          mul             RND_Mult[BX]            ; multiply it\r
+ 00C9  F7 B7 000C R         1          div             RND_ModV[BX]            ; and obtain the Mod value\r
+ 00CD  89 97 0000 R         1          mov             RND_Seed[BX], DX        ; save that for the next time\r
+ 00D1  03 CA                1          add             CX, DX                          ; add it into the accumulator\r
+ 00D3  43                   1          inc             BX\r
+ 00D4  43                   1          inc             BX                      ; point to the next set of values\r
+\r
+ 00D5  8B C1                           mov             AX, CX                          ; AX = Random #\r
+                                       CLR             DX                                      ; DX = 0\r
+ 00D7  33 D2                1          xor             DX, DX          ; Set Register = 0\r
+ 00D9  F7 76 06                                div             [BP].RI_MaxVal          ; DX = DX:AX / MAxVal Remainder\r
+\r
+ 00DC  8B C2                           mov             AX, DX\r
+\r
+ 00DE  5D                              pop             BP                                      ; Restore BP\r
+ 00DF  CA 0002                         ret             2                               ; back to BASIC with AX holding the result\r
+\r
+ 00E2                          RANDOM_INT      ENDP\r
+\r
+\r
+                               ;==================================\r
+                               ;void far pascal init_random (void)\r
+                               ;==================================\r
+                               ;\r
+                               ; Scrambles the psuedo-random number sequence\r
+                               ; (XOR's the seed value with the timer)\r
+                               ;\r
+\r
+                                       PUBLIC  INIT_RANDOM\r
+\r
+ 00E2                          INIT_RANDOM     PROC    FAR\r
+\r
+                                       CLR             AX                                      ; Segment = 0000\r
+ 00E2  33 C0                1          xor             AX, AX          ; Set Register = 0\r
+ 00E4  8E C0                           mov             ES, AX\r
+ 00E6  26: A1 046C                     mov             AX, ES:[046Ch]      ; Get Timer Lo Word\r
+\r
+ 00EA  31 06 0000 R                    xor             RND_Seed, AX            ; Scramble 1st Seed\r
+\r
+ 00EE  CB                              ret                                                     ; Exit & Clean Up Stack\r
+\r
+ 00EF                          INIT_RANDOM     ENDP\r
+\r
+                               ;=========================================\r
+                               ;int far pascal int_sqr (int X, int Round)\r
+                               ;=========================================\r
+                               ;\r
+                               ; Returns the Integer Square Root of (X)\r
+                               ; Round allows the return value to be rounded to the \r
+                               ; nearest integer value by passing 0x80.  Passing 0\r
+                               ; return the Integer Portion only.  The rounding amound is\r
+                               ; a number from 0 to 1 multiplied by 256, thus \r
+                               ; 0.5 * 0x100 = 0x80!\r
+                               ;\r
+\r
+ 000C                          ISQ_Stack       STRUC\r
+ 0000  0000 0000                                                       DW      ?,?     ; BP, DI\r
+ 0004  00000000                                                                DD      ?       ; Caller\r
+ 0008  0000                            ISQ_Round               DW      ?       ; Amount to Round Result * 256\r
+ 000A  0000                            ISQ_X                   DW      ?       ; "X"\r
+                               ISQ_Stack       ENDS\r
+\r
+                                       PUBLIC  INT_SQR\r
+\r
+ 00EF                          INT_SQR         PROC    FAR\r
+\r
+                                   PUSHx   BP, DI                              ; Save BP\r
+ 00EF  55                   1                  push    BP                              ; Save R1\r
+ 00F0  57                   2                  push    DI                              ; Save R1\r
+ 00F1  8B EC                       mov     BP, SP                              ; Set up Stack Frame\r
+\r
+ 00F3  33 C0                           xor     AX, AX                          ; {xor eax,eax}\r
+ 00F5  33 D2                           xor     DX, DX                          ; {xor edx,edx}\r
+ 00F7  8B 7E 0A                                mov     DI, [BP].ISQ_X          ; {mov edi,x}\r
+\r
+ 00FA  B9 0010                         mov     CX, 16                          ; {mov cx, 32}\r
+\r
+ 00FD                          @ISQ_L:\r
+\r
+ 00FD  D1 E7                           shl     DI, 1                           ; {shl edi,1}\r
+ 00FF  D1 D2                           rcl     DX, 1                           ; {rcl edx,1}\r
+ 0101  D1 E7                           shl     DI, 1                           ; {shl edi,1}\r
+ 0103  D1 D2                           rcl     DX, 1                           ; {rcl edx,1}\r
+ 0105  D1 E0                           shl     AX, 1                           ; {shl eax,1}\r
+ 0107  8B D8                           mov     BX, AX                          ; {mov ebx,eax}\r
+ 0109  D1 E3                           shl     BX, 1                           ; {shl ebx,1}\r
+ 010B  43                              inc     BX                                      ; {inc ebx}\r
+ 010C  3B D3                           cmp     DX, BX                          ; {cmp edx,ebx}\r
+ 010E  7C 03                           jl              @ISQ_S\r
+\r
+ 0110  2B D3                           sub     DX, BX                          ; {sub edx,ebx}\r
+ 0112  40                              inc     AX                                      ; {inc eax}\r
+\r
+ 0113                          @ISQ_S: \r
+ 0113  E2 E8                           loop    @ISQ_L\r
+\r
+ 0115  03 46 08                                add     ax, [BP].ISQ_Round      ; {add eax,$00008000}  \r
+                                                                                               ; {*round* result in hi word: ie. +0\r
+                               .5}\r
+ 0118  C1 E8 08                                shr     ax, 8                           ; {shr eax,16}  {to ax (result)}\r
+\r
+                                       POPx    DI, BP                          ; Restore Registers     \r
+ 011B  5F                   1                  pop             DI                              ; Restore R1\r
+ 011C  5D                   2                  pop             BP                              ; Restore R1\r
+ 011D  CA 0004                         ret             4                                       ; Exit\r
+\r
+ 0120                          INT_SQR         ENDP\r
+\r
+                               ;=================================\r
+                               ;int far pascal timer_count (void)\r
+                               ;=================================\r
+                               ;\r
+                               ; Returns the current timer value as an integer/long integer\r
+                               ;\r
+\r
+                                       PUBLIC  TIMER_COUNT\r
+\r
+ 0120                          TIMER_COUNT      PROC    FAR\r
+\r
+                                       CLR             AX                                      ; Segment = 0000\r
+ 0120  33 C0                1          xor             AX, AX          ; Set Register = 0\r
+ 0122  8E C0                           mov             ES, AX\r
+ 0124  26: A1 046C                     mov             AX, ES:[046Ch]      ; Get Timer Lo Word\r
+ 0128  26: 8B 16 046E                  mov             DX, ES:[046Eh]          ; Get Timer Hi Word\r
+ 012D  CB                              ret                                                     ; Exit & Clean Up Stack\r
+\r
+ 012E                          TIMER_COUNT      ENDP\r
+\r
+\r
+                                       END\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/03/14 12:38:18\r
+c_utils.asm                                                 Symbols 3 - 1\r
+\r
+\r
+\r
+\r
+Macros:\r
+\r
+                N a m e                 Type\r
+\r
+CLR  . . . . . . . . . . . . . .       Proc\r
+LOOPjz . . . . . . . . . . . . .       Proc\r
+LOOPx  . . . . . . . . . . . . .       Proc\r
+POPx . . . . . . . . . . . . . .       Proc\r
+PUSHx  . . . . . . . . . . . . .       Proc\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/03/14 12:38:18\r
+c_utils.asm                                                 Symbols 4 - 1\r
+\r
+\r
+\r
+\r
+Structures and Unions:\r
+\r
+                N a m e                  Size\r
+                                         Offset      Type\r
+\r
+DP_Stack . . . . . . . . . . . .        0010\r
+  DP_Text  . . . . . . . . . . .        000C        DWord\r
+ISQ_Stack  . . . . . . . . . . .        000C\r
+  ISQ_Round  . . . . . . . . . .        0008        Word\r
+  ISQ_X  . . . . . . . . . . . .        000A        Word\r
+RI_Stack . . . . . . . . . . . .        0008\r
+  RI_MaxVal  . . . . . . . . . .        0006        Word\r
+SVM_Stack  . . . . . . . . . . .        000E\r
+  SVM_Mode . . . . . . . . . . .        000C        Byte\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/03/14 12:38:18\r
+c_utils.asm                                                 Symbols 5 - 1\r
+\r
+\r
+\r
+\r
+Segments and Groups:\r
+\r
+                N a m e                 Size     Length   Align   Combine Class\r
+\r
+C_UTILS_TEXT . . . . . . . . . .       16 Bit   012E     Word    Public  'CODE'        \r
+DGROUP . . . . . . . . . . . . .       GROUP\r
+_DATA  . . . . . . . . . . . . .       16 Bit   0014     Word    Public  'DATA'        \r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/03/14 12:38:18\r
+c_utils.asm                                                 Symbols 6 - 1\r
+\r
+\r
+\r
+\r
+Procedures,  parameters and locals:\r
+\r
+                N a m e                 Type     Value    Attr\r
+\r
+DOS_PRINTS . . . . . . . . . . .       P Far    0039     C_UTILS_TEXT  Length= 0027 Public\r
+DOS_PRINT  . . . . . . . . . . .       P Far    0000     C_UTILS_TEXT  Length= 0039 Public\r
+INIT_RANDOM  . . . . . . . . . .       P Far    00E2     C_UTILS_TEXT  Length= 000D Public\r
+INT_SQR  . . . . . . . . . . . .       P Far    00EF     C_UTILS_TEXT  Length= 0031 Public\r
+RANDOM_INT . . . . . . . . . . .       P Far    0092     C_UTILS_TEXT  Length= 0050 Public\r
+SCAN_KEYBOARD  . . . . . . . . .       P Far    0074     C_UTILS_TEXT  Length= 001E Public\r
+SET_VIDEO_MODE . . . . . . . . .       P Far    0060     C_UTILS_TEXT  Length= 0014 Public\r
+TIMER_COUNT  . . . . . . . . . .       P Far    0120     C_UTILS_TEXT  Length= 000E Public\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/03/14 12:38:18\r
+c_utils.asm                                                 Symbols 7 - 1\r
+\r
+\r
+\r
+\r
+Symbols:\r
+\r
+                N a m e                 Type     Value    Attr\r
+\r
+?x3  . . . . . . . . . . . . . .       Text     ?,?,?\r
+?x4  . . . . . . . . . . . . . .       Text     ?,?,?,?\r
+@@DPS_Got_len  . . . . . . . . .       L Near   004F     C_UTILS_TEXT  \r
+@@DPS_Scan_it  . . . . . . . . .       L Near   0046     C_UTILS_TEXT  \r
+@@DP_Got_len . . . . . . . . . .       L Near   0016     C_UTILS_TEXT  \r
+@@DP_Scan_it . . . . . . . . . .       L Near   000D     C_UTILS_TEXT  \r
+@CodeSize  . . . . . . . . . . .       Number   0001h   \r
+@DPS_Exit  . . . . . . . . . . .       L Near   0058     C_UTILS_TEXT  \r
+@DataSize  . . . . . . . . . . .       Number   0000h   \r
+@ISQ_L . . . . . . . . . . . . .       L Near   00FD     C_UTILS_TEXT  \r
+@ISQ_S . . . . . . . . . . . . .       L Near   0113     C_UTILS_TEXT  \r
+@Interface . . . . . . . . . . .       Number   0000h   \r
+@Model . . . . . . . . . . . . .       Number   0004h   \r
+@No_Print  . . . . . . . . . . .       L Near   001F     C_UTILS_TEXT  \r
+@SK_Exit . . . . . . . . . . . .       L Near   008C     C_UTILS_TEXT  \r
+@SK_NO_KEY . . . . . . . . . . .       L Near   008A     C_UTILS_TEXT  \r
+@SVM_Exit  . . . . . . . . . . .       L Near   006D     C_UTILS_TEXT  \r
+@code  . . . . . . . . . . . . .       Text     C_UTILS_TEXT\r
+@data  . . . . . . . . . . . . .       Text     DGROUP\r
+@fardata?  . . . . . . . . . . .       Text     FAR_BSS\r
+@fardata . . . . . . . . . . . .       Text     FAR_DATA\r
+@stack . . . . . . . . . . . . .       Text     DGROUP\r
+CR_LF  . . . . . . . . . . . . .       Byte     0012     _DATA \r
+False  . . . . . . . . . . . . .       Number   0000h   \r
+RND_ModV . . . . . . . . . . . .       Word     000C     _DATA \r
+RND_Mult . . . . . . . . . . . .       Word     0006     _DATA \r
+RND_Seed . . . . . . . . . . . .       Word     0000     _DATA \r
+True . . . . . . . . . . . . . .       Number   -0001h   \r
+b  . . . . . . . . . . . . . . .       Text     BYTE PTR\r
+d  . . . . . . . . . . . . . . .       Text     DWORD PTR\r
+f  . . . . . . . . . . . . . . .       Text     FAR PTR\r
+nil  . . . . . . . . . . . . . .       Number   0000h   \r
+o  . . . . . . . . . . . . . . .       Text     OFFSET\r
+s  . . . . . . . . . . . . . . .       Text     SHORT\r
+w  . . . . . . . . . . . . . . .       Text     WORD PTR\r
+\r
+          0 Warnings\r
+          0 Errors\r
diff --git a/src/lib/modex/demos/c/c_utils.sbr b/src/lib/modex/demos/c/c_utils.sbr
new file mode 100755 (executable)
index 0000000..0301171
Binary files /dev/null and b/src/lib/modex/demos/c/c_utils.sbr differ
diff --git a/src/lib/modex/demos/c/makefile b/src/lib/modex/demos/c/makefile
new file mode 100755 (executable)
index 0000000..2c94d9b
--- /dev/null
@@ -0,0 +1,30 @@
+!ifdef __LINUX__
+REMOVECOMMAND=rm -f
+COPYCOMMAND=cp -f
+DIRSEP=/
+OBJ=o
+!else
+REMOVECOMMAND=del
+COPYCOMMAND=copy /y
+DIRSEP=\
+OBJ=obj
+!endif
+
+CFLAGS=-d2 -0 -mc
+
+all: x-demo.exe
+
+x-demo.exe: x-demo.$(OBJ) modex.$(OBJ) c_utils.$(OBJ)
+       wcl $(CFLAGS) x-demo.$(OBJ) modex.$(OBJ) c_utils.$(OBJ)
+x-demo.$(OBJ): x-demo.c
+       wcl -c $(CFLAGS) x-demo.c
+
+c_utils.$(OBJ): c_utils.asm
+       wcl -c $(CFLAGS) c_utils.asm
+modex.$(OBJ): modex.asm
+       wcl -c $(CFLAGS) modex.asm
+
+clean: .symbolic
+       @$(REMOVECOMMAND) x-demo.exe
+       @$(REMOVECOMMAND) *.$(OBJ)
+       @$(REMOVECOMMAND) *.err
diff --git a/src/lib/modex/demos/c/modex.asm b/src/lib/modex/demos/c/modex.asm
new file mode 100755 (executable)
index 0000000..f2b1b51
--- /dev/null
@@ -0,0 +1,3505 @@
+;========================================================\r
+; MODEX.ASM - A Complete Mode X Library\r
+;\r
+; Version 1.04 Release, 3 May 1993, By Matt Pritchard\r
+; With considerable input from Michael Abrash\r
+;\r
+; The following information is donated to the public domain in\r
+; the hopes that save other programmers much frustration.\r
+;\r
+; If you do use this code in a product, it would be nice if\r
+; you include a line like "Mode X routines by Matt Pritchard"\r
+; in the credits.\r
+;\r
+; =========================================================\r
+;\r
+; All of this code is designed to be assembled with MASM 5.10a\r
+; but TASM 3.0 could be used as well.\r
+;\r
+; The routines contained are designed for use in a MEDIUM model\r
+; program.  All Routines are FAR, and is assumed that a DGROUP\r
+; data segment exists and that DS will point to it on entry.\r
+;\r
+; For all routines, the AX, BX, CX, DX, ES and FLAGS registers\r
+; will not be preserved, while the DS, BP, SI and DI registers\r
+; will be preserved.\r
+;\r
+; Unless specifically noted, All Parameters are assumed to be\r
+; "PASSED BY VALUE".  That is, the actual value is placed on\r
+; the stack.  When a reference is passed it is assumed to be\r
+; a near pointer to a variable in the DGROUP segment.\r
+;\r
+; Routines that return a single 16-Bit integer value will\r
+; return that value in the AX register.\r
+;\r
+; This code will *NOT* run on an 8086/8088 because 80286+\r
+; specific instructions are used.   If you have an 8088/86\r
+; and VGA, you can buy an 80386-40 motherboard for about\r
+; $160 and move into the 90's.\r
+;\r
+; This code is reasonably optimized: Most drawing loops have\r
+; been unrolled once and memory references are minimized by\r
+; keeping stuff in registers when possible.\r
+;\r
+; Error Trapping varies by Routine.  No Clipping is performed\r
+; so the caller should verify that all coordinates are valid.\r
+;\r
+; Several Macros are used to simplify common 2 or 3 instruction\r
+; sequences.  Several Single letter Text Constants also\r
+; simplify common assembler expressions like "WORD PTR".\r
+;\r
+; ------------------ Mode X Variations ------------------\r
+;\r
+;  Mode #  Screen Size    Max Pages   Aspect Ratio (X:Y)\r
+;\r
+;    0      320 x 200      4 Pages         1.2:1\r
+;    1      320 x 400      2 Pages         2.4:1\r
+;    2      360 x 200      3 Pages        1.35:1\r
+;    3      360 x 400      1 Page          2.7:1\r
+;    4      320 x 240      3 Pages           1:1\r
+;    5      320 x 480      1 Page            2:1\r
+;    6      360 x 240      3 Pages       1.125:1\r
+;    7      360 x 480      1 Page         2.25:1\r
+;\r
+; -------------------- The Legal Stuff ------------------\r
+;\r
+; No warranty, either written or implied, is made as to\r
+; the accuracy and usability of this code product.  Use\r
+; at your own risk.  Batteries not included.  Pepperoni\r
+; and extra cheese available for an additional charge.\r
+;\r
+; ----------------------- The Author --------------------\r
+;\r
+; Matt Pritchard is a paid programmer who'd rather be\r
+; writing games.  He can be reached at: P.O. Box 140264,\r
+; Irving, TX  75014  USA.  Michael Abrash is a living\r
+; god, who now works for Bill Gates (Microsoft).\r
+;\r
+; -------------------- Revision History -----------------\r
+; 4-12-93: v1.02 - SET_POINT & READ_POINT now saves DI\r
+;          SET_MODEX now saves SI\r
+; 5-3-93:  v1.04 - added LOAD_DAC_REGISTERS and\r
+;          READ_DAC_REGISTERS.  Expanded CLR Macro\r
+;          to handle multiple registers\r
+;\r
+\r
+    PAGE    255, 132\r
+\r
+    .MODEL Huge\r
+    ;.286\r
+\r
+    ; ===== MACROS =====\r
+\r
+    ; Macro to OUT a 16 bit value to an I/O port\r
+\r
+OUT_16 MACRO Register, Value\r
+    IFDIFI <Register>, <DX>         ; If DX not setup\r
+        MOV     DX, Register        ; then Select Register\r
+    ENDIF\r
+    IFDIFI <Value>, <AX>            ; If AX not setup\r
+        MOV     AX, Value           ; then Get Data Value\r
+    ENDIF\r
+        OUT     DX, AX              ; Set I/O Register(s)\r
+ENDM\r
+\r
+    ; Macro to OUT a 8 bit value to an I/O Port\r
+\r
+OUT_8 MACRO Register, Value\r
+    IFDIFI <Register>, <DX>         ; If DX not setup\r
+        MOV     DX, Register        ; then Select Register\r
+    ENDIF\r
+    IFDIFI <Value>, <AL>            ; If AL not Setup\r
+        MOV     AL, Value           ; then Get Data Value\r
+    ENDIF\r
+        OUT     DX, AL              ; Set I/O Register\r
+ENDM\r
+\r
+    ; macros to PUSH and POP multiple registers\r
+\r
+; PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+;     IFNB <R1>\r
+;         PUSH    R1              ; Save R1\r
+;         PUSHx   R2, R3, R4, R5, R6, R7, R8\r
+;     ENDIF\r
+; ENDM\r
+;\r
+; POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+;     IFNB <R1>\r
+;         POP     R1              ; Restore R1\r
+;         POPx    R2, R3, R4, R5, R6, R7, R8\r
+;     ENDIF\r
+; ENDM\r
+\r
+    ; Macro to Clear Registers to 0\r
+\r
+; CLR MACRO Register, R2, R3, R4;, R5, R6\r
+;     IFNB <Register>\r
+;         XOR     Register, Register      ; Set Register = 0\r
+;         CLR R2, R3, R4;, R5, R6\r
+;     ENDIF\r
+; ENDM\r
+\r
+    ; Macros to Decrement Counter & Jump on Condition\r
+\r
+LOOPx MACRO Register, Destination\r
+    DEC     Register                ; Counter--\r
+    JNZ     Destination             ; Jump if not 0\r
+ENDM\r
+\r
+LOOPjz MACRO Register, Destination\r
+    DEC     Register                ; Counter--\r
+    JZ      Destination             ; Jump if 0\r
+ENDM\r
+\r
+\r
+    ; ===== General Constants =====\r
+\r
+    False   EQU 0\r
+    True    EQU -1\r
+    nil     EQU 0\r
+\r
+    b       EQU BYTE PTR\r
+    w       EQU WORD PTR\r
+    d       EQU DWORD PTR\r
+    o       EQU OFFSET\r
+    f       EQU FAR PTR\r
+    s       EQU SHORT\r
+    ?x1     EQU <?>\r
+\r
+    ; ===== VGA Register Values =====\r
+\r
+    VGA_Segment     EQU 0A000h  ; Vga Memory Segment\r
+\r
+    ATTRIB_Ctrl     EQU 03C0h   ; VGA Attribute Controller\r
+    GC_Index        EQU 03CEh   ; VGA Graphics Controller\r
+    SC_Index        EQU 03C4h   ; VGA Sequencer Controller\r
+    SC_Data         EQU 03C5h   ; VGA Sequencer Data Port\r
+    CRTC_Index      EQU 03D4h   ; VGA CRT Controller\r
+    CRTC_Data       EQU 03D5h   ; VGA CRT Controller Data\r
+    MISC_OUTPUT     EQU 03C2h   ; VGA Misc Register\r
+    INPUT_1         EQU 03DAh   ; Input Status #1 Register\r
+\r
+    DAC_WRITE_ADDR  EQU 03C8h   ; VGA DAC Write Addr Register\r
+    DAC_READ_ADDR   EQU 03C7h   ; VGA DAC Read Addr Register\r
+    PEL_DATA_REG    EQU 03C9h   ; VGA DAC/PEL data Register R/W\r
+\r
+    PIXEL_PAN_REG   EQU 033h    ; Attrib Index: Pixel Pan Reg\r
+    MAP_MASK        EQU 002h    ; Sequ Index: Write Map Mask reg\r
+    READ_MAP        EQU 004h    ; GC Index: Read Map Register\r
+    START_DISP_HI   EQU 00Ch    ; CRTC Index: Display Start Hi\r
+    START_DISP_LO   EQU 00Dh    ; CRTC Index: Display Start Lo\r
+\r
+    MAP_MASK_PLANE1 EQU 00102h  ; Map Register + Plane 1\r
+    MAP_MASK_PLANE2 EQU 01102h  ; Map Register + Plane 1\r
+    ALL_PLANES_ON   EQU 00F02h  ; Map Register + All Bit Planes\r
+\r
+    CHAIN4_OFF      EQU 00604h  ; Chain 4 mode Off\r
+    ASYNC_RESET     EQU 00100h  ; (A)synchronous Reset\r
+    SEQU_RESTART    EQU 00300h  ; Sequencer Restart\r
+\r
+    LATCHES_ON      EQU 00008h  ; Bit Mask + Data from Latches\r
+    LATCHES_OFF     EQU 0FF08h  ; Bit Mask + Data from CPU\r
+\r
+    VERT_RETRACE    EQU 08h     ; INPUT_1: Vertical Retrace Bit\r
+    PLANE_BITS      EQU 03h     ; Bits 0-1 of Xpos = Plane #\r
+    ALL_PLANES      EQU 0Fh     ; All Bit Planes Selected\r
+    CHAR_BITS       EQU 0Fh     ; Bits 0-3 of Character Data\r
+\r
+    GET_CHAR_PTR    EQU 01130h  ; VGA BIOS Func: Get Char Set\r
+    ROM_8x8_Lo      EQU 03h     ; ROM 8x8 Char Set Lo Pointer\r
+    ROM_8x8_Hi      EQU 04h     ; ROM 8x8 Char Set Hi Pointer\r
+\r
+    ; Constants Specific for these routines\r
+\r
+    NUM_MODES       EQU 8       ; # of Mode X Variations\r
+\r
+    ; Specific Mode Data Table format...\r
+\r
+Mode_Data_Table STRUC\r
+    M_MiscR         DB  ?       ; Value of MISC_OUTPUT register\r
+    M_Pages         DB  ?       ; Maximum Possible # of pages\r
+    M_XSize         DW  ?       ; X Size Displayed on screen\r
+    M_YSize         DW  ?       ; Y Size Displayed on screen\r
+    M_XMax          DW  ?       ; Maximum Possible X Size\r
+    M_YMax          DW  ?       ; Maximum Possible Y Size\r
+    M_CRTC          DW  ?       ; Table of CRTC register values\r
+Mode_Data_Table ENDS\r
+\r
+    ; ===== DGROUP STORAGE NEEDED (42 BYTES) =====\r
+\r
+    .DATA?\r
+\r
+SCREEN_WIDTH    DW  0       ; Width of a line in Bytes\r
+SCREEN_HEIGHT   DW  0       ; Vertical Height in Pixels\r
+\r
+LAST_PAGE       DW  0       ; # of Display Pages\r
+PAGE_ADDR       DW  4 DUP (0)   ; Offsets to start of each page\r
+\r
+PAGE_SIZE       DW  0       ; Size of Page in Addr Bytes\r
+\r
+DISPLAY_PAGE    DW  0       ; Page # currently displayed\r
+ACTIVE_PAGE     DW  0       ; Page # currently active\r
+\r
+CURRENT_PAGE    DW  0       ; Offset of current Page\r
+CURRENT_SEGMENT DW  0       ; Segment of VGA memory\r
+\r
+CURRENT_XOFFSET DW  0       ; Current Display X Offset\r
+CURRENT_YOFFSET DW  0       ; Current Display Y Offset\r
+\r
+CURRENT_MOFFSET DW  0       ; Current Start Offset\r
+\r
+MAX_XOFFSET     DW  0       ; Current Display X Offset\r
+MAX_YOFFSET     DW  0       ; Current Display Y Offset\r
+\r
+CHARSET_LOW     DW  0, 0    ; Far Ptr to Char Set: 0-127\r
+CHARSET_HI      DW  0, 0    ; Far Ptr to Char Set: 128-255\r
+\r
+    .CODE\r
+\r
+    ; ===== DATA TABLES =====\r
+\r
+    ; Data Tables, Put in Code Segment for Easy Access\r
+    ; (Like when all the other Segment Registers are in\r
+    ; use!!) and reduced DGROUP requirements...\r
+\r
+    ; Bit Mask Tables for Left/Right/Character Masks\r
+\r
+Left_Clip_Mask      DB  0FH, 0EH, 0CH, 08H\r
+\r
+Right_Clip_Mask     DB  01H, 03H, 07H, 0FH\r
+\r
+    ; Bit Patterns for converting character fonts\r
+\r
+Char_Plane_Data     DB  00H,08H,04H,0CH,02H,0AH,06H,0EH\r
+                    DB  01H,09H,05H,0DH,03H,0BH,07H,0FH\r
+\r
+        ; CRTC Register Values for Various Configurations\r
+\r
+MODE_Single_Line:       ; CRTC Setup Data for 400/480 Line modes\r
+        DW  04009H      ; Cell Height (1 Scan Line)\r
+        DW  00014H      ; Dword Mode off\r
+        DW  0E317H      ; turn on Byte Mode\r
+        DW  nil         ; End of CRTC Data for 400/480 Line Mode\r
+\r
+MODE_Double_Line:       ; CRTC Setup Data for 200/240 Line modes\r
+        DW  04109H      ; Cell Height (2 Scan Lines)\r
+        DW  00014H      ; Dword Mode off\r
+        DW  0E317H      ; turn on Byte Mode\r
+        DW  nil         ; End of CRTC Data for 200/240 Line Mode\r
+\r
+MODE_320_Wide:          ; CRTC Setup Data for 320 Horz Pixels\r
+        DW  05F00H      ; Horz total\r
+        DW  04F01H      ; Horz Displayed\r
+        DW  05002H      ; Start Horz Blanking\r
+        DW  08203H      ; End Horz Blanking\r
+        DW  05404H      ; Start H Sync\r
+        DW  08005H      ; End H Sync\r
+        DW  nil         ; End of CRTC Data for 320 Horz pixels\r
+\r
+MODE_360_Wide:          ; CRTC Setup Data for 360 Horz Pixels\r
+        DW  06B00H      ; Horz total\r
+        DW  05901H      ; Horz Displayed\r
+        DW  05A02H      ; Start Horz Blanking\r
+        DW  08E03H      ; End Horz Blanking\r
+        DW  05E04H      ; Start H Sync\r
+        DW  08A05H      ; End H Sync\r
+        DW  nil         ; End of CRTC Data for 360 Horz pixels\r
+\r
+MODE_200_Tall:\r
+MODE_400_Tall:          ; CRTC Setup Data for 200/400 Line modes\r
+        DW  0BF06H      ; Vertical Total\r
+        DW  01F07H      ; Overflow\r
+        DW  09C10H      ; V Sync Start\r
+        DW  08E11H      ; V Sync End/Prot Cr0 Cr7\r
+        DW  08F12H      ; Vertical Displayed\r
+        DW  09615H      ; V Blank Start\r
+        DW  0B916H      ; V Blank End\r
+        DW  nil         ; End of CRTC Data for 200/400 Lines\r
+\r
+MODE_240_Tall:\r
+MODE_480_Tall:          ; CRTC Setup Data for 240/480 Line modes\r
+        DW  00D06H      ; Vertical Total\r
+        DW  03E07H      ; Overflow\r
+        DW  0EA10H      ; V Sync Start\r
+        DW  08C11H      ; V Sync End/Prot Cr0 Cr7\r
+        DW  0DF12H      ; Vertical Displayed\r
+        DW  0E715H      ; V Blank Start\r
+        DW  00616H      ; V Blank End\r
+        DW  nil         ; End of CRTC Data for 240/480 Lines\r
+\r
+        ; Table of Display Mode Tables\r
+\r
+MODE_TABLE:\r
+        DW  o MODE_320x200, o MODE_320x400\r
+        DW  o MODE_360x200, o MODE_360x400\r
+        DW  o MODE_320x240, o MODE_320x480\r
+        DW  o MODE_360x240, o MODE_360x480\r
+\r
+        ; Table of Display Mode Components\r
+\r
+MODE_320x200:           ; Data for 320 by 200 Pixels\r
+\r
+        DB  063h        ; 400 scan Lines & 25 Mhz Clock\r
+        DB  4           ; Maximum of 4 Pages\r
+        DW  320, 200    ; Displayed Pixels (X,Y)\r
+        DW  1302, 816   ; Max Possible X and Y Sizes\r
+\r
+        DW  o MODE_320_Wide, o MODE_200_Tall\r
+        DW  o MODE_Double_Line, nil\r
+\r
+MODE_320x400:           ; Data for 320 by 400 Pixels\r
+\r
+        DB  063h        ; 400 scan Lines & 25 Mhz Clock\r
+        DB  2           ; Maximum of 2 Pages\r
+        DW  320, 400    ; Displayed Pixels X,Y\r
+        DW  648, 816    ; Max Possible X and Y Sizes\r
+\r
+        DW  o MODE_320_Wide, o MODE_400_Tall\r
+        DW  o MODE_Single_Line, nil\r
+\r
+MODE_360x240:           ; Data for 360 by 240 Pixels\r
+\r
+        DB  0E7h        ; 480 scan Lines & 28 Mhz Clock\r
+        DB  3           ; Maximum of 3 Pages\r
+        DW  360, 240    ; Displayed Pixels X,Y\r
+        DW  1092, 728   ; Max Possible X and Y Sizes\r
+\r
+        DW  o MODE_360_Wide, o MODE_240_Tall\r
+        DW  o MODE_Double_Line , nil\r
+\r
+MODE_360x480:           ; Data for 360 by 480 Pixels\r
+\r
+        DB  0E7h        ; 480 scan Lines & 28 Mhz Clock\r
+        DB  1           ; Only 1 Page Possible\r
+        DW  360, 480    ; Displayed Pixels X,Y\r
+        DW  544, 728    ; Max Possible X and Y Sizes\r
+\r
+        DW  o MODE_360_Wide, o MODE_480_Tall\r
+        DW  o MODE_Single_Line , nil\r
+\r
+MODE_320x240:           ; Data for 320 by 240 Pixels\r
+\r
+        DB  0E3h        ; 480 scan Lines & 25 Mhz Clock\r
+        DB  3           ; Maximum of 3 Pages\r
+        DW  320, 240    ; Displayed Pixels X,Y\r
+        DW  1088, 818   ; Max Possible X and Y Sizes\r
+\r
+        DW  o MODE_320_Wide, o MODE_240_Tall\r
+        DW  o MODE_Double_Line, nil\r
+\r
+MODE_320x480:           ; Data for 320 by 480 Pixels\r
+\r
+        DB  0E3h        ; 480 scan Lines & 25 Mhz Clock\r
+        DB  1           ; Only 1 Page Possible\r
+        DW  320, 480    ; Displayed Pixels X,Y\r
+        DW  540, 818    ; Max Possible X and Y Sizes\r
+\r
+        DW  o MODE_320_WIDE, o MODE_480_Tall\r
+        DW  o MODE_Single_Line, nil\r
+\r
+MODE_360x200:           ; Data for 360 by 200 Pixels\r
+\r
+        DB  067h        ; 400 scan Lines & 28 Mhz Clock\r
+        DB  3           ; Maximum of 3 Pages\r
+        DW  360, 200    ; Displayed Pixels (X,Y)\r
+        DW  1302, 728   ; Max Possible X and Y Sizes\r
+\r
+        DW  o MODE_360_Wide, MODE_200_Tall\r
+        DW  o MODE_Double_Line, nil\r
+\r
+MODE_360x400:           ; Data for 360 by 400 Pixels\r
+\r
+        DB  067h        ; 400 scan Lines & 28 Mhz Clock\r
+        DB  1           ; Maximum of 1 Pages\r
+        DW  360, 400    ; Displayed Pixels X,Y\r
+        DW  648, 816    ; Max Possible X and Y Sizes\r
+\r
+        DW  o MODE_360_Wide, MODE_400_Tall\r
+        DW  o MODE_Single_Line, nil\r
+\r
+\r
+    ; ===== MODE X SETUP ROUTINES =====\r
+\r
+;======================================================\r
+;SET_VGA_MODEX% (ModeType%, MaxXPos%, MaxYpos%, Pages%)\r
+;======================================================\r
+;\r
+; Sets Up the specified version of Mode X.  Allows for\r
+; the setup of multiple video pages, and a virtual\r
+; screen which can be larger than the displayed screen\r
+; (which can then be scrolled a pixel at a time)\r
+;\r
+; ENTRY: ModeType = Desired Screen Resolution (0-7)\r
+;\r
+;     0 =  320 x 200, 4 Pages max,   1.2:1 Aspect Ratio\r
+;     1 =  320 x 400, 2 Pages max,   2.4:1 Aspect Ratio\r
+;     2 =  360 x 200, 3 Pages max,  1.35:1 Aspect Ratio\r
+;     3 =  360 x 400, 1 Page  max,   2.7:1 Aspect Ratio\r
+;     4 =  320 x 240, 3 Pages max,     1:1 Aspect Ratio\r
+;     5 =  320 x 480, 1 Page  max,     2:1 Aspect Ratio\r
+;     6 =  360 x 240, 3 Pages max, 1.125:1 Aspect Ratio\r
+;     7 =  360 x 480, 1 Page  max,  2.25:1 Aspect Ratio\r
+;\r
+;        MaxXpos = The Desired Virtual Screen Width\r
+;        MaxYpos = The Desired Virtual Screen Height\r
+;        Pages   = The Desired # of Video Pages\r
+;\r
+; EXIT:  AX = Success Flag:   >0 = Failure / 0 = Success\r
+;\r
+\r
+SVM_STACK   STRUC\r
+    SVM_Table   DW  ?   ; Offset of Mode Info Table\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DD  ?   ; Caller\r
+    SVM_Pages   DW  ?   ; # of Screen Pages desired\r
+    SVM_Ysize   DW  ?   ; Vertical Screen Size Desired\r
+    SVM_Xsize   DW  ?   ; Horizontal Screen Size Desired\r
+    SVM_Mode    DW  ?   ; Display Resolution Desired\r
+SVM_STACK   ENDS\r
+\r
+    PUBLIC  SET_VGA_MODEX\r
+\r
+SET_VGA_MODEX   PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+       push    di\r
+    SUB     SP, 2               ; Allocate workspace\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    ; Check Legality of Mode Request....\r
+\r
+    MOV     BX, [BP].SVM_Mode   ; Get Requested Mode #\r
+    CMP     BX, NUM_MODES       ; Is it 0..7?\r
+    JAE     @SVM_BadModeSetup1   ; If Not, Error out\r
+\r
+    SHL     BX, 1                   ; Scale BX\r
+    MOV     SI, w MODE_TABLE[BX]    ; CS:SI -> Mode Info\r
+    MOV     [BP].SVM_Table, SI      ; Save ptr for later use\r
+\r
+    ; Check # of Requested Display Pages\r
+\r
+    MOV     CX, [BP].SVM_Pages  ; Get # of Requested Pages\r
+    ;CLR       CH                  ; Set Hi Word = 0!\r
+    mov        ch,0                  ; Set Hi Word = 0!\r
+    CMP     CL, CS:[SI].M_Pages ; Check # Pages for mode\r
+    JA      @SVM_BadModeSetup2   ; Report Error if too Many Pages\r
+    JCXZ    @SVM_BadModeSetup3   ; Report Error if 0 Pages\r
+\r
+    ; Check Validity of X Size\r
+\r
+    AND     [BP].SVM_XSize, 0FFF8h  ; X size Mod 8 Must = 0\r
+\r
+    MOV     AX, [BP].SVM_XSize  ; Get Logical Screen Width\r
+    CMP     AX, CS:[SI].M_XSize ; Check against Displayed X\r
+    JB      @SVM_BadModeSetup4   ; Report Error if too small\r
+    CMP     AX, CS:[SI].M_XMax  ; Check against Max X\r
+    JA      @SVM_BadModeSetup5   ; Report Error if too big\r
+\r
+    ; Check Validity of Y Size\r
+\r
+    MOV     BX, [BP].SVM_YSize  ; Get Logical Screen Height\r
+    CMP     BX, CS:[SI].M_YSize ; Check against Displayed Y\r
+    JB      @SVM_BadModeSetup6   ; Report Error if too small\r
+    CMP     BX, CS:[SI].M_YMax  ; Check against Max Y\r
+    JA      @SVM_BadModeSetup7   ; Report Error if too big\r
+\r
+    ; Enough memory to Fit it all?\r
+\r
+    SHR     AX, 1               ; # of Bytes:Line = XSize/4\r
+    SHR     AX, 1               ; # of Bytes:Line = XSize/4\r
+    MUL     CX                  ; AX = Bytes/Line * Pages\r
+    MUL     BX                  ; DX:AX = Total VGA mem needed\r
+    JNO     @SVM_Continue       ; Exit if Total Size > 256K\r
+\r
+    DEC     DX                  ; Was it Exactly 256K???\r
+    OR      DX, AX              ; (DX = 1, AX = 0000)\r
+    JZ      @SVM_Continue       ; if so, it's valid...\r
+\r
+       jmp      @SVM_Continue;0000\r
+\r
+@SVM_BadModeSetup:\r
+    mov ax,8                  ; Return Value = False\r
+    JMP     @SVM_Exit           ; Normal Exit\r
+@SVM_BadModeSetup1:\r
+    mov ax,1                  ; Return Value = False\r
+    JMP     @SVM_Exit           ; Normal Exit\r
+@SVM_BadModeSetup2:\r
+    mov ax,2                  ; Return Value = False\r
+    JMP     @SVM_Exit           ; Normal Exit\r
+@SVM_BadModeSetup3:\r
+    mov ax,3                  ; Return Value = False\r
+    JMP     @SVM_Exit           ; Normal Exit\r
+@SVM_BadModeSetup4:\r
+    mov ax,4                  ; Return Value = False\r
+    JMP     @SVM_Exit           ; Normal Exit\r
+@SVM_BadModeSetup5:\r
+    mov ax,5                  ; Return Value = False\r
+    JMP     @SVM_Exit           ; Normal Exit\r
+@SVM_BadModeSetup6:\r
+    mov ax,6                  ; Return Value = False\r
+    JMP     @SVM_Exit           ; Normal Exit\r
+@SVM_BadModeSetup7:\r
+    mov ax,7                  ; Return Value = False\r
+    JMP     @SVM_Exit           ; Normal Exit\r
+\r
+@SVM_Continue:\r
+\r
+    MOV     AX, 13H             ; Start with Mode 13H\r
+    INT     10H                 ; Let BIOS Set Mode\r
+\r
+    OUT_16  SC_INDEX, CHAIN4_OFF            ; Disable Chain 4 Mode\r
+    OUT_16  SC_INDEX, ASYNC_RESET           ; (A)synchronous Reset\r
+    OUT_8   MISC_OUTPUT, CS:[SI].M_MiscR    ; Set New Timing/Size\r
+    OUT_16  SC_INDEX, SEQU_RESTART          ; Restart Sequencer ...\r
+\r
+    OUT_8   CRTC_INDEX, 11H     ; Select Vert Retrace End Register\r
+    INC     DX                  ; Point to Data\r
+    IN      AL, DX              ; Get Value, Bit 7 = Protect\r
+    AND     AL, 7FH             ; Mask out Write Protect\r
+    OUT     DX, AL              ; And send it back\r
+\r
+    MOV     DX, CRTC_INDEX      ; Vga Crtc Registers\r
+    ADD     SI, M_CRTC          ; SI -> CRTC Parameter Data\r
+\r
+    ; Load Tables of CRTC Parameters from List of Tables\r
+\r
+@SVM_Setup_Table:\r
+\r
+    MOV     DI, CS:[SI]         ; Get Pointer to CRTC Data Tbl\r
+    ADD     SI, 2               ; Point to next Ptr Entry\r
+    OR      DI, DI              ; A nil Ptr means that we have\r
+    JZ      @SVM_Set_Data       ; finished CRTC programming\r
+\r
+@SVM_Setup_CRTC:\r
+    MOV     AX, CS:[DI]         ; Get CRTC Data from Table\r
+    ADD     DI, 2               ; Advance Pointer\r
+    OR      AX, AX              ; At End of Data Table?\r
+    JZ      @SVM_Setup_Table    ; If so, Exit & get next Table\r
+\r
+    OUT     DX, AX              ; Reprogram VGA CRTC reg\r
+    JMP     s @SVM_Setup_CRTC   ; Process Next Table Entry\r
+\r
+    ; Initialize Page & Scroll info, DI = 0\r
+\r
+@SVM_Set_Data:\r
+    MOV     DISPLAY_PAGE, DI    ; Display Page = 0\r
+    MOV     ACTIVE_PAGE, DI     ; Active Page = 0\r
+    MOV     CURRENT_PAGE, DI    ; Current Page (Offset) = 0\r
+    MOV     CURRENT_XOFFSET, DI ; Horz Scroll Index = 0\r
+    MOV     CURRENT_YOFFSET, DI ; Vert Scroll Index = 0\r
+    MOV     CURRENT_MOFFSET, DI ; Memory Scroll Index = 0\r
+\r
+    MOV     AX, VGA_SEGMENT     ; Segment for VGA memory\r
+    MOV     CURRENT_SEGMENT, AX ; Save for Future LES's\r
+\r
+    ; Set Logical Screen Width, X Scroll and Our Data\r
+\r
+    MOV     SI, [BP].SVM_Table  ; Get Saved Ptr to Mode Info\r
+    MOV     AX, [BP].SVM_Xsize  ; Get Display Width\r
+\r
+    MOV     CX, AX              ; CX = Logical Width\r
+    SUB     CX, CS:[SI].M_XSize ; CX = Max X Scroll Value\r
+    MOV     MAX_XOFFSET, CX     ; Set Maximum X Scroll\r
+\r
+    SHR     AX, 1               ; Bytes = Pixels / 4\r
+    SHR     AX, 1               ; Bytes = Pixels / 4\r
+    MOV     SCREEN_WIDTH, AX    ; Save Width in Pixels\r
+\r
+    SHR     AX, 1               ; Offset Value = Bytes / 2\r
+    MOV     AH, 13h             ; CRTC Offset Register Index\r
+    XCHG    AL, AH              ; Switch format for OUT\r
+    OUT     DX, AX              ; Set VGA CRTC Offset Reg\r
+\r
+    ; Setup Data table, Y Scroll, Misc for Other Routines\r
+\r
+    MOV     AX, [BP].SVM_Ysize  ; Get Logical Screen Height\r
+\r
+    MOV     CX, AX              ; CX = Logical Height\r
+    SUB     BX, CS:[SI].M_YSize ; CX = Max Y Scroll Value\r
+    MOV     MAX_YOFFSET, CX     ; Set Maximum Y Scroll\r
+\r
+    MOV     SCREEN_HEIGHT, AX   ; Save Height in Pixels\r
+    MUL     SCREEN_WIDTH        ; AX = Page Size in Bytes,\r
+    MOV     PAGE_SIZE, AX       ; Save Page Size\r
+\r
+    MOV     CX, [BP].SVM_Pages  ; Get # of Pages\r
+    MOV     LAST_PAGE, CX       ; Save # of Pages\r
+\r
+    mov bx,0                  ; Page # = 0\r
+    MOV     DX, BX              ; Page 0 Offset = 0\r
+\r
+@SVM_Set_Pages:\r
+\r
+    MOV     PAGE_ADDR[BX], DX   ; Set Page #(BX) Offset\r
+    ADD     BX, 2               ; Page#++\r
+    ADD     DX, AX              ; Compute Addr of Next Page\r
+    LOOPx   CX, @SVM_Set_Pages  ; Loop until all Pages Set\r
+\r
+    ; Clear VGA Memory\r
+\r
+    OUT_16  SC_INDEX, ALL_PLANES_ON ; Select All Planes\r
+    LES     DI, d CURRENT_PAGE      ; -> Start of VGA memory\r
+\r
+    mov ax,0                  ; AX = 0\r
+    CLD                         ; Block Xfer Forwards\r
+    MOV     CX, 8000H           ; 32K * 4 * 2 = 256K\r
+    REP     STOSW               ; Clear dat memory!\r
+\r
+    ; Setup Font Pointers\r
+\r
+    MOV     BH, ROM_8x8_Lo      ; Ask for 8x8 Font, 0-127\r
+    MOV     AX, GET_CHAR_PTR    ; Service to Get Pointer\r
+    INT     10h                 ; Call VGA BIOS\r
+\r
+    MOV     CHARSET_LOW, BP     ; Save Char Set Offset\r
+    MOV     CHARSET_LOW+2, ES   ; Save Char Set Segment\r
+\r
+    MOV     BH, ROM_8x8_Hi      ; Ask for 8x8 Font, 128-255\r
+    MOV     AX, GET_CHAR_PTR    ; Service to Get Pointer\r
+    INT     10h                 ; Call VGA BIOS\r
+\r
+    MOV     CHARSET_HI, BP      ; Save Char Set Offset\r
+    MOV     CHARSET_HI+2, ES    ; Save Char Set Segment\r
+\r
+    MOV     AX, True            ; Return Success Code\r
+\r
+@SVM_EXIT:\r
+    ADD     SP, 2               ; Deallocate workspace\r
+    ;POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    RET     8                   ; Exit & Clean Up Stack\r
+\r
+SET_VGA_MODEX   ENDP\r
+\r
+\r
+;==================\r
+;SET_MODEX% (Mode%)\r
+;==================\r
+;\r
+; Quickie Mode Set - Sets Up Mode X to Default Configuration\r
+;\r
+; ENTRY: ModeType = Desired Screen Resolution (0-7)\r
+;        (See SET_VGA_MODEX for list)\r
+;\r
+; EXIT:  AX = Success Flag:   0 = Failure / -1= Success\r
+;\r
+\r
+SM_STACK    STRUC\r
+                DW  ?,? ; BP, SI\r
+                DD  ?   ; Caller\r
+    SM_Mode     DW  ?   ; Desired Screen Resolution\r
+SM_STACK    ENDS\r
+\r
+    PUBLIC  SET_MODEX\r
+\r
+SET_MODEX   PROC    FAR\r
+\r
+    ;PUSHx   BP, SI              ; Preserve Important registers\r
+    push       bp\r
+       push    si\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    mov ax,0                  ; Assume Failure\r
+    MOV     BX, [BP].SM_Mode    ; Get Desired Mode #\r
+    CMP     BX, NUM_MODES       ; Is it a Valid Mode #?\r
+    JAE     @SMX_Exit           ; If Not, don't Bother\r
+\r
+    PUSH    BX                  ; Push Mode Parameter\r
+\r
+    SHL     BX, 1                   ; Scale BX to word Index\r
+    MOV     SI, w MODE_TABLE[BX]    ; CS:SI -> Mode Info\r
+\r
+    PUSH    CS:[SI].M_XSize     ; Push Default X Size\r
+    PUSH    CS:[SI].M_Ysize     ; Push Default Y size\r
+    MOV     AL, CS:[SI].M_Pages ; Get Default # of Pages\r
+    mov ah,0                  ; Hi Byte = 0\r
+    PUSH    AX                  ; Push # Pages\r
+\r
+    CALL    f SET_VGA_MODEX     ; Set up Mode X!\r
+\r
+@SMX_Exit:\r
+    ;POPx    SI, BP              ; Restore Registers\r
+       pop     si\r
+       pop     bp\r
+    RET     2                   ; Exit & Clean Up Stack\r
+\r
+SET_MODEX   ENDP\r
+\r
+\r
+    ; ===== BASIC GRAPHICS PRIMITIVES =====\r
+\r
+;============================\r
+;CLEAR_VGA_SCREEN (ColorNum%)\r
+;============================\r
+;\r
+; Clears the active display page\r
+;\r
+; ENTRY: ColorNum = Color Value to fill the page with\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+CVS_STACK   STRUC\r
+                DW  ?,? ; DI, BP\r
+                DD  ?   ; Caller\r
+    CVS_COLOR   DB  ?,? ; Color to Set Screen to\r
+CVS_STACK   ENDS\r
+\r
+    PUBLIC  CLEAR_VGA_SCREEN\r
+\r
+CLEAR_VGA_SCREEN    PROC    FAR\r
+\r
+    ;PUSHx   BP, DI              ; Preserve Important Registers\r
+    push       bp\r
+       push    di\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    OUT_16  SC_INDEX, ALL_PLANES_ON ; Select All Planes\r
+    LES     DI, d CURRENT_PAGE      ; Point to Active VGA Page\r
+\r
+    MOV     AL, [BP].CVS_COLOR  ; Get Color\r
+    MOV     AH, AL              ; Copy for Word Write\r
+    CLD                         ; Block fill Forwards\r
+\r
+    MOV     CX, PAGE_SIZE       ; Get Size of Page\r
+    SHR     CX, 1               ; Divide by 2 for Words\r
+    REP     STOSW               ; Block Fill VGA memory\r
+\r
+    ;POPx    DI, BP              ; Restore Saved Registers\r
+    pop        di\r
+       pop     bp\r
+    RET     2                   ; Exit & Clean Up Stack\r
+\r
+CLEAR_VGA_SCREEN    ENDP\r
+\r
+\r
+;===================================\r
+;SET_POINT (Xpos%, Ypos%, ColorNum%)\r
+;===================================\r
+;\r
+; Plots a single Pixel on the active display page\r
+;\r
+; ENTRY: Xpos     = X position to plot pixel at\r
+;        Ypos     = Y position to plot pixel at\r
+;        ColorNum = Color to plot pixel with\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+SP_STACK    STRUC\r
+                DW  ?,? ; BP, DI\r
+                DD  ?   ; Caller\r
+    SETP_Color  DB  ?,? ; Color of Point to Plot\r
+    SETP_Ypos   DW  ?   ; Y pos of Point to Plot\r
+    SETP_Xpos   DW  ?   ; X pos of Point to Plot\r
+SP_STACK    ENDS\r
+\r
+        PUBLIC SET_POINT\r
+\r
+SET_POINT   PROC    FAR\r
+\r
+    ;PUSHx   BP, DI              ; Preserve Registers\r
+    push       bp\r
+       push    di\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+\r
+    MOV     AX, [BP].SETP_Ypos  ; Get Line # of Pixel\r
+    MUL     SCREEN_WIDTH        ; Get Offset to Start of Line\r
+\r
+    MOV     BX, [BP].SETP_Xpos  ; Get Xpos\r
+    MOV     CX, BX              ; Copy to extract Plane # from\r
+    SHR     BX, 1               ; X offset (Bytes) = Xpos/4\r
+    SHR     BX, 1               ; X offset (Bytes) = Xpos/4\r
+    ADD     BX, AX              ; Offset = Width*Ypos + Xpos/4\r
+\r
+    MOV     AX, MAP_MASK_PLANE1 ; Map Mask & Plane Select Register\r
+    AND     CL, PLANE_BITS      ; Get Plane Bits\r
+    SHL     AH, CL              ; Get Plane Select Value\r
+    OUT_16  SC_Index, AX        ; Select Plane\r
+\r
+    MOV     AL,[BP].SETP_Color  ; Get Pixel Color\r
+    MOV     ES:[DI+BX], AL      ; Draw Pixel\r
+\r
+    ;POPx    DI, BP              ; Restore Saved Registers\r
+    pop        di\r
+       pop     bp\r
+    RET     6                   ; Exit and Clean up Stack\r
+\r
+SET_POINT        ENDP\r
+\r
+\r
+;==========================\r
+;READ_POINT% (Xpos%, Ypos%)\r
+;==========================\r
+;\r
+; Read the color of a pixel from the Active Display Page\r
+;\r
+; ENTRY: Xpos = X position of pixel to read\r
+;        Ypos = Y position of pixel to read\r
+;\r
+; EXIT:  AX   = Color of Pixel at (Xpos, Ypos)\r
+;\r
+\r
+RP_STACK    STRUC\r
+            DW  ?,? ; BP, DI\r
+            DD  ?   ; Caller\r
+    RP_Ypos DW  ?   ; Y pos of Point to Read\r
+    RP_Xpos DW  ?   ; X pos of Point to Read\r
+RP_STACK    ENDS\r
+\r
+        PUBLIC  READ_POINT\r
+\r
+READ_POINT      PROC    FAR\r
+\r
+    ;PUSHx   BP, DI              ; Preserve Registers\r
+    push       bp\r
+       push    di\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+\r
+    MOV     AX, [BP].RP_Ypos    ; Get Line # of Pixel\r
+    MUL     SCREEN_WIDTH        ; Get Offset to Start of Line\r
+\r
+    MOV     BX, [BP].RP_Xpos    ; Get Xpos\r
+    MOV     CX, BX\r
+    SHR     BX, 1               ; X offset (Bytes) = Xpos/4\r
+    SHR     BX, 1               ; X offset (Bytes) = Xpos/4\r
+    ADD     BX, AX              ; Offset = Width*Ypos + Xpos/4\r
+\r
+    MOV     AL, READ_MAP        ; GC Read Mask Register\r
+    MOV     AH, CL              ; Get Xpos\r
+    AND     AH, PLANE_BITS      ; & mask out Plane #\r
+    OUT_16  GC_INDEX, AX        ; Select Plane to read in\r
+\r
+    mov ah,0                  ; Clear Return Value Hi byte\r
+    MOV     AL, ES:[DI+BX]      ; Get Color of Pixel\r
+\r
+    ;POPx    DI, BP              ; Restore Saved Registers\r
+    pop        di\r
+       pop     bp\r
+    RET     4                   ; Exit and Clean up Stack\r
+\r
+READ_POINT        ENDP\r
+\r
+\r
+;======================================================\r
+;FILL_BLOCK (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%)\r
+;======================================================\r
+;\r
+; Fills a rectangular block on the active display Page\r
+;\r
+; ENTRY: Xpos1    = Left X position of area to fill\r
+;        Ypos1    = Top Y position of area to fill\r
+;        Xpos2    = Right X position of area to fill\r
+;        Ypos2    = Bottom Y position of area to fill\r
+;        ColorNum = Color to fill area with\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+FB_STACK    STRUC\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DD  ?   ; Caller\r
+    FB_Color    DB  ?,? ; Fill Color\r
+    FB_Ypos2    DW  ?   ; Y pos of Lower Right Pixel\r
+    FB_Xpos2    DW  ?   ; X pos of Lower Right Pixel\r
+    FB_Ypos1    DW  ?   ; Y pos of Upper Left Pixel\r
+    FB_Xpos1    DW  ?   ; X pos of Upper Left Pixel\r
+FB_STACK    ENDS\r
+\r
+        PUBLIC    FILL_BLOCK\r
+\r
+FILL_BLOCK  PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+       push    di\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+    CLD                         ; Direction Flag = Forward\r
+\r
+    OUT_8   SC_INDEX, MAP_MASK  ; Set up for Plane Select\r
+\r
+    ; Validate Pixel Coordinates\r
+    ; If necessary, Swap so X1 <= X2, Y1 <= Y2\r
+\r
+    MOV     AX, [BP].FB_Ypos1   ; AX = Y1   is Y1< Y2?\r
+    MOV     BX, [BP].FB_Ypos2   ; BX = Y2\r
+    CMP     AX, BX\r
+    JLE     @FB_NOSWAP1\r
+\r
+    MOV     [BP].FB_Ypos1, BX   ; Swap Y1 and Y2 and save Y1\r
+    XCHG    AX, BX              ; on stack for future use\r
+\r
+@FB_NOSWAP1:\r
+    SUB     BX, AX              ; Get Y width\r
+    INC     BX                  ; Add 1 to avoid 0 value\r
+    MOV     [BP].FB_Ypos2, BX   ; Save in Ypos2\r
+\r
+    MUL     SCREEN_WIDTH        ; Mul Y1 by Bytes per Line\r
+    ADD     DI, AX              ; DI = Start of Line Y1\r
+\r
+    MOV     AX, [BP].FB_Xpos1   ; Check X1 <= X2\r
+    MOV     BX, [BP].FB_Xpos2   ;\r
+    CMP     AX, BX\r
+    JLE     @FB_NOSWAP2         ; Skip Ahead if Ok\r
+\r
+    MOV     [BP].FB_Xpos2, AX   ; Swap X1 AND X2 and save X2\r
+    XCHG    AX, BX              ; on stack for future use\r
+\r
+    ; All our Input Values are in order, Now determine\r
+    ; How many full "bands" 4 pixels wide (aligned) there\r
+    ; are, and if there are partial bands (<4 pixels) on\r
+    ; the left and right edges.\r
+\r
+@FB_NOSWAP2:\r
+    MOV     DX, AX              ; DX = X1 (Pixel Position)\r
+    SHR     DX, 1               ; DX/4 = Bytes into Line\r
+    SHR     DX, 1               ; DX/4 = Bytes into Line\r
+    ADD     DI, DX              ; DI = Addr of Upper-Left Corner\r
+\r
+    MOV     CX, BX              ; CX = X2 (Pixel Position)\r
+    SHR     CX, 1               ; CX/4 = Bytes into Line\r
+    SHR     CX, 1               ; CX/4 = Bytes into Line\r
+\r
+    CMP     DX, CX              ; Start and end in same band?\r
+    JNE     @FB_NORMAL          ; if not, check for l & r edges\r
+    JMP     @FB_ONE_BAND_ONLY   ; if so, then special processing\r
+\r
+@FB_NORMAL:\r
+    SUB     CX, DX              ; CX = # bands -1\r
+    MOV     SI, AX              ; SI = PLANE#(X1)\r
+    AND     SI, PLANE_BITS      ; if Left edge is aligned then\r
+    JZ      @FB_L_PLANE_FLUSH   ; no special processing..\r
+\r
+    ; Draw "Left Edge" vertical strip of 1-3 pixels...\r
+\r
+    OUT_8   SC_Data, Left_Clip_Mask[SI] ; Set Left Edge Plane Mask\r
+\r
+    MOV     SI, DI              ; SI = Copy of Start Addr (UL)\r
+\r
+    MOV     DX, [BP].FB_Ypos2   ; Get # of Lines to draw\r
+    MOV     AL, [BP].FB_Color   ; Get Fill Color\r
+    MOV     BX, SCREEN_WIDTH    ; Get Vertical increment Value\r
+\r
+@FB_LEFT_LOOP:\r
+    MOV     ES:[SI], AL         ; Fill in Left Edge Pixels\r
+    ADD     SI, BX              ; Point to Next Line (Below)\r
+    LOOPjz  DX, @FB_LEFT_CONT   ; Exit loop if all Lines Drawn\r
+\r
+    MOV     ES:[SI], AL         ; Fill in Left Edge Pixels\r
+    ADD     SI, BX              ; Point to Next Line (Below)\r
+    LOOPx   DX, @FB_LEFT_LOOP   ; loop until left strip is drawn\r
+\r
+@FB_LEFT_CONT:\r
+\r
+    INC     DI                  ; Point to Middle (or Right) Block\r
+    DEC     CX                  ; Reset CX instead of JMP @FB_RIGHT\r
+\r
+@FB_L_PLANE_FLUSH:\r
+    INC     CX                  ; Add in Left band to middle block\r
+\r
+    ; DI = Addr of 1st middle Pixel (band) to fill\r
+    ; CX = # of Bands to fill -1\r
+\r
+@FB_RIGHT:\r
+    MOV     SI, [BP].FB_Xpos2   ; Get Xpos2\r
+    AND     SI, PLANE_BITS      ; Get Plane values\r
+    CMP     SI, 0003            ; Plane = 3?\r
+    JE      @FB_R_EDGE_FLUSH    ; Hey, add to middle\r
+\r
+    ; Draw "Right Edge" vertical strip of 1-3 pixels...\r
+\r
+    OUT_8   SC_Data, Right_Clip_Mask[SI]    ; Right Edge Plane Mask\r
+\r
+    MOV     SI, DI              ; Get Addr of Left Edge\r
+    ADD     SI, CX              ; Add Width-1 (Bands)\r
+    DEC     SI                  ; To point to top of Right Edge\r
+\r
+    MOV     DX, [BP].FB_Ypos2   ; Get # of Lines to draw\r
+    MOV     AL, [BP].FB_Color   ; Get Fill Color\r
+    MOV     BX, SCREEN_WIDTH    ; Get Vertical increment Value\r
+\r
+@FB_RIGHT_LOOP:\r
+    MOV     ES:[SI], AL         ; Fill in Right Edge Pixels\r
+    ADD     SI, BX              ; Point to Next Line (Below)\r
+    LOOPjz  DX, @FB_RIGHT_CONT  ; Exit loop if all Lines Drawn\r
+\r
+    MOV     ES:[SI], AL         ; Fill in Right Edge Pixels\r
+    ADD     SI, BX              ; Point to Next Line (Below)\r
+    LOOPx   DX, @FB_RIGHT_LOOP  ; loop until left strip is drawn\r
+\r
+@FB_RIGHT_CONT:\r
+\r
+    DEC     CX                  ; Minus 1 for Middle bands\r
+    JZ      @FB_EXIT            ; Uh.. no Middle bands...\r
+\r
+@FB_R_EDGE_FLUSH:\r
+\r
+    ; DI = Addr of Upper Left block to fill\r
+    ; CX = # of Bands to fill in (width)\r
+\r
+    OUT_8   SC_Data, ALL_PLANES ; Write to All Planes\r
+\r
+    MOV     DX, SCREEN_WIDTH    ; DX = DI Increment\r
+    SUB     DX, CX              ;  = Screen_Width-# Planes Filled\r
+\r
+    MOV     BX, CX              ; BX = Quick Refill for CX\r
+    MOV     SI, [BP].FB_Ypos2   ; SI = # of Line to Fill\r
+    MOV     AL, [BP].FB_Color   ; Get Fill Color\r
+\r
+@FB_MIDDLE_LOOP:\r
+    REP     STOSB               ; Fill in entire line\r
+\r
+    MOV     CX, BX              ; Recharge CX (Line Width)\r
+    ADD     DI, DX              ; Point to start of Next Line\r
+    LOOPx   SI, @FB_MIDDLE_LOOP ; Loop until all lines drawn\r
+\r
+    JMP     s @FB_EXIT          ; Outa here\r
+\r
+@FB_ONE_BAND_ONLY:\r
+    MOV     SI, AX                  ; Get Left Clip Mask, Save X1\r
+    AND     SI, PLANE_BITS          ; Mask out Row #\r
+    MOV     AL, Left_Clip_Mask[SI]  ; Get Left Edge Mask\r
+    MOV     SI, BX                  ; Get Right Clip Mask, Save X2\r
+    AND     SI, PLANE_BITS          ; Mask out Row #\r
+    AND     AL, Right_Clip_Mask[SI] ; Get Right Edge Mask byte\r
+\r
+    OUT_8   SC_Data, AL         ; Clip For Left & Right Masks\r
+\r
+    MOV     CX, [BP].FB_Ypos2   ; Get # of Lines to draw\r
+    MOV     AL, [BP].FB_Color   ; Get Fill Color\r
+    MOV     BX, SCREEN_WIDTH    ; Get Vertical increment Value\r
+\r
+@FB_ONE_LOOP:\r
+    MOV     ES:[DI], AL         ; Fill in Pixels\r
+    ADD     DI, BX              ; Point to Next Line (Below)\r
+    LOOPjz  CX, @FB_EXIT        ; Exit loop if all Lines Drawn\r
+\r
+    MOV     ES:[DI], AL         ; Fill in Pixels\r
+    ADD     DI, BX              ; Point to Next Line (Below)\r
+    LOOPx   CX, @FB_ONE_LOOP    ; loop until left strip is drawn\r
+\r
+@FB_EXIT:\r
+    ;POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    RET     10                  ; Exit and Clean up Stack\r
+\r
+FILL_BLOCK   ENDP\r
+\r
+\r
+;=====================================================\r
+;DRAW_LINE (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%)\r
+;=====================================================\r
+;\r
+; Draws a Line on the active display page\r
+;\r
+; ENTRY: Xpos1    = X position of first point on line\r
+;        Ypos1    = Y position of first point on line\r
+;        Xpos2    = X position of last point on line\r
+;        Ypos2    = Y position of last point on line\r
+;        ColorNum = Color to draw line with\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+DL_STACK    STRUC\r
+                DW  ?x1 ; DI, SI, BP\r
+                DW  ?x1 ; DI, SI, BP\r
+                DW  ?x1 ; DI, SI, BP\r
+                DD  ?   ; Caller\r
+    DL_ColorF   DB  ?,? ; Line Draw Color\r
+    DL_Ypos2    DW  ?   ; Y pos of last point\r
+    DL_Xpos2    DW  ?   ; X pos of last point\r
+    DL_Ypos1    DW  ?   ; Y pos of first point\r
+    DL_Xpos1    DW  ?   ; X pos of first point\r
+DL_STACK    ENDS\r
+\r
+        PUBLIC DRAW_LINE\r
+\r
+DRAW_LINE   PROC    FAR\r
+\r
+    ;PUSHx   BP, SI, DI          ; Preserve Important Registers\r
+    push       bp\r
+       push    si\r
+       push    di\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+    CLD                         ; Direction Flag = Forward\r
+\r
+    OUT_8   SC_INDEX, MAP_MASK  ; Set up for Plane Select\r
+    MOV     CH, [BP].DL_ColorF  ; Save Line Color in CH\r
+\r
+    ; Check Line Type\r
+\r
+    MOV     SI, [BP].DL_Xpos1   ; AX = X1   is X1< X2?\r
+    MOV     DI, [BP].DL_Xpos2   ; DX = X2\r
+    CMP     SI, DI              ; Is X1 < X2\r
+    JE      @DL_VLINE           ; If X1=X2, Draw Vertical Line\r
+    JL      @DL_NOSWAP1         ; If X1 < X2, don't swap\r
+\r
+    XCHG    SI, DI              ; X2 IS > X1, SO SWAP THEM\r
+\r
+@DL_NOSWAP1:\r
+\r
+    ; SI = X1, DI = X2\r
+\r
+    MOV     AX, [BP].DL_Ypos1   ; AX = Y1   is Y1 <> Y2?\r
+    CMP     AX, [BP].DL_Ypos2   ; Y1 = Y2?\r
+    JE      @DL_HORZ            ; If so, Draw a Horizontal Line\r
+\r
+    JMP     @DL_BREZHAM         ; Diagonal line... go do it...\r
+\r
+    ; This Code draws a Horizontal Line in Mode X where:\r
+    ; SI = X1, DI = X2, and AX = Y1/Y2\r
+\r
+@DL_HORZ:\r
+\r
+    MUL     SCREEN_WIDTH        ; Offset = Ypos * Screen_Width\r
+    MOV     DX, AX              ; CX = Line offset into Page\r
+\r
+    MOV     AX, SI                  ; Get Left edge, Save X1\r
+    AND     SI, PLANE_BITS          ; Mask out Row #\r
+    MOV     BL, Left_Clip_Mask[SI]  ; Get Left Edge Mask\r
+    MOV     CX, DI                  ; Get Right edge, Save X2\r
+    AND     DI, PLANE_BITS          ; Mask out Row #\r
+    MOV     BH, Right_Clip_Mask[DI] ; Get Right Edge Mask byte\r
+\r
+    SHR     AX, 1               ; Get X1 Byte # (=X1/4)\r
+    SHR     CX, 1               ; Get X2 Byte # (=X2/4)\r
+    SHR     AX, 1               ; Get X1 Byte # (=X1/4)\r
+    SHR     CX, 1               ; Get X2 Byte # (=X2/4)\r
+\r
+    LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+    ADD     DI, DX              ; Point to Start of Line\r
+    ADD     DI, AX              ; Point to Pixel X1\r
+\r
+    SUB     CX, AX              ; CX = # Of Bands (-1) to set\r
+    JNZ     @DL_LONGLN          ; jump if longer than one segment\r
+\r
+    AND     BL, BH              ; otherwise, merge clip masks\r
+\r
+@DL_LONGLN:\r
+\r
+    OUT_8   SC_Data, BL         ; Set the Left Clip Mask\r
+\r
+    MOV     AL, [BP].DL_ColorF  ; Get Line Color\r
+    MOV     BL, AL              ; BL = Copy of Line Color\r
+    STOSB                       ; Set Left (1-4) Pixels\r
+\r
+    JCXZ    @DL_EXIT            ; Done if only one Line Segment\r
+\r
+    DEC     CX                  ; CX = # of Middle Segments\r
+    JZ      @DL_XRSEG           ; If no middle segments....\r
+\r
+    ; Draw Middle Segments\r
+\r
+    OUT_8   DX, ALL_PLANES      ; Write to ALL Planes\r
+\r
+    MOV     AL, BL              ; Get Color from BL\r
+    REP     STOSB               ; Draw Middle (4 Pixel) Segments\r
+\r
+@DL_XRSEG:\r
+    OUT_8   DX, BH              ; Select Planes for Right Clip Mask\r
+    MOV     AL, BL              ; Get Color Value\r
+    STOSB                       ; Draw Right (1-4) Pixels\r
+\r
+    JMP     s @DL_EXIT          ; We Are Done...\r
+\r
+\r
+    ; This Code Draws A Vertical Line.  On entry:\r
+    ; CH = Line Color, SI & DI = X1\r
+\r
+@DL_VLINE:\r
+\r
+    MOV     AX, [BP].DL_Ypos1   ; AX = Y1\r
+    MOV     SI, [BP].DL_Ypos2   ; SI = Y2\r
+    CMP     AX, SI              ; Is Y1 < Y2?\r
+    JLE     @DL_NOSWAP2         ; if so, Don't Swap them\r
+\r
+    XCHG    AX, SI              ; Ok, NOW Y1 < Y2\r
+\r
+@DL_NOSWAP2:\r
+\r
+    SUB     SI, AX              ; SI = Line Height (Y2-Y1+1)\r
+    INC     SI\r
+\r
+    ; AX = Y1, DI = X1, Get offset into Page into AX\r
+\r
+    MUL     SCREEN_WIDTH        ; Offset = Y1 (AX) * Screen Width\r
+    MOV     DX, DI              ; Copy Xpos into DX\r
+    SHR     DI, 1               ; DI = Xpos/4\r
+    SHR     DI, 1               ; DI = Xpos/4\r
+    ADD     AX, DI              ; DI = Xpos/4 + ScreenWidth * Y1\r
+\r
+    LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+    ADD     DI, AX              ; Point to Pixel X1, Y1\r
+\r
+    ;Select Plane\r
+\r
+    MOV     CL, DL              ; CL = Save X1\r
+    AND     CL, PLANE_BITS      ; Get X1 MOD 4 (Plane #)\r
+    MOV     AX, MAP_MASK_PLANE1 ; Code to set Plane #1\r
+    SHL     AH, CL              ; Change to Correct Plane #\r
+    OUT_16  SC_Index, AX        ; Select Plane\r
+\r
+    MOV     AL, CH              ; Get Saved Color\r
+    MOV     BX, SCREEN_WIDTH    ; Get Offset to Advance Line By\r
+\r
+@DL_VLoop:\r
+    MOV     ES:[DI], AL         ; Draw Single Pixel\r
+    ADD     DI, BX              ; Point to Next Line\r
+    LOOPjz  SI, @DL_EXIT        ; Lines--, Exit if done\r
+\r
+    MOV     ES:[DI], AL         ; Draw Single Pixel\r
+    ADD     DI, BX              ; Point to Next Line\r
+    LOOPx   SI, @DL_VLoop       ; Lines--, Loop until Done\r
+\r
+@DL_EXIT:\r
+\r
+    JMP     @DL_EXIT2           ; Done!\r
+\r
+    ; This code Draws a diagonal line in Mode X\r
+\r
+@DL_BREZHAM:\r
+    LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+\r
+    MOV     AX, [BP].DL_Ypos1   ; get Y1 value\r
+    MOV     BX, [BP].DL_Ypos2   ; get Y2 value\r
+    MOV     CX, [BP].DL_Xpos1   ; Get Starting Xpos\r
+\r
+    CMP     BX, AX              ; Y2-Y1 is?\r
+    JNC     @DL_DeltaYOK        ; if Y2>=Y1 then goto...\r
+\r
+    XCHG    BX, AX              ; Swap em...\r
+    MOV     CX, [BP].DL_Xpos2   ; Get New Starting Xpos\r
+\r
+@DL_DeltaYOK:\r
+    MUL     SCREEN_WIDTH        ; Offset = SCREEN_WIDTH * Y1\r
+\r
+    ADD     DI, AX              ; DI -> Start of Line Y1 on Page\r
+    MOV     AX, CX              ; AX = Xpos (X1)\r
+    SHR     AX, 1               ; /4 = Byte Offset into Line\r
+    SHR     AX, 1               ; /4 = Byte Offset into Line\r
+    ADD     DI, AX              ; DI = Starting pos (X1,Y1)\r
+\r
+    MOV     AL, 11h             ; Staring Mask\r
+    AND     CL, PLANE_BITS      ; Get Plane #\r
+    SHL     AL, CL              ; and shift into place\r
+    MOV     AH, [BP].DL_ColorF  ; Color in Hi Bytes\r
+\r
+    PUSH    AX                  ; Save Mask,Color...\r
+\r
+    MOV     AH, AL              ; Plane # in AH\r
+    MOV     AL, MAP_MASK        ; Select Plane Register\r
+    OUT_16  SC_Index, AX        ; Select initial plane\r
+\r
+    MOV     AX, [BP].DL_Xpos1   ; get X1 value\r
+    MOV     BX, [BP].DL_Ypos1   ; get Y1 value\r
+    MOV     CX, [BP].DL_Xpos2   ; get X2 value\r
+    MOV     DX, [BP].DL_Ypos2   ; get Y2 value\r
+\r
+    MOV     BP, SCREEN_WIDTH    ; Use BP for Line width to\r
+                                ; to avoid extra memory access\r
+\r
+    SUB     DX, BX              ; figure Delta_Y\r
+    JNC     @DL_DeltaYOK2       ; jump if Y2 >= Y1\r
+\r
+    ADD     BX, DX              ; put Y2 into Y1\r
+    NEG     DX                  ; abs(Delta_Y)\r
+    XCHG    AX, CX              ; and exchange X1 and X2\r
+\r
+@DL_DeltaYOK2:\r
+    MOV     BX, 08000H          ; seed for fraction accumulator\r
+\r
+    SUB     CX, AX              ; figure Delta_X\r
+    JC      @DL_DrawLeft        ; if negative, go left\r
+\r
+    JMP     @DL_DrawRight       ; Draw Line that slopes right\r
+\r
+@DL_DrawLeft:\r
+\r
+    NEG     CX                  ; abs(Delta_X)\r
+\r
+    CMP     CX, DX              ; is Delta_X < Delta_Y?\r
+    JB      @DL_SteepLeft       ; yes, so go do steep line\r
+                                ; (Delta_Y iterations)\r
+\r
+    ; Draw a Shallow line to the left in Mode X\r
+\r
+@DL_ShallowLeft:\r
+    mov ax,0                  ; zero low word of Delta_Y * 10000h\r
+    SUB     AX, DX              ; DX:AX <- DX * 0FFFFh\r
+    SBB     DX, 0               ; include carry\r
+    DIV     CX                  ; divide by Delta_X\r
+\r
+    MOV     SI, BX              ; SI = Accumulator\r
+    MOV     BX, AX              ; BX = Add fraction\r
+    POP     AX                  ; Get Color, Bit mask\r
+    MOV     DX, SC_Data         ; Sequence controller data register\r
+    INC     CX                  ; Inc Delta_X so we can unroll loop\r
+\r
+    ; Loop (x2) to Draw Pixels, Move Left, and Maybe Down...\r
+\r
+@DL_SLLLoop:\r
+    MOV     ES:[DI], AH         ; set first pixel, plane data set up\r
+    LOOPjz  CX, @DL_SLLExit     ; Delta_X--, Exit if done\r
+\r
+    ADD     SI, BX              ; add numerator to accumulator\r
+    JNC     @DL_SLLL2nc         ; move down on carry\r
+\r
+    ADD     DI, BP              ; Move Down one line...\r
+\r
+@DL_SLLL2nc:\r
+    DEC     DI                  ; Left one addr\r
+    ROR     AL, 1               ; Move Left one plane, back on 0 1 2\r
+    CMP     AL, 87h             ; wrap?, if AL <88 then Carry set\r
+    ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+    OUT     DX, AL              ; Set up New Bit Plane mask\r
+\r
+    MOV     ES:[DI], AH         ; set pixel\r
+    LOOPjz  CX, @DL_SLLExit     ; Delta_X--, Exit if done\r
+\r
+    ADD     SI, BX              ; add numerator to accumulator,\r
+    JNC     @DL_SLLL3nc         ; move down on carry\r
+\r
+    ADD     DI, BP              ; Move Down one line...\r
+\r
+@DL_SLLL3nc:                    ; Now move left a pixel...\r
+    DEC     DI                  ; Left one addr\r
+    ROR     AL, 1               ; Move Left one plane, back on 0 1 2\r
+    CMP     AL, 87h             ; Wrap?, if AL <88 then Carry set\r
+    ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+    OUT     DX, AL              ; Set up New Bit Plane mask\r
+    JMP     s @DL_SLLLoop       ; loop until done\r
+\r
+@DL_SLLExit:\r
+    JMP     @DL_EXIT2           ; and exit\r
+\r
+    ; Draw a steep line to the left in Mode X\r
+\r
+@DL_SteepLeft:\r
+    mov ax,0                  ; zero low word of Delta_Y * 10000h\r
+    XCHG    DX, CX              ; Delta_Y switched with Delta_X\r
+    DIV     CX                  ; divide by Delta_Y\r
+\r
+    MOV     SI, BX              ; SI = Accumulator\r
+    MOV     BX, AX              ; BX = Add Fraction\r
+    POP     AX                  ; Get Color, Bit mask\r
+    MOV     DX, SC_Data         ; Sequence controller data register\r
+    INC     CX                  ; Inc Delta_Y so we can unroll loop\r
+\r
+    ; Loop (x2) to Draw Pixels, Move Down, and Maybe left\r
+\r
+@DL_STLLoop:\r
+\r
+    MOV     ES:[DI], AH         ; set first pixel\r
+    LOOPjz  CX, @DL_STLExit     ; Delta_Y--, Exit if done\r
+\r
+    ADD     SI, BX              ; add numerator to accumulator\r
+    JNC     @DL_STLnc2          ; No carry, just move down!\r
+\r
+    DEC     DI                  ; Move Left one addr\r
+    ROR     AL, 1               ; Move Left one plane, back on 0 1 2\r
+    CMP     AL, 87h             ; Wrap?, if AL <88 then Carry set\r
+    ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+    OUT     DX, AL              ; Set up New Bit Plane mask\r
+\r
+@DL_STLnc2:\r
+    ADD     DI, BP              ; advance to next line.\r
+\r
+    MOV     ES:[DI], AH         ; set pixel\r
+    LOOPjz  CX, @DL_STLExit     ; Delta_Y--, Exit if done\r
+\r
+    ADD     SI, BX              ; add numerator to accumulator\r
+    JNC     @DL_STLnc3          ; No carry, just move down!\r
+\r
+    DEC     DI                  ; Move Left one addr\r
+    ROR     AL, 1               ; Move Left one plane, back on 0 1 2\r
+    CMP     AL, 87h             ; Wrap?, if AL <88 then Carry set\r
+    ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+    OUT     DX, AL              ; Set up New Bit Plane mask\r
+\r
+@DL_STLnc3:\r
+    ADD     DI, BP              ; advance to next line.\r
+    JMP     s @DL_STLLoop       ; Loop until done\r
+\r
+@DL_STLExit:\r
+    JMP     @DL_EXIT2           ; and exit\r
+\r
+    ; Draw a line that goes to the Right...\r
+\r
+@DL_DrawRight:\r
+    CMP     CX, DX              ; is Delta_X < Delta_Y?\r
+    JB      @DL_SteepRight      ; yes, so go do steep line\r
+                                ; (Delta_Y iterations)\r
+\r
+    ; Draw a Shallow line to the Right in Mode X\r
+\r
+@DL_ShallowRight:\r
+    mov ax,0                  ; zero low word of Delta_Y * 10000h\r
+    SUB     AX, DX              ; DX:AX <- DX * 0FFFFh\r
+    SBB     DX, 0               ; include carry\r
+    DIV     CX                  ; divide by Delta_X\r
+\r
+    MOV     SI, BX              ; SI = Accumulator\r
+    MOV     BX, AX              ; BX = Add Fraction\r
+    POP     AX                  ; Get Color, Bit mask\r
+    MOV     DX, SC_Data         ; Sequence controller data register\r
+    INC     CX                  ; Inc Delta_X so we can unroll loop\r
+\r
+    ; Loop (x2) to Draw Pixels, Move Right, and Maybe Down...\r
+\r
+@DL_SLRLoop:\r
+    MOV     ES:[DI], AH         ; set first pixel, mask is set up\r
+    LOOPjz  CX, @DL_SLRExit     ; Delta_X--, Exit if done..\r
+\r
+    ADD     SI, BX              ; add numerator to accumulator\r
+    JNC     @DL_SLR2nc          ; don't move down if carry not set\r
+\r
+    ADD     DI, BP              ; Move Down one line...\r
+\r
+@DL_SLR2nc:                     ; Now move right a pixel...\r
+    ROL     AL, 1               ; Move Right one addr if Plane = 0\r
+    CMP     AL, 12h             ; Wrap? if AL >12 then Carry not set\r
+    ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+    OUT     DX, AL              ; Set up New Bit Plane mask\r
+\r
+    MOV     ES:[DI], AH         ; set pixel\r
+    LOOPjz  CX, @DL_SLRExit     ; Delta_X--, Exit if done..\r
+\r
+    ADD     SI, BX              ; add numerator to accumulator\r
+    JNC     @DL_SLR3nc          ; don't move down if carry not set\r
+\r
+    ADD     DI, BP              ; Move Down one line...\r
+\r
+@DL_SLR3nc:\r
+    ROL     AL, 1               ; Move Right one addr if Plane = 0\r
+    CMP     AL, 12h             ; Wrap? if AL >12 then Carry not set\r
+    ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+    OUT     DX, AL              ; Set up New Bit Plane mask\r
+    JMP     s @DL_SLRLoop       ; loop till done\r
+\r
+@DL_SLRExit:\r
+    JMP     @DL_EXIT2           ; and exit\r
+\r
+    ; Draw a Steep line to the Right in Mode X\r
+\r
+@DL_SteepRight:\r
+    mov ax,0                  ; zero low word of Delta_Y * 10000h\r
+    XCHG    DX, CX              ; Delta_Y switched with Delta_X\r
+    DIV     CX                  ; divide by Delta_Y\r
+\r
+    MOV     SI, BX              ; SI = Accumulator\r
+    MOV     BX, AX              ; BX = Add Fraction\r
+    POP     AX                  ; Get Color, Bit mask\r
+    MOV     DX, SC_Data         ; Sequence controller data register\r
+    INC     CX                  ; Inc Delta_Y so we can unroll loop\r
+\r
+    ; Loop (x2) to Draw Pixels, Move Down, and Maybe Right\r
+\r
+@STRLoop:\r
+    MOV     ES:[DI], AH         ; set first pixel, mask is set up\r
+    LOOPjz  CX, @DL_EXIT2       ; Delta_Y--, Exit if Done\r
+\r
+    ADD     SI, BX              ; add numerator to accumulator\r
+    JNC     @STRnc2             ; if no carry then just go down...\r
+\r
+    ROL     AL, 1               ; Move Right one addr if Plane = 0\r
+    CMP     AL, 12h             ; Wrap? if AL >12 then Carry not set\r
+    ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+    OUT     DX, AL              ; Set up New Bit Plane mask\r
+\r
+@STRnc2:\r
+    ADD     DI, BP              ; advance to next line.\r
+\r
+    MOV     ES:[DI], AH         ; set pixel\r
+    LOOPjz  CX, @DL_EXIT2       ; Delta_Y--, Exit if Done\r
+\r
+    ADD     SI, BX              ; add numerator to accumulator\r
+    JNC     @STRnc3             ; if no carry then just go down...\r
+\r
+    ROL     AL, 1               ; Move Right one addr if Plane = 0\r
+    CMP     AL, 12h             ; Wrap? if AL >12 then Carry not set\r
+    ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+    OUT     DX, AL              ; Set up New Bit Plane mask\r
+\r
+@STRnc3:\r
+    ADD     DI, BP              ; advance to next line.\r
+    JMP     s @STRLoop          ; loop till done\r
+\r
+@DL_EXIT2:\r
+    ;POPx    DI, SI, BP          ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     bp\r
+    RET     10                  ; Exit and Clean up Stack\r
+\r
+DRAW_LINE        ENDP\r
+\r
+\r
+    ; ===== DAC COLOR REGISTER ROUTINES =====\r
+\r
+;=================================================\r
+;SET_DAC_REGISTER (Register%, Red%, Green%, Blue%)\r
+;=================================================\r
+;\r
+; Sets a single (RGB) Vga Palette Register\r
+;\r
+; ENTRY: Register = The DAC # to modify (0-255)\r
+;        Red      = The new Red Intensity (0-63)\r
+;        Green    = The new Green Intensity (0-63)\r
+;        Blue     = The new Blue Intensity (0-63)\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+SDR_STACK   STRUC\r
+                    DW  ?   ; BP\r
+                    DD  ?   ; Caller\r
+    SDR_Blue        DB  ?,? ; Blue Data Value\r
+    SDR_Green       DB  ?,? ; Green Data Value\r
+    SDR_Red         DB  ?,? ; Red Data Value\r
+    SDR_Register    DB  ?,? ; Palette Register #\r
+SDR_STACK   ENDS\r
+\r
+    PUBLIC  SET_DAC_REGISTER\r
+\r
+SET_DAC_REGISTER    PROC    FAR\r
+\r
+    PUSH    BP                  ; Save BP\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    ; Select which DAC Register to modify\r
+\r
+    OUT_8   DAC_WRITE_ADDR, [BP].SDR_Register\r
+\r
+    MOV     DX, PEL_DATA_REG    ; Dac Data Register\r
+    OUT_8   DX, [BP].SDR_Red    ; Set Red Intensity\r
+    OUT_8   DX, [BP].SDR_Green  ; Set Green Intensity\r
+    OUT_8   DX, [BP].SDR_Blue   ; Set Blue Intensity\r
+\r
+    POP     BP                  ; Restore Registers\r
+    RET     8                   ; Exit & Clean Up Stack\r
+\r
+SET_DAC_REGISTER    ENDP\r
+\r
+;====================================================\r
+;GET_DAC_REGISTER (Register%, &Red%, &Green%, &Blue%)\r
+;====================================================\r
+;\r
+; Reads the RGB Values of a single Vga Palette Register\r
+;\r
+; ENTRY: Register = The DAC # to read (0-255)\r
+;        Red      = Offset to Red Variable in DS\r
+;        Green    = Offset to Green Variable in DS\r
+;        Blue     = Offset to Blue Variable in DS\r
+;\r
+; EXIT:  The values of the integer variables Red,\r
+;        Green, and Blue are set to the values\r
+;        taken from the specified DAC register.\r
+;\r
+\r
+GDR_STACK   STRUC\r
+                    DW  ?   ; BP\r
+                    DD  ?   ; Caller\r
+    GDR_Blue        DW  ?   ; Addr of Blue Data Value in DS\r
+    GDR_Green       DW  ?   ; Addr of Green Data Value in DS\r
+    GDR_Red         DW  ?   ; Addr of Red Data Value in DS\r
+    GDR_Register    DB  ?,? ; Palette Register #\r
+GDR_STACK   ENDS\r
+\r
+    PUBLIC  GET_DAC_REGISTER\r
+\r
+GET_DAC_REGISTER    PROC    FAR\r
+\r
+    PUSH    BP                  ; Save BP\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    ; Select which DAC Register to read in\r
+\r
+    OUT_8   DAC_READ_ADDR, [BP].GDR_Register\r
+\r
+    MOV     DX, PEL_DATA_REG    ; Dac Data Register\r
+    mov ax,0                  ; Clear AX\r
+\r
+    IN      AL, DX              ; Read Red Value\r
+    MOV     BX, [BP].GDR_Red    ; Get Address of Red%\r
+    MOV     [BX], AX            ; *Red% = AX\r
+\r
+    IN      AL, DX              ; Read Green Value\r
+    MOV     BX, [BP].GDR_Green  ; Get Address of Green%\r
+    MOV     [BX], AX            ; *Green% = AX\r
+\r
+    IN      AL, DX              ; Read Blue Value\r
+    MOV     BX, [BP].GDR_Blue   ; Get Address of Blue%\r
+    MOV     [BX], AX            ; *Blue% = AX\r
+\r
+    POP     BP                  ; Restore Registers\r
+    RET     8                   ; Exit & Clean Up Stack\r
+\r
+GET_DAC_REGISTER    ENDP\r
+\r
+\r
+;===========================================================\r
+;LOAD_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%, Sync%)\r
+;===========================================================\r
+;\r
+; Sets a Block of Vga Palette Registers\r
+;\r
+; ENTRY: PalData  = Far Pointer to Block of palette data\r
+;        StartReg = First Register # in range to set (0-255)\r
+;        EndReg   = Last Register # in Range to set (0-255)\r
+;        Sync     = Wait for Vertical Retrace Flag (Boolean)\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+; NOTES: PalData is a linear array of 3 byte Palette values\r
+;        in the order: Red  (0-63), Green (0-63), Blue (0-63)\r
+;\r
+\r
+LDR_STACK   STRUC\r
+                    DW  ?x1 ; BP, DS, SI\r
+                    DW  ?x1 ; BP, DS, SI\r
+                    DW  ?x1 ; BP, DS, SI\r
+                    DD  ?   ; Caller\r
+    LDR_Sync        DW  ?   ; Vertical Sync Flag\r
+    LDR_EndReg      DB  ?,? ; Last Register #\r
+    LDR_StartReg    DB  ?,? ; First Register #\r
+    LDR_PalData     DD  ?   ; Far Ptr to Palette Data\r
+LDR_STACK   ENDS\r
+\r
+    PUBLIC  LOAD_DAC_REGISTERS\r
+\r
+LOAD_DAC_REGISTERS  PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI          ; Save Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+    mov     BP, SP              ; Set up Stack Frame\r
+\r
+    mov     AX, [BP].LDR_Sync   ; Get Vertical Sync Flag\r
+    or      AX, AX              ; is Sync Flag = 0?\r
+    jz      @LDR_Load           ; if so, skip call\r
+\r
+    call    f SYNC_DISPLAY      ; wait for vsync\r
+\r
+    ; Determine register #'s, size to copy, etc\r
+\r
+@LDR_Load:\r
+\r
+    lds     SI, [BP].LDR_PalData    ; DS:SI -> Palette Data\r
+    mov     DX, DAC_WRITE_ADDR      ; DAC register # selector\r
+\r
+    mov ax,0, BX                  ; Clear for byte loads\r
+    mov     AL, [BP].LDR_StartReg   ; Get Start Register\r
+    mov     BL, [BP].LDR_EndReg     ; Get End Register\r
+\r
+    sub     BX, AX              ; BX = # of DAC registers -1\r
+    inc     BX                  ; BX = # of DAC registers\r
+    mov     CX, BX              ; CX = # of DAC registers\r
+    add     CX, BX              ; CX =  "   " * 2\r
+    add     CX, BX              ; CX =  "   " * 3\r
+    cld                         ; Block OUTs forward\r
+    out     DX, AL              ; set up correct register #\r
+\r
+    ; Load a block of DAC Registers\r
+\r
+    mov     DX, PEL_DATA_REG    ; Dac Data Register\r
+\r
+    ;rep     outsb               ; block set DAC registers\r
+\r
+    ;POPx    SI, DS, BP          ; Restore Registers\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    ret     10                  ; Exit & Clean Up Stack\r
+\r
+LOAD_DAC_REGISTERS  ENDP\r
+\r
+\r
+;====================================================\r
+;READ_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%)\r
+;====================================================\r
+;\r
+; Reads a Block of Vga Palette Registers\r
+;\r
+; ENTRY: PalData  = Far Pointer to block to store palette data\r
+;        StartReg = First Register # in range to read (0-255)\r
+;        EndReg   = Last Register # in Range to read (0-255)\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+; NOTES: PalData is a linear array of 3 byte Palette values\r
+;        in the order: Red  (0-63), Green (0-63), Blue (0-63)\r
+;\r
+\r
+RDR_STACK   STRUC\r
+                    DW  ?x1 ; BP, ES, DI\r
+                    DW  ?x1 ; BP, ES, DI\r
+                    DW  ?x1 ; BP, ES, DI\r
+                    DD  ?   ; Caller\r
+    RDR_EndReg      DB  ?,? ; Last Register #\r
+    RDR_StartReg    DB  ?,? ; First Register #\r
+    RDR_PalData     DD  ?   ; Far Ptr to Palette Data\r
+RDR_STACK   ENDS\r
+\r
+    PUBLIC  READ_DAC_REGISTERS\r
+\r
+READ_DAC_REGISTERS  PROC    FAR\r
+\r
+    ;PUSHx   BP, ES, DI          ; Save Registers\r
+    push       bp\r
+       push    es\r
+       push    di\r
+    mov     BP, SP              ; Set up Stack Frame\r
+\r
+    ; Determine register #'s, size to copy, etc\r
+\r
+    les     DI, [BP].RDR_PalData    ; ES:DI -> Palette Buffer\r
+    mov     DX, DAC_READ_ADDR       ; DAC register # selector\r
+\r
+    mov ax,0, BX                  ; Clear for byte loads\r
+    mov     AL, [BP].RDR_StartReg   ; Get Start Register\r
+    mov     BL, [BP].RDR_EndReg     ; Get End Register\r
+\r
+    sub     BX, AX              ; BX = # of DAC registers -1\r
+    inc     BX                  ; BX = # of DAC registers\r
+    mov     CX, BX              ; CX = # of DAC registers\r
+    add     CX, BX              ; CX =  "   " * 2\r
+    add     CX, BX              ; CX =  "   " * 3\r
+    cld                         ; Block INs forward\r
+\r
+    ; Read a block of DAC Registers\r
+\r
+    out     DX, AL              ; set up correct register #\r
+    mov     DX, PEL_DATA_REG    ; Dac Data Register\r
+\r
+    ;rep     insb                ; block read DAC registers\r
+\r
+    ;POPx    DI, ES, BP          ; Restore Registers\r
+    pop        di\r
+       pop     es\r
+       pop     bp\r
+    ret     8                   ; Exit & Clean Up Stack\r
+\r
+READ_DAC_REGISTERS  ENDP\r
+\r
+\r
+    ; ===== PAGE FLIPPING AND SCROLLING ROUTINES =====\r
+\r
+;=========================\r
+;SET_ACTIVE_PAGE (PageNo%)\r
+;=========================\r
+;\r
+; Sets the active display Page to be used for future drawing\r
+;\r
+; ENTRY: PageNo = Display Page to make active\r
+;        (values: 0 to Number of Pages - 1)\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+SAP_STACK   STRUC\r
+                DW  ?   ; BP\r
+                DD  ?   ; Caller\r
+    SAP_Page    DW  ?   ; Page # for Drawing\r
+SAP_STACK   ENDS\r
+\r
+    PUBLIC  SET_ACTIVE_PAGE\r
+\r
+SET_ACTIVE_PAGE PROC    FAR\r
+\r
+    PUSH    BP                  ; Preserve Registers\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    MOV     BX, [BP].SAP_Page   ; Get Desired Page #\r
+    CMP     BX, LAST_PAGE       ; Is Page # Valid?\r
+    JAE     @SAP_Exit           ; IF Not, Do Nothing\r
+\r
+    MOV     ACTIVE_PAGE, BX     ; Set Active Page #\r
+\r
+    SHL     BX, 1               ; Scale Page # to Word\r
+    MOV     AX, PAGE_ADDR[BX]   ; Get offset to Page\r
+\r
+    MOV     CURRENT_PAGE, AX    ; And set for future LES's\r
+\r
+@SAP_Exit:\r
+    POP     BP                  ; Restore Registers\r
+    RET     2                   ; Exit and Clean up Stack\r
+\r
+SET_ACTIVE_PAGE ENDP\r
+\r
+\r
+;================\r
+;GET_ACTIVE_PAGE%\r
+;================\r
+;\r
+; Returns the Video Page # currently used for Drawing\r
+;\r
+; ENTRY: No Parameters are passed\r
+;\r
+; EXIT:  AX = Current Video Page used for Drawing\r
+;\r
+\r
+    PUBLIC  GET_ACTIVE_PAGE\r
+\r
+GET_ACTIVE_PAGE PROC    FAR\r
+\r
+    MOV     AX, ACTIVE_PAGE     ; Get Active Page #\r
+    RET                         ; Exit and Clean up Stack\r
+\r
+GET_ACTIVE_PAGE ENDP\r
+\r
+\r
+;===============================\r
+;SET_DISPLAY_PAGE (DisplayPage%)\r
+;===============================\r
+;\r
+; Sets the currently visible display page.\r
+; When called this routine syncronizes the display\r
+; to the vertical blank.\r
+;\r
+; ENTRY: PageNo = Display Page to show on the screen\r
+;        (values: 0 to Number of Pages - 1)\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+SDP_STACK   STRUC\r
+                DW  ?       ; BP\r
+                DD  ?       ; Caller\r
+    SDP_Page    DW  ?       ; Page # to Display...\r
+SDP_STACK   ENDS\r
+\r
+    PUBLIC  SET_DISPLAY_PAGE\r
+\r
+SET_DISPLAY_PAGE    PROC    FAR\r
+\r
+    PUSH    BP                  ; Preserve Registers\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    MOV     BX, [BP].SDP_Page   ; Get Desired Page #\r
+    CMP     BX, LAST_PAGE       ; Is Page # Valid?\r
+    JAE     @SDP_Exit           ; IF Not, Do Nothing\r
+\r
+    MOV     DISPLAY_PAGE, BX    ; Set Display Page #\r
+\r
+    SHL     BX, 1               ; Scale Page # to Word\r
+    MOV     CX, PAGE_ADDR[BX]   ; Get offset in memory to Page\r
+    ADD     CX, CURRENT_MOFFSET ; Adjust for any scrolling\r
+\r
+    ; Wait if we are currently in a Vertical Retrace\r
+\r
+    MOV     DX, INPUT_1         ; Input Status #1 Register\r
+\r
+@DP_WAIT0:\r
+    IN      AL, DX              ; Get VGA status\r
+    AND     AL, VERT_RETRACE    ; In Display mode yet?\r
+    JNZ     @DP_WAIT0           ; If Not, wait for it\r
+\r
+    ; Set the Start Display Address to the new page\r
+\r
+    MOV     DX, CRTC_Index      ; We Change the VGA Sequencer\r
+\r
+    MOV     AL, START_DISP_LO   ; Display Start Low Register\r
+    MOV     AH, CL              ; Low 8 Bits of Start Addr\r
+    OUT     DX, AX              ; Set Display Addr Low\r
+\r
+    MOV     AL, START_DISP_HI   ; Display Start High Register\r
+    MOV     AH, CH              ; High 8 Bits of Start Addr\r
+    OUT     DX, AX              ; Set Display Addr High\r
+\r
+    ; Wait for a Vertical Retrace to smooth out things\r
+\r
+    MOV     DX, INPUT_1         ; Input Status #1 Register\r
+\r
+@DP_WAIT1:\r
+    IN      AL, DX              ; Get VGA status\r
+    AND     AL, VERT_RETRACE    ; Vertical Retrace Start?\r
+    JZ      @DP_WAIT1           ; If Not, wait for it\r
+\r
+    ; Now Set Display Starting Address\r
+\r
+\r
+@SDP_Exit:\r
+    POP     BP                  ; Restore Registers\r
+    RET     2                   ; Exit and Clean up Stack\r
+\r
+SET_DISPLAY_PAGE    ENDP\r
+\r
+\r
+;=================\r
+;GET_DISPLAY_PAGE%\r
+;=================\r
+;\r
+; Returns the Video Page # currently displayed\r
+;\r
+; ENTRY: No Parameters are passed\r
+;\r
+; EXIT:  AX = Current Video Page being displayed\r
+;\r
+\r
+    PUBLIC  GET_DISPLAY_PAGE\r
+\r
+GET_DISPLAY_PAGE    PROC    FAR\r
+\r
+    MOV     AX, DISPLAY_PAGE    ; Get Display Page #\r
+    RET                         ; Exit & Clean Up Stack\r
+\r
+GET_DISPLAY_PAGE    ENDP\r
+\r
+\r
+;=======================================\r
+;SET_WINDOW (DisplayPage%, Xpos%, Ypos%)\r
+;=======================================\r
+;\r
+; Since a Logical Screen can be larger than the Physical\r
+; Screen, Scrolling is possible.  This routine sets the\r
+; Upper Left Corner of the Screen to the specified Pixel.\r
+; Also Sets the Display page to simplify combined page\r
+; flipping and scrolling.  When called this routine\r
+; syncronizes the display to the vertical blank.\r
+;\r
+; ENTRY: DisplayPage = Display Page to show on the screen\r
+;        Xpos        = # of pixels to shift screen right\r
+;        Ypos        = # of lines to shift screen down\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+SW_STACK    STRUC\r
+                DW  ?   ; BP\r
+                DD  ?   ; Caller\r
+    SW_Ypos     DW  ?   ; Y pos of UL Screen Corner\r
+    SW_Xpos     DW  ?   ; X pos of UL Screen Corner\r
+    SW_Page     DW  ?   ; (new) Display Page\r
+SW_STACK    ENDS\r
+\r
+        PUBLIC SET_WINDOW\r
+\r
+SET_WINDOW  PROC    FAR\r
+\r
+    PUSH    BP                  ; Preserve Registers\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    ; Check if our Scroll Offsets are Valid\r
+\r
+    MOV     BX, [BP].SW_Page    ; Get Desired Page #\r
+    CMP     BX, LAST_PAGE       ; Is Page # Valid?\r
+    JAE     @SW_Exit            ; IF Not, Do Nothing\r
+\r
+    MOV     AX, [BP].SW_Ypos    ; Get Desired Y Offset\r
+    CMP     AX, MAX_YOFFSET     ; Is it Within Limits?\r
+    JA      @SW_Exit            ; if not, exit\r
+\r
+    MOV     CX, [BP].SW_Xpos    ; Get Desired X Offset\r
+    CMP     CX, MAX_XOFFSET     ; Is it Within Limits?\r
+    JA      @SW_Exit            ; if not, exit\r
+\r
+    ; Compute proper Display start address to use\r
+\r
+    MUL     SCREEN_WIDTH        ; AX = YOffset * Line Width\r
+    SHR     CX, 1               ; CX / 4 = Bytes into Line\r
+    SHR     CX, 1               ; CX / 4 = Bytes into Line\r
+    ADD     AX, CX              ; AX = Offset of Upper Left Pixel\r
+\r
+    MOV     CURRENT_MOFFSET, AX ; Save Offset Info\r
+\r
+    MOV     DISPLAY_PAGE, BX    ; Set Current Page #\r
+    SHL     BX, 1               ; Scale Page # to Word\r
+    ADD     AX, PAGE_ADDR[BX]   ; Get offset in VGA to Page\r
+    MOV     BX, AX              ; BX = Desired Display Start\r
+\r
+    MOV     DX, INPUT_1         ; Input Status #1 Register\r
+\r
+    ; Wait if we are currently in a Vertical Retrace\r
+\r
+@SW_WAIT0:\r
+    IN      AL, DX              ; Get VGA status\r
+    AND     AL, VERT_RETRACE    ; In Display mode yet?\r
+    JNZ     @SW_WAIT0           ; If Not, wait for it\r
+\r
+    ; Set the Start Display Address to the new window\r
+\r
+    MOV     DX, CRTC_Index      ; We Change the VGA Sequencer\r
+    MOV     AL, START_DISP_LO   ; Display Start Low Register\r
+    MOV     AH, BL              ; Low 8 Bits of Start Addr\r
+    OUT     DX, AX              ; Set Display Addr Low\r
+\r
+    MOV     AL, START_DISP_HI   ; Display Start High Register\r
+    MOV     AH, BH              ; High 8 Bits of Start Addr\r
+    OUT     DX, AX              ; Set Display Addr High\r
+\r
+    ; Wait for a Vertical Retrace to smooth out things\r
+\r
+    MOV     DX, INPUT_1         ; Input Status #1 Register\r
+\r
+@SW_WAIT1:\r
+    IN      AL, DX              ; Get VGA status\r
+    AND     AL, VERT_RETRACE    ; Vertical Retrace Start?\r
+    JZ      @SW_WAIT1           ; If Not, wait for it\r
+\r
+    ; Now Set the Horizontal Pixel Pan values\r
+\r
+    OUT_8   ATTRIB_Ctrl, PIXEL_PAN_REG  ; Select Pixel Pan Register\r
+\r
+    MOV     AX, [BP].SW_Xpos    ; Get Desired X Offset\r
+    AND     AL, 03              ; Get # of Pixels to Pan (0-3)\r
+    SHL     AL, 1               ; Shift for 256 Color Mode\r
+    OUT     DX, AL              ; Fine tune the display!\r
+\r
+@SW_Exit:\r
+    POP     BP                  ; Restore Saved Registers\r
+    RET     6                   ; Exit and Clean up Stack\r
+\r
+SET_WINDOW        ENDP\r
+\r
+\r
+;=============\r
+;GET_X_OFFSET%\r
+;=============\r
+;\r
+; Returns the X coordinate of the Pixel currently display\r
+; in the upper left corner of the display\r
+;\r
+; ENTRY: No Parameters are passed\r
+;\r
+; EXIT:  AX = Current Horizontal Scroll Offset\r
+;\r
+\r
+    PUBLIC  GET_X_OFFSET\r
+\r
+GET_X_OFFSET    PROC    FAR\r
+\r
+    MOV     AX, CURRENT_XOFFSET ; Get current horz offset\r
+    RET                         ; Exit & Clean Up Stack\r
+\r
+GET_X_OFFSET    ENDP\r
+\r
+\r
+;=============\r
+;GET_Y_OFFSET%\r
+;=============\r
+;\r
+; Returns the Y coordinate of the Pixel currently display\r
+; in the upper left corner of the display\r
+;\r
+; ENTRY: No Parameters are passed\r
+;\r
+; EXIT:  AX = Current Vertical Scroll Offset\r
+;\r
+\r
+    PUBLIC  GET_Y_OFFSET\r
+\r
+GET_Y_OFFSET    PROC    FAR\r
+\r
+    MOV     AX, CURRENT_YOFFSET ; Get current vertical offset\r
+    RET                         ; Exit & Clean Up Stack\r
+\r
+GET_Y_OFFSET    ENDP\r
+\r
+\r
+;============\r
+;SYNC_DISPLAY\r
+;============\r
+;\r
+; Pauses the computer until the next Vertical Retrace starts\r
+;\r
+; ENTRY: No Parameters are passed\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+    PUBLIC  SYNC_DISPLAY\r
+\r
+SYNC_DISPLAY    PROC    FAR\r
+\r
+    MOV     DX, INPUT_1         ; Input Status #1 Register\r
+\r
+    ; Wait for any current retrace to end\r
+\r
+@SD_WAIT0:\r
+    IN      AL, DX              ; Get VGA status\r
+    AND     AL, VERT_RETRACE    ; In Display mode yet?\r
+    JNZ     @SD_WAIT0           ; If Not, wait for it\r
+\r
+    ; Wait for the start of the next vertical retrace\r
+\r
+@SD_WAIT1:\r
+    IN      AL, DX              ; Get VGA status\r
+    AND     AL, VERT_RETRACE    ; Vertical Retrace Start?\r
+    JZ      @SD_WAIT1           ; If Not, wait for it\r
+\r
+    RET                         ; Exit & Clean Up Stack\r
+\r
+SYNC_DISPLAY    ENDP\r
+\r
+\r
+    ; ===== TEXT DISPLAY ROUTINES =====\r
+\r
+;==================================================\r
+;GPRINTC (CharNum%, Xpos%, Ypos%, ColorF%, ColorB%)\r
+;==================================================\r
+;\r
+; Draws an ASCII Text Character using the currently selected\r
+; 8x8 font on the active display page.  It would be a simple\r
+; exercise to make this routine process variable height fonts.\r
+;\r
+; ENTRY: CharNum = ASCII character # to draw\r
+;        Xpos    = X position to draw Character at\r
+;        Ypos    = Y position of to draw Character at\r
+;        ColorF  = Color to draw text character in\r
+;        ColorB  = Color to set background to\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+GPC_STACK   STRUC\r
+    GPC_Width   DW  ?   ; Screen Width-1\r
+    GPC_Lines   DB  ?,? ; Scan lines to Decode\r
+    GPC_T_SETS  DW  ?   ; Saved Charset Segment\r
+    GPC_T_SETO  DW  ?   ; Saved Charset Offset\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DD  ?   ; Caller\r
+    GPC_ColorB  DB  ?,? ; Background Color\r
+    GPC_ColorF  DB  ?,? ; Text Color\r
+    GPC_Ypos    DW  ?   ; Y Position to Print at\r
+    GPC_Xpos    DW  ?   ; X position to Print at\r
+    GPC_Char    DB  ?,? ; Character to Print\r
+GPC_STACK   ENDS\r
+\r
+        PUBLIC GPRINTC\r
+\r
+GPRINTC     PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+       push    di\r
+    SUB     SP, 8               ; Allocate WorkSpace on Stack\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+\r
+    MOV     AX, SCREEN_WIDTH    ; Get Logical Line Width\r
+    MOV     BX, AX              ; BX = Screen Width\r
+    DEC     BX                  ;    = Screen Width-1\r
+    MOV     [BP].GPC_Width, BX  ; Save for later use\r
+\r
+    MUL     [BP].GPC_Ypos       ; Start of Line = Ypos * Width\r
+    ADD     DI, AX              ; DI -> Start of Line Ypos\r
+\r
+    MOV     AX, [BP].GPC_Xpos   ; Get Xpos of Character\r
+    MOV     CX, AX              ; Save Copy of Xpos\r
+    SHR     AX, 1               ; Bytes into Line = Xpos/4\r
+    SHR     AX, 1               ; Bytes into Line = Xpos/4\r
+    ADD     DI, AX              ; DI -> (Xpos, Ypos)\r
+\r
+    ;Get Source ADDR of Character Bit Map  & Save\r
+\r
+    MOV     AL, [BP].GPC_Char   ; Get Character #\r
+    TEST    AL, 080h            ; Is Hi Bit Set?\r
+    JZ      @GPC_LowChar        ; Nope, use low char set ptr\r
+\r
+    AND     AL, 07Fh            ; Mask Out Hi Bit\r
+    MOV     BX, CHARSET_HI      ; BX = Char Set Ptr:Offset\r
+    MOV     DX, CHARSET_HI+2    ; DX = Char Set Ptr:Segment\r
+    JMP     s @GPC_Set_Char     ; Go Setup Character Ptr\r
+\r
+@GPC_LowChar:\r
+\r
+    MOV     BX, CHARSET_LOW     ; BX = Char Set Ptr:Offset\r
+    MOV     DX, CHARSET_LOW+2   ; DX = Char Set Ptr:Segment\r
+\r
+@GPC_Set_Char:\r
+    MOV     [BP].GPC_T_SETS, DX ; Save Segment on Stack\r
+\r
+    MOV     AH, 0               ; Valid #'s are 0..127\r
+    SHL     AX, 1               ; * 8 Bytes Per Bitmap\r
+    SHL     AX, 1               ; * 8 Bytes Per Bitmap\r
+    SHL     AX, 1               ; * 8 Bytes Per Bitmap\r
+    ADD     BX, AX              ; BX = Offset of Selected char\r
+    MOV     [BP].GPC_T_SETO, BX ; Save Offset on Stack\r
+\r
+    AND     CX, PLANE_BITS      ; Get Plane #\r
+    MOV     CH, ALL_PLANES      ; Get Initial Plane mask\r
+    SHL     CH, CL              ; And shift into position\r
+    AND     CH, ALL_PLANES      ; And mask to lower nibble\r
+\r
+    MOV     AL, 04              ; 4-Plane # = # of initial\r
+    SUB     AL, CL              ; shifts to align bit mask\r
+    MOV     CL, AL              ; Shift Count for SHL\r
+\r
+    ;Get segment of character map\r
+\r
+    OUT_8   SC_Index, MAP_MASK  ; Setup Plane selections\r
+    INC     DX                  ; DX -> SC_Data\r
+\r
+    MOV     AL, 08              ; 8 Lines to Process\r
+    MOV     [BP].GPC_Lines, AL  ; Save on Stack\r
+\r
+    MOV     DS, [BP].GPC_T_SETS ; Point to character set\r
+\r
+@GPC_DECODE_CHAR_BYTE:\r
+\r
+    MOV     SI, [BP].GPC_T_SETO ; Get DS:SI = String\r
+\r
+    MOV     BH, [SI]            ; Get Bit Map\r
+    INC     SI                  ; Point to Next Line\r
+    MOV     [BP].GPC_T_SETO, SI ; And save new Pointer...\r
+\r
+    mov ax,0                  ; Clear AX\r
+\r
+    ;mov bl,0                      ; Clear BL\r
+    mov bl,0\r
+    ROL     BX, CL                  ; BL holds left edge bits\r
+    MOV     SI, BX                  ; Use as Table Index\r
+    AND     SI, CHAR_BITS           ; Get Low Bits\r
+    MOV     AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+    JZ      @GPC_NO_LEFT1BITS       ; Skip if No Pixels to set\r
+\r
+    MOV     AH, [BP].GPC_ColorF ; Get Foreground Color\r
+    OUT     DX, AL              ; Set up Screen Mask\r
+    MOV     ES:[DI], AH         ; Write Foreground color\r
+\r
+@GPC_NO_LEFT1BITS:\r
+    XOR     AL, CH              ; Invert mask for Background\r
+    JZ      @GPC_NO_LEFT0BITS   ; Hey, no need for this\r
+\r
+    MOV     AH, [BP].GPC_ColorB ; Get background Color\r
+    OUT     DX, AL              ; Set up Screen Mask\r
+    MOV     ES:[DI], AH         ; Write Foreground color\r
+\r
+    ;Now Do Middle/Last Band\r
+\r
+@GPC_NO_LEFT0BITS:\r
+    INC     DI                  ; Point to next Byte\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+\r
+    MOV     SI, BX                  ; Make Lookup Pointer\r
+    AND     SI, CHAR_BITS           ; Get Low Bits\r
+    MOV     AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+    JZ      @GPC_NO_MIDDLE1BITS     ; Skip if no pixels to set\r
+\r
+    MOV     AH, [BP].GPC_ColorF ; Get Foreground Color\r
+    OUT     DX, AL              ; Set up Screen Mask\r
+    MOV     ES:[DI], AH         ; Write Foreground color\r
+\r
+@GPC_NO_MIDDLE1BITS:\r
+    XOR     AL, ALL_PLANES      ; Invert mask for Background\r
+    JZ      @GPC_NO_MIDDLE0BITS ; Hey, no need for this\r
+\r
+    MOV     AH, [BP].GPC_ColorB ; Get background Color\r
+    OUT     DX, AL              ; Set up Screen Mask\r
+    MOV     ES:[DI], AH         ; Write Foreground color\r
+\r
+@GPC_NO_MIDDLE0BITS:\r
+    XOR     CH, ALL_PLANES      ; Invert Clip Mask\r
+    CMP     CL, 4               ; Aligned by 4?\r
+    JZ      @GPC_NEXT_LINE      ; If so, Exit now..\r
+\r
+    INC     DI                  ; Point to next Byte\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+\r
+    MOV     SI, BX                  ; Make Lookup Pointer\r
+    AND     SI, CHAR_BITS           ; Get Low Bits\r
+    MOV     AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+    JZ      @GPC_NO_RIGHT1BITS      ; Skip if No Pixels to set\r
+\r
+    MOV     AH, [BP].GPC_ColorF ; Get Foreground Color\r
+    OUT     DX, AL              ; Set up Screen Mask\r
+    MOV     ES:[DI], AH         ; Write Foreground color\r
+\r
+@GPC_NO_RIGHT1BITS:\r
+\r
+    XOR     AL, CH              ; Invert mask for Background\r
+    JZ      @GPC_NO_RIGHT0BITS  ; Hey, no need for this\r
+\r
+    MOV     AH, [BP].GPC_ColorB ; Get background Color\r
+    OUT     DX, AL              ; Set up Screen Mask\r
+    MOV     ES:[DI], AH         ; Write Foreground color\r
+\r
+@GPC_NO_RIGHT0BITS:\r
+    DEC     DI                  ; Adjust for Next Line Advance\r
+\r
+@GPC_NEXT_LINE:\r
+    ADD     DI, [BP].GPC_Width  ; Point to Next Line\r
+    XOR     CH, CHAR_BITS       ; Flip the Clip mask back\r
+\r
+    DEC     [BP].GPC_Lines      ; Count Down Lines\r
+    JZ      @GPC_EXIT           ; Ok... Done!\r
+\r
+    JMP     @GPC_DECODE_CHAR_BYTE   ; Again! Hey!\r
+\r
+@GPC_EXIT:\r
+    ADD     SP, 08              ; Deallocate stack workspace\r
+    ;POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    RET     10                  ; Exit and Clean up Stack\r
+\r
+GPRINTC  ENDP\r
+\r
+\r
+;==========================================\r
+;TGPRINTC (CharNum%, Xpos%, Ypos%, ColorF%)\r
+;==========================================\r
+;\r
+; Transparently draws an ASCII Text Character using the\r
+; currently selected 8x8 font on the active display page.\r
+;\r
+; ENTRY: CharNum = ASCII character # to draw\r
+;        Xpos    = X position to draw Character at\r
+;        Ypos    = Y position of to draw Character at\r
+;        ColorF  = Color to draw text character in\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+TGP_STACK   STRUC\r
+    TGP_Width   DW  ?   ; Screen Width-1\r
+    TGP_Lines   DB  ?,? ; Scan lines to Decode\r
+    TGP_T_SETS  DW  ?   ; Saved Charset Segment\r
+    TGP_T_SETO  DW  ?   ; Saved Charset Offset\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DD  ?   ; Caller\r
+    TGP_ColorF  DB  ?,? ; Text Color\r
+    TGP_Ypos    DW  ?   ; Y Position to Print at\r
+    TGP_Xpos    DW  ?   ; X position to Print at\r
+    TGP_Char    DB  ?,? ; Character to Print\r
+TGP_STACK   ENDS\r
+\r
+        PUBLIC TGPRINTC\r
+\r
+TGPRINTC    PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+       push    di\r
+    SUB     SP, 8               ; Allocate WorkSpace on Stack\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+\r
+    MOV     AX, SCREEN_WIDTH    ; Get Logical Line Width\r
+    MOV     BX, AX              ; BX = Screen Width\r
+    DEC     BX                  ;    = Screen Width-1\r
+    MOV     [BP].TGP_Width, BX  ; Save for later use\r
+\r
+    MUL     [BP].TGP_Ypos       ; Start of Line = Ypos * Width\r
+    ADD     DI, AX              ; DI -> Start of Line Ypos\r
+\r
+    MOV     AX, [BP].TGP_Xpos   ; Get Xpos of Character\r
+    MOV     CX, AX              ; Save Copy of Xpos\r
+    SHR     AX, 1               ; Bytes into Line = Xpos/4\r
+    SHR     AX, 1               ; Bytes into Line = Xpos/4\r
+    ADD     DI, AX              ; DI -> (Xpos, Ypos)\r
+\r
+    ;Get Source ADDR of Character Bit Map  & Save\r
+\r
+    MOV     AL, [BP].TGP_Char   ; Get Character #\r
+    TEST    AL, 080h            ; Is Hi Bit Set?\r
+    JZ      @TGP_LowChar        ; Nope, use low char set ptr\r
+\r
+    AND     AL, 07Fh            ; Mask Out Hi Bit\r
+    MOV     BX, CHARSET_HI      ; BX = Char Set Ptr:Offset\r
+    MOV     DX, CHARSET_HI+2    ; DX = Char Set Ptr:Segment\r
+    JMP     s @TGP_Set_Char     ; Go Setup Character Ptr\r
+\r
+@TGP_LowChar:\r
+\r
+    MOV     BX, CHARSET_LOW     ; BX = Char Set Ptr:Offset\r
+    MOV     DX, CHARSET_LOW+2   ; DX = Char Set Ptr:Segment\r
+\r
+@TGP_Set_Char:\r
+    MOV     [BP].TGP_T_SETS, DX ; Save Segment on Stack\r
+\r
+    MOV     AH, 0               ; Valid #'s are 0..127\r
+    SHL     AX, 1               ; * 8 Bytes Per Bitmap\r
+    SHL     AX, 1               ; * 8 Bytes Per Bitmap\r
+    SHL     AX, 1               ; * 8 Bytes Per Bitmap\r
+    ADD     BX, AX              ; BX = Offset of Selected char\r
+    MOV     [BP].TGP_T_SETO, BX ; Save Offset on Stack\r
+\r
+    AND     CX, PLANE_BITS      ; Get Plane #\r
+    MOV     CH, ALL_PLANES      ; Get Initial Plane mask\r
+    SHL     CH, CL              ; And shift into position\r
+    AND     CH, ALL_PLANES      ; And mask to lower nibble\r
+\r
+    MOV     AL, 04              ; 4-Plane # = # of initial\r
+    SUB     AL, CL              ; shifts to align bit mask\r
+    MOV     CL, AL              ; Shift Count for SHL\r
+\r
+    ;Get segment of character map\r
+\r
+    OUT_8   SC_Index, MAP_MASK  ; Setup Plane selections\r
+    INC     DX                  ; DX -> SC_Data\r
+\r
+    MOV     AL, 08              ; 8 Lines to Process\r
+    MOV     [BP].TGP_Lines, AL  ; Save on Stack\r
+\r
+    MOV     DS, [BP].TGP_T_SETS ; Point to character set\r
+\r
+@TGP_DECODE_CHAR_BYTE:\r
+\r
+    MOV     SI, [BP].TGP_T_SETO ; Get DS:SI = String\r
+\r
+    MOV     BH, [SI]            ; Get Bit Map\r
+    INC     SI                  ; Point to Next Line\r
+    MOV     [BP].TGP_T_SETO, SI ; And save new Pointer...\r
+\r
+    MOV     AH, [BP].TGP_ColorF ; Get Foreground Color\r
+\r
+    mov bl,0                      ; Clear BL\r
+    ROL     BX, CL                  ; BL holds left edge bits\r
+    MOV     SI, BX                  ; Use as Table Index\r
+    AND     SI, CHAR_BITS           ; Get Low Bits\r
+    MOV     AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+    JZ      @TGP_NO_LEFT1BITS       ; Skip if No Pixels to set\r
+\r
+    OUT     DX, AL              ; Set up Screen Mask\r
+    MOV     ES:[DI], AH         ; Write Foreground color\r
+\r
+    ;Now Do Middle/Last Band\r
+\r
+@TGP_NO_LEFT1BITS:\r
+\r
+    INC     DI                  ; Point to next Byte\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+\r
+    MOV     SI, BX                  ; Make Lookup Pointer\r
+    AND     SI, CHAR_BITS           ; Get Low Bits\r
+    MOV     AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+    JZ      @TGP_NO_MIDDLE1BITS     ; Skip if no pixels to set\r
+\r
+    OUT     DX, AL              ; Set up Screen Mask\r
+    MOV     ES:[DI], AH         ; Write Foreground color\r
+\r
+@TGP_NO_MIDDLE1BITS:\r
+    XOR     CH, ALL_PLANES      ; Invert Clip Mask\r
+    CMP     CL, 4               ; Aligned by 4?\r
+    JZ      @TGP_NEXT_LINE      ; If so, Exit now..\r
+\r
+    INC     DI                  ; Point to next Byte\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+\r
+    MOV     SI, BX                  ; Make Lookup Pointer\r
+    AND     SI, CHAR_BITS           ; Get Low Bits\r
+    MOV     AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+    JZ      @TGP_NO_RIGHT1BITS      ; Skip if No Pixels to set\r
+\r
+    OUT     DX, AL              ; Set up Screen Mask\r
+    MOV     ES:[DI], AH         ; Write Foreground color\r
+\r
+@TGP_NO_RIGHT1BITS:\r
+\r
+    DEC     DI                  ; Adjust for Next Line Advance\r
+\r
+@TGP_NEXT_LINE:\r
+    ADD     DI, [BP].TGP_Width  ; Point to Next Line\r
+    XOR     CH, CHAR_BITS       ; Flip the Clip mask back\r
+\r
+    DEC     [BP].TGP_Lines      ; Count Down Lines\r
+    JZ      @TGP_EXIT           ; Ok... Done!\r
+\r
+    JMP     @TGP_DECODE_CHAR_BYTE   ; Again! Hey!\r
+\r
+@TGP_EXIT:\r
+    ADD     SP, 08              ; Deallocate stack workspace\r
+    ;POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    RET     8                   ; Exit and Clean up Stack\r
+\r
+TGPRINTC    ENDP\r
+\r
+\r
+;===============================================================\r
+;PRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%)\r
+;===============================================================\r
+;\r
+; Routine to quickly Print a null terminated ASCII string on the\r
+; active display page up to a maximum length.\r
+;\r
+; ENTRY: String  = Far Pointer to ASCII string to print\r
+;        MaxLen  = # of characters to print if no null found\r
+;        Xpos    = X position to draw Text at\r
+;        Ypos    = Y position of to draw Text at\r
+;        ColorF  = Color to draw text in\r
+;        ColorB  = Color to set background to\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+PS_STACK    STRUC\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DD  ?   ; Caller\r
+    PS_ColorB   DW  ?   ; Background Color\r
+    PS_ColorF   DW  ?   ; Text Color\r
+    PS_Ypos     DW  ?   ; Y Position to Print at\r
+    PS_Xpos     DW  ?   ; X position to Print at\r
+    PS_Len      DW  ?   ; Maximum Length of string to print\r
+    PS_Text     DW  ?,? ; Far Ptr to Text String\r
+PS_STACK    ENDS\r
+\r
+        PUBLIC  PRINT_STR\r
+\r
+PRINT_STR   PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+       push    di\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+@PS_Print_It:\r
+\r
+    MOV     CX, [BP].PS_Len     ; Get Remaining text Length\r
+    JCXZ    @PS_Exit            ; Exit when out of text\r
+\r
+    LES     DI, d [BP].PS_Text  ; ES:DI -> Current Char in Text\r
+    MOV     AL, ES:[DI]         ; AL = Text Character\r
+    AND     AX, 00FFh           ; Clear High Word\r
+    JZ      @PS_Exit            ; Exit if null character\r
+\r
+    DEC     [BP].PS_Len         ; Remaining Text length--\r
+    INC     [BP].PS_Text        ; Point to Next text char\r
+\r
+    ; Set up Call to GPRINTC\r
+\r
+    PUSH    AX                  ; Set Character Parameter\r
+    MOV     BX, [BP].PS_Xpos    ; Get Xpos\r
+    PUSH    BX                  ; Set Xpos Parameter\r
+    ADD     BX, 8               ; Advance 1 Char to Right\r
+    MOV     [BP].PS_Xpos, BX    ; Save for next time through\r
+\r
+    MOV     BX, [BP].PS_Ypos    ; Get Ypos\r
+    PUSH    BX                  ; Set Ypos Parameter\r
+\r
+    MOV     BX, [BP].PS_ColorF  ; Get Text Color\r
+    PUSH    BX                  ; Set ColorF Parameter\r
+\r
+    MOV     BX, [BP].PS_ColorB  ; Get Background Color\r
+    PUSH    BX                  ; Set ColorB Parameter\r
+\r
+    CALL    f GPRINTC           ; Print Character!\r
+    JMP     s @PS_Print_It      ; Process next character\r
+\r
+@PS_Exit:\r
+    ;POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    RET     14                  ; Exit and Clean up Stack\r
+\r
+PRINT_STR  ENDP\r
+\r
+\r
+;================================================================\r
+;TPRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%)\r
+;================================================================\r
+;\r
+; Routine to quickly transparently Print a null terminated ASCII\r
+; string on the active display page up to a maximum length.\r
+;\r
+; ENTRY: String  = Far Pointer to ASCII string to print\r
+;        MaxLen  = # of characters to print if no null found\r
+;        Xpos    = X position to draw Text at\r
+;        Ypos    = Y position of to draw Text at\r
+;        ColorF  = Color to draw text in\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+TPS_STACK   STRUC\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DD  ?   ; Caller\r
+    TPS_ColorF  DW  ?   ; Text Color\r
+    TPS_Ypos    DW  ?   ; Y Position to Print at\r
+    TPS_Xpos    DW  ?   ; X position to Print at\r
+    TPS_Len     DW  ?   ; Maximum Length of string to print\r
+    TPS_Text    DW  ?,? ; Far Ptr to Text String\r
+TPS_STACK   ENDS\r
+\r
+        PUBLIC  TPRINT_STR\r
+\r
+TPRINT_STR  PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+       push    di\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+@TPS_Print_It:\r
+\r
+    MOV     CX, [BP].TPS_Len    ; Get Remaining text Length\r
+    JCXZ    @TPS_Exit           ; Exit when out of text\r
+\r
+    LES     DI, d [BP].TPS_Text ; ES:DI -> Current Char in Text\r
+    MOV     AL, ES:[DI]         ; AL = Text Character\r
+    AND     AX, 00FFh           ; Clear High Word\r
+    JZ      @TPS_Exit           ; Exit if null character\r
+\r
+    DEC     [BP].TPS_Len        ; Remaining Text length--\r
+    INC     [BP].TPS_Text       ; Point to Next text char\r
+\r
+    ; Set up Call to TGPRINTC\r
+\r
+    PUSH    AX                  ; Set Character Parameter\r
+    MOV     BX, [BP].TPS_Xpos   ; Get Xpos\r
+    PUSH    BX                  ; Set Xpos Parameter\r
+    ADD     BX, 8               ; Advance 1 Char to Right\r
+    MOV     [BP].TPS_Xpos, BX   ; Save for next time through\r
+\r
+    MOV     BX, [BP].TPS_Ypos   ; Get Ypos\r
+    PUSH    BX                  ; Set Ypos Parameter\r
+\r
+    MOV     BX, [BP].TPS_ColorF ; Get Text Color\r
+    PUSH    BX                  ; Set ColorF Parameter\r
+\r
+    CALL    f TGPRINTC          ; Print Character!\r
+    JMP     s @TPS_Print_It     ; Process next character\r
+\r
+@TPS_Exit:\r
+    ;POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    RET     12                  ; Exit and Clean up Stack\r
+\r
+TPRINT_STR  ENDP\r
+\r
+\r
+;===========================================\r
+;SET_DISPLAY_FONT(SEG FontData, FontNumber%)\r
+;===========================================\r
+;\r
+; Allows the user to specify their own font data for\r
+; wither the lower or upper 128 characters.\r
+;\r
+; ENTRY: FontData   = Far Pointer to Font Bitmaps\r
+;        FontNumber = Which half of set this is\r
+;                   = 0, Lower 128 characters\r
+;                   = 1, Upper 128 characters\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+SDF_STACK   STRUC\r
+                DW  ?   ; BP\r
+                DD  ?   ; Caller\r
+    SDF_Which   DW  ?   ; Hi Table/Low Table Flag\r
+    SDF_Font    DD  ?   ; Far Ptr to Font Table\r
+SDF_STACK   ENDS\r
+\r
+    PUBLIC  SET_DISPLAY_FONT\r
+\r
+SET_DISPLAY_FONT    PROC    FAR\r
+\r
+    PUSH    BP                  ; Preserve Registers\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    LES     DI, [BP].SDF_Font   ; Get Far Ptr to Font\r
+\r
+    MOV     SI, o CHARSET_LOW   ; Assume Lower 128 chars\r
+    TEST    [BP].SDF_Which, 1   ; Font #1 selected?\r
+    JZ      @SDF_Set_Font       ; If not, skip ahead\r
+\r
+    MOV     SI, o CHARSET_HI    ; Ah, really it's 128-255\r
+\r
+@SDF_Set_Font:\r
+    MOV     [SI], DI            ; Set Font Pointer Offset\r
+    MOV     [SI+2], ES          ; Set Font Pointer Segment\r
+\r
+    POP     BP                  ; Restore Registers\r
+    RET     6                   ; We are Done.. Outa here\r
+\r
+SET_DISPLAY_FONT    ENDP\r
+\r
+\r
+    ; ===== BITMAP (SPRITE) DISPLAY ROUTINES =====\r
+\r
+;======================================================\r
+;DRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%)\r
+;======================================================\r
+;\r
+; Draws a variable sized Graphics Bitmap such as a\r
+; picture or an Icon on the current Display Page in\r
+; Mode X.  The Bitmap is stored in a linear byte array\r
+; corresponding to (0,0) (1,0), (2,0) .. (Width, Height)\r
+; This is the same linear manner as mode 13h graphics.\r
+;\r
+; ENTRY: Image  = Far Pointer to Bitmap Data\r
+;        Xpos   = X position to Place Upper Left pixel at\r
+;        Ypos   = Y position to Place Upper Left pixel at\r
+;        Width  = Width of the Bitmap in Pixels\r
+;        Height = Height of the Bitmap in Pixels\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+DB_STACK    STRUC\r
+    DB_LineO    DW  ?   ; Offset to Next Line\r
+    DB_PixCount DW  ?   ; (Minimum) # of Pixels/Line\r
+    DB_Start    DW  ?   ; Addr of Upper Left Pixel\r
+    DB_PixSkew  DW  ?   ; # of bytes to Adjust EOL\r
+    DB_SkewFlag DW  ?   ; Extra Pix on Plane Flag\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DD  ?   ; Caller\r
+    DB_Height   DW  ?   ; Height of Bitmap in Pixels\r
+    DB_Width    DW  ?   ; Width of Bitmap in Pixels\r
+    DB_Ypos     DW  ?   ; Y position to Draw Bitmap at\r
+    DB_Xpos     DW  ?   ; X position to Draw Bitmap at\r
+    DB_Image    DD  ?   ; Far Pointer to Graphics Bitmap\r
+DB_STACK    ENDS\r
+\r
+        PUBLIC    DRAW_BITMAP\r
+\r
+DRAW_BITMAP PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+       push    di\r
+    SUB     SP, 10              ; Allocate workspace\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+    CLD                         ; Direction Flag = Forward\r
+\r
+    MOV     AX, [BP].DB_Ypos    ; Get UL Corner Ypos\r
+    MUL     SCREEN_WIDTH        ; AX = Offset to Line Ypos\r
+\r
+    MOV     BX, [BP].DB_Xpos    ; Get UL Corner Xpos\r
+    MOV     CL, BL              ; Save Plane # in CL\r
+    SHR     BX, 1               ; Xpos/4 = Offset Into Line\r
+    SHR     BX, 1               ; Xpos/4 = Offset Into Line\r
+\r
+    ADD     DI, AX              ; ES:DI -> Start of Line\r
+    ADD     DI, BX              ; ES:DI -> Upper Left Pixel\r
+    MOV     [BP].DB_Start, DI   ; Save Starting Addr\r
+\r
+    ; Compute line to line offset\r
+\r
+    MOV     BX, [BP].DB_Width   ; Get Width of Image\r
+    MOV     DX, BX              ; Save Copy in DX\r
+    SHR     BX, 1               ; /4 = width in bands\r
+    SHR     BX, 1               ; /4 = width in bands\r
+    MOV     AX, SCREEN_WIDTH    ; Get Screen Width\r
+    SUB     AX, BX              ; - (Bitmap Width/4)\r
+\r
+    MOV     [BP].DB_LineO, AX       ; Save Line Width offset\r
+    MOV     [BP].DB_PixCount, BX    ; Minimum # pix to copy\r
+\r
+    AND     DX, PLANE_BITS          ; Get "partial band" size (0-3)\r
+    MOV     [BP].DB_PixSkew, DX     ; Also End of Line Skew\r
+    MOV     [BP].DB_SkewFlag, DX    ; Save as Flag/Count\r
+\r
+    AND     CX, PLANE_BITS      ; CL = Starting Plane #\r
+    MOV     AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select\r
+    SHL     AH, CL              ; Select correct Plane\r
+    OUT_16  SC_Index, AX        ; Select Plane...\r
+    MOV     BH, AH              ; BH = Saved Plane Mask\r
+    MOV     BL, 4               ; BL = Planes to Copy\r
+\r
+@DB_COPY_PLANE:\r
+\r
+    LDS     SI, [BP].DB_Image   ; DS:SI-> Source Image\r
+    MOV     DX, [BP].DB_Height  ; # of Lines to Copy\r
+    MOV     DI, [BP].DB_Start   ; ES:DI-> Dest pos\r
+\r
+@DB_COPY_LINE:\r
+    MOV     CX, [BP].DB_PixCount    ; Min # to copy\r
+\r
+    TEST    CL, 0FCh            ; 16+PixWide?\r
+    JZ      @DB_COPY_REMAINDER  ; Nope...\r
+\r
+    ; Pixel Copy loop has been unrolled to x4\r
+\r
+@DB_COPY_LOOP:\r
+    MOVSB                       ; Copy Bitmap Pixel\r
+    ADD     SI, 3               ; Skip to Next Byte in same plane\r
+    MOVSB                       ; Copy Bitmap Pixel\r
+    ADD     SI, 3               ; Skip to Next Byte in same plane\r
+    MOVSB                       ; Copy Bitmap Pixel\r
+    ADD     SI, 3               ; Skip to Next Byte in same plane\r
+    MOVSB                       ; Copy Bitmap Pixel\r
+    ADD     SI, 3               ; Skip to Next Byte in same plane\r
+\r
+    SUB     CL, 4               ; Pixels to Copy=-4\r
+    TEST    CL, 0FCh            ; 4+ Pixels Left?\r
+    JNZ     @DB_COPY_LOOP       ; if so, do another block\r
+\r
+@DB_COPY_REMAINDER:\r
+    JCXZ    @DB_NEXT_LINE       ; Any Pixels left on line\r
+\r
+@DB_COPY2:\r
+    MOVSB                       ; Copy Bitmap Pixel\r
+    ADD     SI,3                ; Skip to Next Byte in same plane\r
+    LOOPx   CX, @DB_COPY2       ; Pixels to Copy--, Loop until done\r
+\r
+@DB_NEXT_LINE:\r
+\r
+    ; any Partial Pixels? (some planes only)\r
+\r
+    OR      CX, [BP].DB_SkewFlag    ; Get Skew Count\r
+    JZ      @DB_NEXT2               ; if no partial pixels\r
+\r
+    MOVSB                       ; Copy Bitmap Pixel\r
+    DEC     DI                  ; Back up to align\r
+    DEC     SI                  ; Back up to align\r
+\r
+@DB_NEXT2:\r
+    ADD     SI, [BP].DB_PixSkew ; Adjust Skew\r
+    ADD     DI, [BP].DB_LineO   ; Set to Next Display Line\r
+    LOOPx   DX, @DB_COPY_LINE   ; Lines to Copy--, Loop if more\r
+\r
+    ; Copy Next Plane....\r
+\r
+    DEC     BL                  ; Planes to Go--\r
+    JZ      @DB_Exit            ; Hey! We are done\r
+\r
+    ROL     BH, 1               ; Next Plane in line...\r
+    OUT_8   SC_Data, BH         ; Select Plane\r
+\r
+    CMP     AL, 12h             ; Carry Set if AL=11h\r
+    ADC     [BP].DB_Start, 0    ; Screen Addr =+Carry\r
+    INC     w [BP].DB_Image     ; Start @ Next Byte\r
+\r
+    SUB     [BP].DB_SkewFlag, 1 ; Reduce Planes to Skew\r
+    ADC     [BP].DB_SkewFlag, 0 ; Back to 0 if it was -1\r
+\r
+    JMP     s @DB_COPY_PLANE    ; Go Copy the Next Plane\r
+\r
+@DB_Exit:\r
+    ADD     SP, 10              ; Deallocate workspace\r
+    ;POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    RET     12                  ; Exit and Clean up Stack\r
+\r
+DRAW_BITMAP   ENDP\r
+\r
+\r
+;=======================================================\r
+;TDRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%)\r
+;=======================================================\r
+;\r
+; Transparently Draws a variable sized Graphics Bitmap\r
+; such as a picture or an Icon on the current Display Page\r
+; in Mode X.  Pixels with a value of 0 are not drawn,\r
+; leaving the previous "background" contents intact.\r
+;\r
+; The Bitmap format is the same as for the DRAW_BITMAP function.\r
+;\r
+; ENTRY: Image  = Far Pointer to Bitmap Data\r
+;        Xpos   = X position to Place Upper Left pixel at\r
+;        Ypos   = Y position to Place Upper Left pixel at\r
+;        Width  = Width of the Bitmap in Pixels\r
+;        Height = Height of the Bitmap in Pixels\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+TB_STACK    STRUC\r
+    TB_LineO    DW  ?   ; Offset to Next Line\r
+    TB_PixCount DW  ?   ; (Minimum) # of Pixels/Line\r
+    TB_Start    DW  ?   ; Addr of Upper Left Pixel\r
+    TB_PixSkew  DW  ?   ; # of bytes to Adjust EOL\r
+    TB_SkewFlag DW  ?   ; Extra Pix on Plane Flag\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DD  ?   ; Caller\r
+    TB_Height   DW  ?   ; Height of Bitmap in Pixels\r
+    TB_Width    DW  ?   ; Width of Bitmap in Pixels\r
+    TB_Ypos     DW  ?   ; Y position to Draw Bitmap at\r
+    TB_Xpos     DW  ?   ; X position to Draw Bitmap at\r
+    TB_Image    DD  ?   ; Far Pointer to Graphics Bitmap\r
+TB_STACK    ENDS\r
+\r
+        PUBLIC    TDRAW_BITMAP\r
+\r
+TDRAW_BITMAP    PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+       push    di\r
+    SUB     SP, 10              ; Allocate workspace\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+    CLD                         ; Direction Flag = Forward\r
+\r
+    MOV     AX, [BP].TB_Ypos    ; Get UL Corner Ypos\r
+    MUL     SCREEN_WIDTH        ; AX = Offset to Line Ypos\r
+\r
+    MOV     BX, [BP].TB_Xpos    ; Get UL Corner Xpos\r
+    MOV     CL, BL              ; Save Plane # in CL\r
+    SHR     BX, 1               ; Xpos/4 = Offset Into Line\r
+    SHR     BX, 1               ; Xpos/4 = Offset Into Line\r
+\r
+    ADD     DI, AX              ; ES:DI -> Start of Line\r
+    ADD     DI, BX              ; ES:DI -> Upper Left Pixel\r
+    MOV     [BP].TB_Start, DI   ; Save Starting Addr\r
+\r
+    ; Compute line to line offset\r
+\r
+    MOV     BX, [BP].TB_Width   ; Get Width of Image\r
+    MOV     DX, BX              ; Save Copy in DX\r
+    SHR     BX, 1               ; /4 = width in bands\r
+    SHR     BX, 1               ; /4 = width in bands\r
+    MOV     AX, SCREEN_WIDTH    ; Get Screen Width\r
+    SUB     AX, BX              ; - (Bitmap Width/4)\r
+\r
+    MOV     [BP].TB_LineO, AX       ; Save Line Width offset\r
+    MOV     [BP].TB_PixCount, BX    ; Minimum # pix to copy\r
+\r
+    AND     DX, PLANE_BITS          ; Get "partial band" size (0-3)\r
+    MOV     [BP].TB_PixSkew, DX     ; Also End of Line Skew\r
+    MOV     [BP].TB_SkewFlag, DX    ; Save as Flag/Count\r
+\r
+    AND     CX, PLANE_BITS      ; CL = Starting Plane #\r
+    MOV     AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select\r
+    SHL     AH, CL              ; Select correct Plane\r
+    OUT_16  SC_Index, AX        ; Select Plane...\r
+    MOV     BH, AH              ; BH = Saved Plane Mask\r
+    MOV     BL, 4               ; BL = Planes to Copy\r
+\r
+@TB_COPY_PLANE:\r
+\r
+    LDS     SI, [BP].TB_Image   ; DS:SI-> Source Image\r
+    MOV     DX, [BP].TB_Height  ; # of Lines to Copy\r
+    MOV     DI, [BP].TB_Start   ; ES:DI-> Dest pos\r
+\r
+    ; Here AH is set with the value to be considered\r
+    ; "Transparent".  It can be changed!\r
+\r
+    MOV     AH, 0               ; Value to Detect 0\r
+\r
+@TB_COPY_LINE:\r
+    MOV     CX, [BP].TB_PixCount    ; Min # to copy\r
+\r
+    TEST    CL, 0FCh            ; 16+PixWide?\r
+    JZ      @TB_COPY_REMAINDER  ; Nope...\r
+\r
+    ; Pixel Copy loop has been unrolled to x4\r
+\r
+@TB_COPY_LOOP:\r
+    LODSB                       ; Get Pixel Value in AL\r
+    ADD     SI, 3               ; Skip to Next Byte in same plane\r
+    CMP     AL, AH              ; It is "Transparent"?\r
+    JE      @TB_SKIP_01         ; Skip ahead if so\r
+    MOV     ES:[DI], AL         ; Copy Pixel to VGA screen\r
+\r
+@TB_SKIP_01:\r
+    LODSB                       ; Get Pixel Value in AL\r
+    ADD     SI, 3               ; Skip to Next Byte in same plane\r
+    CMP     AL, AH              ; It is "Transparent"?\r
+    JE      @TB_SKIP_02         ; Skip ahead if so\r
+    MOV     ES:[DI+1], AL       ; Copy Pixel to VGA screen\r
+\r
+@TB_SKIP_02:\r
+    LODSB                       ; Get Pixel Value in AL\r
+    ADD     SI, 3               ; Skip to Next Byte in same plane\r
+    CMP     AL, AH              ; It is "Transparent"?\r
+    JE      @TB_SKIP_03         ; Skip ahead if so\r
+    MOV     ES:[DI+2], AL       ; Copy Pixel to VGA screen\r
+\r
+@TB_SKIP_03:\r
+    LODSB                       ; Get Pixel Value in AL\r
+    ADD     SI, 3               ; Skip to Next Byte in same plane\r
+    CMP     AL, AH              ; It is "Transparent"?\r
+    JE      @TB_SKIP_04         ; Skip ahead if so\r
+    MOV     ES:[DI+3], AL       ; Copy Pixel to VGA screen\r
+\r
+@TB_SKIP_04:\r
+    ADD     DI, 4               ; Adjust Pixel Write Location\r
+    SUB     CL, 4               ; Pixels to Copy=-4\r
+    TEST    CL, 0FCh            ; 4+ Pixels Left?\r
+    JNZ     @TB_COPY_LOOP       ; if so, do another block\r
+\r
+@TB_COPY_REMAINDER:\r
+    JCXZ    @TB_NEXT_LINE       ; Any Pixels left on line\r
+\r
+@TB_COPY2:\r
+    LODSB                       ; Get Pixel Value in AL\r
+    ADD     SI, 3               ; Skip to Next Byte in same plane\r
+    CMP     AL, AH              ; It is "Transparent"?\r
+    JE      @TB_SKIP_05         ; Skip ahead if so\r
+    MOV     ES:[DI], AL         ; Copy Pixel to VGA screen\r
+\r
+@TB_SKIP_05:\r
+    INC     DI                  ; Advance Dest Addr\r
+    LOOPx   CX, @TB_COPY2       ; Pixels to Copy--, Loop until done\r
+\r
+@TB_NEXT_LINE:\r
+\r
+    ; any Partial Pixels? (some planes only)\r
+\r
+    OR      CX, [BP].TB_SkewFlag    ; Get Skew Count\r
+    JZ      @TB_NEXT2               ; if no partial pixels\r
+\r
+    LODSB                       ; Get Pixel Value in AL\r
+    DEC     SI                  ; Backup to Align\r
+    CMP     AL, AH              ; It is "Transparent"?\r
+    JE      @TB_NEXT2           ; Skip ahead if so\r
+    MOV     ES:[DI], AL         ; Copy Pixel to VGA screen\r
+\r
+@TB_NEXT2:\r
+    ADD     SI, [BP].TB_PixSkew ; Adjust Skew\r
+    ADD     DI, [BP].TB_LineO   ; Set to Next Display Line\r
+    LOOPx   DX, @TB_COPY_LINE   ; Lines to Copy--, Loop if More\r
+\r
+    ;Copy Next Plane....\r
+\r
+    DEC     BL                  ; Planes to Go--\r
+    JZ      @TB_Exit            ; Hey! We are done\r
+\r
+    ROL     BH, 1               ; Next Plane in line...\r
+    OUT_8   SC_Data, BH         ; Select Plane\r
+\r
+    CMP     AL, 12h             ; Carry Set if AL=11h\r
+    ADC     [BP].TB_Start, 0    ; Screen Addr =+Carry\r
+    INC     w [BP].TB_Image     ; Start @ Next Byte\r
+\r
+    SUB     [BP].TB_SkewFlag, 1 ; Reduce Planes to Skew\r
+    ADC     [BP].TB_SkewFlag, 0 ; Back to 0 if it was -1\r
+\r
+    JMP     @TB_COPY_PLANE      ; Go Copy the next Plane\r
+\r
+@TB_Exit:\r
+    ADD     SP, 10              ; Deallocate workspace\r
+    ;POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    RET     12                  ; Exit and Clean up Stack\r
+\r
+TDRAW_BITMAP    ENDP\r
+\r
+\r
+    ; ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====\r
+\r
+;==================================\r
+;COPY_PAGE (SourcePage%, DestPage%)\r
+;==================================\r
+;\r
+; Duplicate on display page onto another\r
+;\r
+; ENTRY: SourcePage = Display Page # to Duplicate\r
+;        DestPage   = Display Page # to hold copy\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+CP_STACK    STRUC\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DD  ?   ; Caller\r
+    CP_DestP    DW  ?   ; Page to hold copied image\r
+    CP_SourceP  DW  ?   ; Page to Make copy from\r
+CP_STACK    ENDS\r
+\r
+        PUBLIC    COPY_PAGE\r
+\r
+COPY_PAGE   PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+       push    di\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+    CLD                         ; Block Xfer Forwards\r
+\r
+    ; Make sure Page #'s are valid\r
+\r
+    MOV     AX, [BP].CP_SourceP ; Get Source Page #\r
+    CMP     AX, LAST_PAGE       ; is it > Max Page #?\r
+    JAE     @CP_Exit            ; if so, abort\r
+\r
+    MOV     BX, [BP].CP_DestP   ; Get Destination Page #\r
+    CMP     BX, LAST_PAGE       ; is it > Max Page #?\r
+    JAE     @CP_Exit            ; if so, abort\r
+\r
+    CMP     AX, BX              ; Pages #'s the same?\r
+    JE      @CP_Exit            ; if so, abort\r
+\r
+    ; Setup DS:SI and ES:DI to Video Pages\r
+\r
+    SHL     BX, 1               ; Scale index to Word\r
+    MOV     DI, PAGE_ADDR[BX]   ; Offset to Dest Page\r
+\r
+    MOV     BX, AX              ; Index to Source page\r
+    SHL     BX, 1               ; Scale index to Word\r
+    MOV     SI, PAGE_ADDR[BX]   ; Offset to Source Page\r
+\r
+    MOV     CX, PAGE_SIZE       ; Get size of Page\r
+    MOV     AX, CURRENT_SEGMENT ; Get Video Mem Segment\r
+    MOV     ES, AX              ; ES:DI -> Dest Page\r
+    MOV     DS, AX              ; DS:SI -> Source Page\r
+\r
+    ; Setup VGA registers for Mem to Mem copy\r
+\r
+    OUT_16  GC_Index, LATCHES_ON    ; Data from Latches = on\r
+    OUT_16  SC_Index, ALL_PLANES_ON ; Copy all Planes\r
+\r
+    ; Note.. Do *NOT* use MOVSW or MOVSD - they will\r
+    ; Screw with the latches which are 8 bits x 4\r
+\r
+    REP     MOVSB               ; Copy entire Page!\r
+\r
+    ; Reset VGA for normal memory access\r
+\r
+    OUT_16  GC_Index, LATCHES_OFF   ; Data from Latches = off\r
+\r
+@CP_Exit:\r
+    ;POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    RET     4                   ; Exit and Clean up Stack\r
+\r
+COPY_PAGE   ENDP\r
+\r
+\r
+;==========================================================================\r
+;COPY_BITMAP (SourcePage%, X1%, Y1%, X2%, Y2%, DestPage%, DestX1%, DestY1%)\r
+;==========================================================================\r
+;\r
+; Copies a Bitmap Image from one Display Page to Another\r
+; This Routine is Limited to copying Images with the same\r
+; Plane Alignment.  To Work: (X1 MOD 4) must = (DestX1 MOD 4)\r
+; Copying an Image to the Same Page is supported, but results\r
+; may be defined when the when the rectangular areas\r
+; (X1, Y1) - (X2, Y2) and (DestX1, DestY1) -\r
+; (DestX1+(X2-X1), DestY1+(Y2-Y1)) overlap...\r
+; No Paramter checking to done to insure that\r
+; X2 >= X1 and Y2 >= Y1.  Be Careful...\r
+;\r
+; ENTRY: SourcePage = Display Page # with Source Image\r
+;        X1         = Upper Left Xpos of Source Image\r
+;        Y1         = Upper Left Ypos of Source Image\r
+;        X2         = Lower Right Xpos of Source Image\r
+;        Y2         = Lower Right Ypos of Source Image\r
+;        DestPage   = Display Page # to copy Image to\r
+;        DestX1     = Xpos to Copy UL Corner of Image to\r
+;        DestY1     = Ypos to Copy UL Corner of Image to\r
+;\r
+; EXIT:  AX = Success Flag:   0 = Failure / -1= Success\r
+;\r
+\r
+CB_STACK    STRUC\r
+    CB_Height   DW  ?   ; Height of Image in Lines\r
+    CB_Width    DW  ?   ; Width of Image in "bands"\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DD  ?   ; Caller\r
+    CB_DestY1   DW  ?   ; Destination Ypos\r
+    CB_DestX1   DW  ?   ; Destination Xpos\r
+    CB_DestP    DW  ?   ; Page to Copy Bitmap To\r
+    CB_Y2       DW  ?   ; LR Ypos of Image\r
+    CB_X2       DW  ?   ; LR Xpos of Image\r
+    CB_Y1       DW  ?   ; UL Ypos of Image\r
+    CB_X1       DW  ?   ; UL Xpos of Image\r
+    CB_SourceP  DW  ?   ; Page containing Source Bitmap\r
+CB_STACK    ENDS\r
+\r
+        PUBLIC    COPY_BITMAP\r
+\r
+COPY_BITMAP PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+       push    di\r
+    SUB     SP, 4               ; Allocate WorkSpace on Stack\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    ; Prep Registers (and keep jumps short!)\r
+\r
+    MOV     ES, CURRENT_SEGMENT ; ES -> VGA Ram\r
+    CLD                         ; Block Xfer Forwards\r
+\r
+    ; Make sure Parameters are valid\r
+\r
+    MOV     BX, [BP].CB_SourceP ; Get Source Page #\r
+    CMP     BX, LAST_PAGE       ; is it > Max Page #?\r
+    JAE     @CB_Abort           ; if so, abort\r
+\r
+    MOV     CX, [BP].CB_DestP   ; Get Destination Page #\r
+    CMP     CX, LAST_PAGE       ; is it > Max Page #?\r
+    JAE     @CB_Abort           ; if so, abort\r
+\r
+    MOV     AX, [BP].CB_X1      ; Get Source X1\r
+    XOR     AX, [BP].CB_DestX1  ; Compare Bits 0-1\r
+    AND     AX, PLANE_BITS      ; Check Plane Bits\r
+    JNZ     @CB_Abort           ; They should cancel out\r
+\r
+    ; Setup for Copy processing\r
+\r
+    OUT_8   SC_INDEX, MAP_MASK      ; Set up for Plane Select\r
+    OUT_16  GC_Index, LATCHES_ON    ; Data from Latches = on\r
+\r
+    ; Compute Info About Images, Setup ES:SI & ES:DI\r
+\r
+    MOV     AX, [BP].CB_Y2      ; Height of Bitmap in lines\r
+    SUB     AX, [BP].CB_Y1      ; is Y2 - Y1 + 1\r
+    INC     AX                  ; (add 1 since were not 0 based)\r
+    MOV     [BP].CB_Height, AX  ; Save on Stack for later use\r
+\r
+    MOV     AX, [BP].CB_X2      ; Get # of "Bands" of 4 Pixels\r
+    MOV     DX, [BP].CB_X1      ; the Bitmap Occupies as X2-X1\r
+    SHR     AX, 1               ; Get X2 Band (X2 / 4)\r
+    SHR     DX, 1               ; Get X1 Band (X1 / 4)\r
+    SHR     AX, 1               ; Get X2 Band (X2 / 4)\r
+    SHR     DX, 1               ; Get X1 Band (X1 / 4)\r
+    SUB     AX, DX              ; AX = # of Bands - 1\r
+    INC     AX                  ; AX = # of Bands\r
+    MOV     [BP].CB_Width, AX   ; Save on Stack for later use\r
+\r
+    SHL     BX, 1               ; Scale Source Page to Word\r
+    MOV     SI, PAGE_ADDR[BX]   ; SI = Offset of Source Page\r
+    MOV     AX, [BP].CB_Y1      ; Get Source Y1 Line\r
+    MUL     SCREEN_WIDTH        ; AX = Offset to Line Y1\r
+    ADD     SI, AX              ; SI = Offset to Line Y1\r
+    MOV     AX, [BP].CB_X1      ; Get Source X1\r
+    SHR     AX, 1               ; X1 / 4 = Byte offset\r
+    SHR     AX, 1               ; X1 / 4 = Byte offset\r
+    ADD     SI, AX              ; SI = Byte Offset to (X1,Y1)\r
+\r
+    MOV     BX, CX              ; Dest Page Index to BX\r
+    SHL     BX, 1               ; Scale Source Page to Word\r
+    MOV     DI, PAGE_ADDR[BX]   ; DI = Offset of Dest Page\r
+    MOV     AX, [BP].CB_DestY1  ; Get Dest Y1 Line\r
+    MUL     SCREEN_WIDTH        ; AX = Offset to Line Y1\r
+    ADD     DI, AX              ; DI = Offset to Line Y1\r
+    MOV     AX, [BP].CB_DestX1  ; Get Dest X1\r
+    SHR     AX, 1              ; X1 / 4 = Byte offset\r
+    SHR     AX, 1               ; X1 / 4 = Byte offset\r
+    ADD     DI, AX              ; DI = Byte Offset to (D-X1,D-Y1)\r
+\r
+    MOV     CX, [BP].CB_Width   ; CX = Width of Image (Bands)\r
+    DEC     CX                  ; CX = 1?\r
+    JE      @CB_Only_One_Band   ; 0 Means Image Width of 1 Band\r
+\r
+    MOV     BX, [BP].CB_X1      ; Get Source X1\r
+    AND     BX, PLANE_BITS      ; Aligned? (bits 0-1 = 00?)\r
+    JZ      @CB_Check_Right     ; if so, check right alignment\r
+    JNZ     @CB_Left_Band       ; not aligned? well..\r
+\r
+@CB_Abort:\r
+    mov ax,0                  ; Return False (Failure)\r
+    JMP     @CB_Exit            ; and Finish Up\r
+\r
+    ; Copy when Left & Right Clip Masks overlap...\r
+\r
+@CB_Only_One_Band:\r
+    MOV     BX, [BP].CB_X1          ; Get Left Clip Mask\r
+    AND     BX, PLANE_BITS          ; Mask out Row #\r
+    MOV     AL, Left_Clip_Mask[BX]  ; Get Left Edge Mask\r
+    MOV     BX, [BP].CB_X2          ; Get Right Clip Mask\r
+    AND     BX, PLANE_BITS          ; Mask out Row #\r
+    AND     AL, Right_Clip_Mask[BX] ; Get Right Edge Mask byte\r
+\r
+    OUT_8   SC_Data, AL         ; Clip For Left & Right Masks\r
+\r
+    MOV     CX, [BP].CB_Height  ; CX = # of Lines to Copy\r
+    MOV     DX, SCREEN_WIDTH    ; DX = Width of Screen\r
+    mov bx,0                  ; BX = Offset into Image\r
+\r
+@CB_One_Loop:\r
+    MOV     AL, ES:[SI+BX]      ; Load Latches\r
+    MOV     ES:[DI+BX], AL      ; Unload Latches\r
+    ADD     BX, DX              ; Advance Offset to Next Line\r
+    LOOPjz  CX, @CB_One_Done    ; Exit Loop if Finished\r
+\r
+    MOV     AL, ES:[SI+BX]      ; Load Latches\r
+    MOV     ES:[DI+BX], AL      ; Unload Latches\r
+    ADD     BX, DX              ; Advance Offset to Next Line\r
+    LOOPx   CX, @CB_One_Loop    ; Loop until Finished\r
+\r
+@CB_One_Done:\r
+    JMP     @CB_Finish          ; Outa Here!\r
+\r
+    ; Copy Left Edge of Bitmap\r
+\r
+@CB_Left_Band:\r
+\r
+    OUT_8   SC_Data, Left_Clip_Mask[BX] ; Set Left Edge Plane Mask\r
+\r
+    MOV     CX, [BP].CB_Height  ; CX = # of Lines to Copy\r
+    MOV     DX, SCREEN_WIDTH    ; DX = Width of Screen\r
+    mov bx,0                  ; BX = Offset into Image\r
+\r
+@CB_Left_Loop:\r
+    MOV     AL, ES:[SI+BX]      ; Load Latches\r
+    MOV     ES:[DI+BX], AL      ; Unload Latches\r
+    ADD     BX, DX              ; Advance Offset to Next Line\r
+    LOOPjz  CX, @CB_Left_Done   ; Exit Loop if Finished\r
+\r
+    MOV     AL, ES:[SI+BX]      ; Load Latches\r
+    MOV     ES:[DI+BX], AL      ; Unload Latches\r
+    ADD     BX, DX              ; Advance Offset to Next Line\r
+    LOOPx   CX, @CB_Left_Loop   ; Loop until Finished\r
+\r
+@CB_Left_Done:\r
+    INC     DI                  ; Move Dest Over 1 band\r
+    INC     SI                  ; Move Source Over 1 band\r
+    DEC     [BP].CB_Width       ; Band Width--\r
+\r
+    ; Determine if Right Edge of Bitmap needs special copy\r
+\r
+@CB_Check_Right:\r
+    MOV     BX, [BP].CB_X2      ; Get Source X2\r
+    AND     BX, PLANE_BITS      ; Aligned? (bits 0-1 = 11?)\r
+    CMP     BL, 03h             ; Plane = 3?\r
+    JE      @CB_Copy_Middle     ; Copy the Middle then!\r
+\r
+    ; Copy Right Edge of Bitmap\r
+\r
+@CB_Right_Band:\r
+\r
+    OUT_8   SC_Data, Right_Clip_Mask[BX]    ; Set Right Edge Plane Mask\r
+\r
+    DEC     [BP].CB_Width       ; Band Width--\r
+    MOV     CX, [BP].CB_Height  ; CX = # of Lines to Copy\r
+    MOV     DX, SCREEN_WIDTH    ; DX = Width of Screen\r
+    MOV     BX, [BP].CB_Width   ; BX = Offset to Right Edge\r
+\r
+@CB_Right_Loop:\r
+    MOV     AL, ES:[SI+BX]      ; Load Latches\r
+    MOV     ES:[DI+BX], AL      ; Unload Latches\r
+    ADD     BX, DX              ; Advance Offset to Next Line\r
+    LOOPjz  CX, @CB_Right_Done  ; Exit Loop if Finished\r
+\r
+    MOV     AL, ES:[SI+BX]      ; Load Latches\r
+    MOV     ES:[DI+BX], AL      ; Unload Latches\r
+    ADD     BX, DX              ; Advance Offset to Next Line\r
+    LOOPx   CX, @CB_Right_Loop  ; Loop until Finished\r
+\r
+@CB_Right_Done:\r
+\r
+    ; Copy the Main Block of the Bitmap\r
+\r
+@CB_Copy_Middle:\r
+\r
+    MOV     CX, [BP].CB_Width   ; Get Width Remaining\r
+    JCXZ    @CB_Finish          ; Exit if Done\r
+\r
+    OUT_8   SC_Data, ALL_PLANES ; Copy all Planes\r
+\r
+    MOV     DX, SCREEN_WIDTH    ; Get Width of Screen minus\r
+    SUB     DX, CX              ; Image width (for Adjustment)\r
+    MOV     AX, [BP].CB_Height  ; AX = # of Lines to Copy\r
+    MOV     BX, CX              ; BX = Quick REP reload count\r
+    MOV     CX, ES              ; Move VGA Segment\r
+    MOV     DS, CX              ; Into DS\r
+\r
+    ; Actual Copy Loop.  REP MOVSB does the work\r
+\r
+@CB_Middle_Copy:\r
+    MOV     CX, BX              ; Recharge Rep Count\r
+    REP     MOVSB               ; Move Bands\r
+    LOOPjz  AX, @CB_Finish      ; Exit Loop if Finished\r
+\r
+    ADD     SI, DX              ; Adjust DS:SI to Next Line\r
+    ADD     DI, DX              ; Adjust ES:DI to Next Line\r
+\r
+    MOV     CX, BX              ; Recharge Rep Count\r
+    REP     MOVSB               ; Move Bands\r
+\r
+    ADD     SI, DX              ; Adjust DS:SI to Next Line\r
+    ADD     DI, DX              ; Adjust ES:DI to Next Line\r
+    LOOPx   AX, @CB_Middle_Copy ; Copy Lines until Done\r
+\r
+@CB_Finish:\r
+    OUT_16  GC_Index, LATCHES_OFF   ; Data from Latches = on\r
+\r
+@CB_Exit:\r
+    ADD     SP, 04              ; Deallocate stack workspace\r
+    ;POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    RET     16                  ; Exit and Clean up Stack\r
+\r
+COPY_BITMAP ENDP\r
+\r
+    END                         ; End of Code Segment\r
diff --git a/src/lib/modex/demos/c/modex.bi b/src/lib/modex/demos/c/modex.bi
new file mode 100755 (executable)
index 0000000..6b1d7af
--- /dev/null
@@ -0,0 +1,63 @@
\r
+    ' ===== SCREEN RESOLUTIONS =====\r
\r
+CONST Mode320x200 = 0, Mode320x400 = 1\r
+CONST Mode360x200 = 2, Mode360x400 = 3\r
+CONST Mode320x240 = 4, Mode320x480 = 5\r
+CONST Mode360x240 = 6, Mode360x480 = 7\r
\r
+    ' ===== MODE X SETUP ROUTINES =====\r
\r
+DECLARE FUNCTION SET.VGA.MODEX% ALIAS "SET_VGA_MODEX" (BYVAL ModeType%, BYVAL MaxXpos%, BYVAL MaxYpos%, BYVAL Pages%)\r
+DECLARE FUNCTION SET.MODEX% ALIAS "SET_MODEX" (BYVAL Mode%)\r
\r
+    ' ===== BASIC GRAPHICS PRIMITIVES =====\r
\r
+DECLARE SUB CLEAR.VGA.SCREEN ALIAS "CLEAR_VGA_SCREEN" (BYVAL ColorNum%)\r
+DECLARE SUB SET.POINT ALIAS "SET_POINT" (BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorNum%)\r
+DECLARE FUNCTION READ.POINT% ALIAS "READ_POINT" (BYVAL Xpos%, BYVAL Ypos%)\r
+DECLARE SUB FILL.BLOCK ALIAS "FILL_BLOCK" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
+DECLARE SUB DRAW.LINE ALIAS "DRAW_LINE" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
\r
+    ' ===== DAC COLOR REGISTER ROUTINES =====\r
\r
+DECLARE SUB SET.DAC.REGISTER ALIAS "SET_DAC_REGISTER" (BYVAL RegNo%, BYVAL Red%, BYVAL Green%, BYVAL Blue%)\r
+DECLARE SUB GET.DAC.REGISTER ALIAS "GET_DAC_REGISTER" (BYVAL RegNo%, Red%, Green%, Blue%)\r
+DECLARE SUB LOAD.DAC.REGISTERS ALIAS "LOAD_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%, BYVAL VSync%)\r
+DECLARE SUB READ.DAC.REGISTERS ALIAS "READ_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%)\r
\r
\r
+    ' ===== PAGE FLIPPING AND SCROLLING ROUTINES =====\r
\r
+DECLARE SUB SET.ACTIVE.PAGE ALIAS "SET_ACTIVE_PAGE" (BYVAL PageNo%)\r
+DECLARE FUNCTION GET.ACTIVE.PAGE% ALIAS "GET_ACTIVE_PAGE"\r
+DECLARE SUB SET.DISPLAY.PAGE ALIAS "SET_DISPLAY_PAGE" (BYVAL PageNo%)\r
+DECLARE FUNCTION GET.DISPLAY.PAGE% ALIAS "GET_DISPLAY_PAGE"\r
+DECLARE SUB SET.WINDOW ALIAS "SET_WINDOW" (BYVAL DisplayPage%, BYVAL XOffset%, BYVAL YOffset%)\r
+DECLARE FUNCTION GET.X.OFFSET% ALIAS "GET_X_OFFSET" ()\r
+DECLARE FUNCTION GET.Y.OFFSET% ALIAS "GET_Y_OFFSET" ()\r
+DECLARE SUB SYNC.DISPLAY ALIAS "SYNC_DISPLAY"\r
\r
+    ' ===== TEXT DISPLAY ROUTINES =====\r
\r
+DECLARE SUB GPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
+DECLARE SUB TGPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
+DECLARE SUB PRINT.STR ALIAS "PRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
+DECLARE SUB TPRINT.STR ALIAS "TPRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
+DECLARE SUB SET.DISPLAY.FONT ALIAS "SET_DISPLAY_FONT" (SEG FontData AS ANY, BYVAL FontNumber%)\r
\r
+    ' ===== BITMAP (SPRITE) DISPLAY ROUTINES =====\r
\r
+DECLARE SUB DRAW.BITMAP ALIAS "DRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
+DECLARE SUB TDRAW.BITMAP ALIAS "TDRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
\r
+    ' ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====\r
\r
+DECLARE SUB COPY.PAGE ALIAS "COPY_PAGE" (BYVAL SourcePage%, BYVAL DestPage%)\r
+DECLARE SUB COPY.BITMAP ALIAS "COPY_BITMAP" (BYVAL SourcePage%, BYVAL X1%, BYVAL Y1%, BYVAL X2%, BYVAL Y2%, BYVAL DestPage%, BYVAL DestX1%, BYVAL DestY1%)\r
\r
\r
\r
\r
\r
\r
diff --git a/src/lib/modex/demos/c/modex.h b/src/lib/modex/demos/c/modex.h
new file mode 100755 (executable)
index 0000000..1381abb
--- /dev/null
@@ -0,0 +1,76 @@
+\r
+#ifndef __MODEX_H\r
+#define __MODEX_H\r
+\r
+    /* ===== SCREEN RESOLUTIONS ===== */\r
+\r
+#define Mode_320x200  0\r
+#define Mode_320x400  1\r
+#define Mode_360x200  2\r
+#define Mode_360x400  3\r
+#define Mode_320x240  4\r
+#define Mode_320x480  5\r
+#define Mode_360x240  6\r
+#define Mode_360x480  7\r
+\r
+    /* ===== MODE X SETUP ROUTINES ===== */\r
+\r
+int far pascal set_vga_modex (int Mode, int MaxXpos, int MaxYpos, int Pages);\r
+int far pascal set_modex (int Mode);\r
+\r
+    /* ===== BASIC GRAPHICS PRIMITIVES ===== */\r
+\r
+void far pascal clear_vga_screen (int Color);\r
+void far pascal set_point (int Xpos, int Ypos, int Color);\r
+int  far pascal read_point (int Xpos, int Ypos);\r
+void far pascal fill_block (int Xpos1, int Ypos1, int Xpos2, int Ypos2,\r
+                            int Color);\r
+void far pascal draw_line (int Xpos1, int Ypos1, int Xpos2, int Ypos2,\r
+                           int Color);\r
+\r
+    /* ===== DAC COLOR REGISTER ROUTINES ===== */\r
+\r
+void far pascal set_dac_register (int RegNo, int Red, int Green, int Blue);\r
+void far pascal get_dac_register (int RegNo, int* Red, int* Green, int* Blue);\r
+void far pascal load_dac_registers (char far *PalData, int StartReg,\r
+                                    int EndReg, int VSync);\r
+void far pascal readd_dac_registers (char far *PalData, int StartReg,\r
+                                    int EndReg);\r
+\r
+    /* ===== PAGE FLIPPING AND SCROLLING ROUTINES ===== */\r
+\r
+void far pascal set_active_page (int PageNo);\r
+int  far pascal get_active_page (void);\r
+void far pascal set_display_page (int PageNo);\r
+int  far pascal get_display_page (void);\r
+void far pascal set_window (int DisplayPage, int XOffset, int YOffset);\r
+int  far pascal get_x_offset (void);\r
+int  far pascal get_y_offset (void);\r
+void far pascal sync_display (void);\r
+\r
+    /* ===== TEXT DISPLAY ROUTINES ===== */\r
+\r
+void far pascal gprintc (int CharNum, int Xpos, int Ypos, int ColorF,\r
+                         int ColorB);\r
+void far pascal tgprintc (int CharNum, int Xpos, int Ypos, int ColorF);\r
+void far pascal print_str (char far *Text, int MaxLen, int Xpos, int Ypos,\r
+                           int ColorF, int ColorB);\r
+void far pascal tprint_str (char far *Text, int MaxLen, int Xpos, int Ypos,\r
+                            int ColorF);\r
+void far pascal set_display_font (char far *FontData, int FontNumber);\r
+\r
+    /* ===== BITMAP (SPRITE) DISPLAY ROUTINES ===== */\r
+\r
+void far pascal draw_bitmap (char far *Image, int Xpos, int Ypos,\r
+                             int Width, int Height);\r
+void far pascal tdraw_bitmap (char far *Image, int Xpos, int Ypos,\r
+                              int Width, int Height);\r
+\r
+    /* ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES ===== */\r
+\r
+void far pascal copy_page (int SourcePage, int DestPage);\r
+void far pascal copy_bitmap (int SourcePage, int X1, int Y1, int X2, int Y2,\r
+                             int DestPage, int DestX1, int DestY1);\r
+\r
+\r
+#endif\r
diff --git a/src/lib/modex/demos/c/utls-asm.bat b/src/lib/modex/demos/c/utls-asm.bat
new file mode 100755 (executable)
index 0000000..d996978
--- /dev/null
@@ -0,0 +1 @@
+MASM c_utils, c_utils, c_utils, nul;
\ No newline at end of file
diff --git a/src/lib/modex/demos/c/w.sh b/src/lib/modex/demos/c/w.sh
new file mode 100755 (executable)
index 0000000..59f6361
--- /dev/null
@@ -0,0 +1,3 @@
+#! /bin/bash
+wmake clean;wmake
+cp x-demo.exe ../../../../../
diff --git a/src/lib/modex/demos/c/x-demo.c b/src/lib/modex/demos/c/x-demo.c
new file mode 100755 (executable)
index 0000000..dfe9a3e
--- /dev/null
@@ -0,0 +1,786 @@
+/* X-DEMO.C - a Mode "X" Demo      */\r
+/* By Matt Pritchard, 14 Apr, 1993 */\r
+\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+\r
+#include "modex.h"\r
+#include "c_utils.h"\r
+\r
+#define MAX_SHAPES  32\r
+#define MAX_SPRITES 64\r
+\r
+       /* routines in this file */\r
+\r
+void demo_res (int, int, int);\r
+int  get_key (void);\r
+void error_out (char*);\r
+void load_shapes (void);\r
+int  int_sqrt (int, int);\r
+void page_demo (void);\r
+\r
+       /* Structures for Sprites */\r
+\r
+struct Shape\r
+{\r
+       unsigned char Image[512];\r
+       int           X_Width;\r
+       int                       Y_Width;\r
+}   Img [MAX_SHAPES];\r
+\r
+struct Sprite\r
+{\r
+       int     X_pos;\r
+       int     Y_pos;\r
+       int X_Dir;\r
+       int Y_Dir;\r
+       int     Shape;\r
+       int     Last_X [2];\r
+       int Last_Y [2];\r
+}   Obj [MAX_SPRITES];\r
+\r
+\r
+       /* MAIN */\r
+\r
+\r
+int main(int argc, char *argv[])\r
+{\r
+\r
+   /*  if (argc > 0)\r
+       {\r
+               while (argc > 0)\r
+               {\r
+                       dos_print ("Unknown Argument: ");\r
+                       dos_print (makefp argv[argc]);\r
+                       argc--;\r
+               }\r
+               return (0);\r
+\r
+       }\r
+        */\r
+\r
+       init_random ();\r
+\r
+       load_shapes ();\r
+\r
+       demo_res ( Mode_320x200, 320, 200 );\r
+       demo_res ( Mode_320x400, 320, 400 );\r
+\r
+       demo_res ( Mode_360x200, 360, 200 );\r
+       demo_res ( Mode_360x400, 360, 400 );\r
+\r
+       demo_res ( Mode_320x240, 320, 240 );\r
+       demo_res ( Mode_320x480, 320, 480 );\r
+\r
+       demo_res ( Mode_360x240, 360, 240 );\r
+       demo_res ( Mode_360x480, 360, 480 );\r
+\r
+       page_demo ();\r
+\r
+       set_video_mode (3);\r
+       dos_print ("This Mode X Demo is Finished");\r
+       return (0);\r
+\r
+}\r
+\r
+\r
+       /* Demonstrate a given resolution */\r
+\r
+\r
+void demo_res (int Screen_Mode, int X_max, int Y_max)\r
+{\r
+\r
+char   *Error1 = "Failure while calling SET_MODEX";\r
+char   *Error2 = "Failure during READ_PIXEL test";\r
+\r
+char   *Abort_Msg = "Demo aborted by User";\r
+\r
+char   *Demo_Msg = " This is a MODE X demo ";\r
+char   *Scrn_Msg = "Screen Resolution is     by    ";\r
+char   *Cont_Msg = "Press <ANY KEY> to Continue";\r
+\r
+char    *Line_Msg = "LINE TEST";\r
+char   *Fill_Msg = "FILL TEST";\r
+char   *Pixel_Msg = "PIXEL TEST";\r
+\r
+char   Text[10];\r
+\r
+int            x1, y1, x2, y2 = 0;\r
+int            x, y, z = 0;\r
+int            X_Center, gap = 0;\r
+\r
+\r
+       if (set_modex (Screen_Mode) == 0)\r
+       {\r
+               error_out (Error1);\r
+       }\r
+\r
+       X_Center = X_max / 2;\r
+\r
+       x1 = 10;\r
+       y1 = 10;\r
+       x2 = X_max - 1;\r
+       y2 = Y_max - 1;\r
+\r
+       for (z = 0; z <= 3; z++)\r
+       {\r
+               y = 31 - z -z;\r
+               draw_line (x1+z, y1+z, x2-z, y1+z, y);\r
+               draw_line (x1+z, y1+z, x1+z, y2-z, y);\r
+               draw_line (x1+z, y2-z, x2-z, y2-z, y);\r
+               draw_line (x2-z, y1+z, x2-z, y2-z, y);\r
+       }\r
+\r
+       for (x = 0; x < (X_max / 10); x++)\r
+       {\r
+               tgprintc (48 + ((x+1) % 10), x*10+1, 1, 9 + ((x/8) % 7) );\r
+               draw_line (x*10+9, 0, x*10+9, 3, c_bWHITE);\r
+       }\r
+\r
+       for (y = 0; y < (Y_max / 10); y++)\r
+       {\r
+               tgprintc (48 + ((y+1) % 10), 1, y*10+1, 9 + ((y/10) % 7) );\r
+               draw_line (0, y*10+9, 3, y*10+9, c_bWHITE);\r
+       }\r
+\r
+       for (x = 0; x <= 63; x++)\r
+       {\r
+               z = 15 + (x * 3 / 4);\r
+               set_dac_register (64+x, z, z, z);\r
+               set_dac_register (128+x, 0, z, z);\r
+\r
+               draw_line (103-x, 60, 40+x, 123, 64+x);\r
+               draw_line (40, 60+x, 103, 123-x, 128+x);\r
+\r
+       }\r
+\r
+       tprint_str (Line_Msg, 9, 37, 130, c_BLUE);\r
+\r
+       y = 60;\r
+       gap = 0;\r
+       for (x = 0; x <= 9; x++)\r
+       {\r
+               fill_block (120, y, 120+x, y+gap, 64+x);\r
+               fill_block (140 - (15-x), y, 150+x, y+gap, 230+x);\r
+               fill_block (170 - (15-x), y, 170, y+gap, 128+x);\r
+               y = y + gap + 2;\r
+               gap++;\r
+       }\r
+\r
+       tprint_str (Fill_Msg, 9, 110, 46, c_GREEN);\r
+\r
+       for (x = 190; x <= 250; x+=2)\r
+       {\r
+               for (y = 60; y <= 122; y+=2)\r
+               {\r
+                       z = (x+x+y+y) & 0xff;\r
+                       set_point (x, y, z);\r
+               }\r
+       }\r
+\r
+       tprint_str (Pixel_Msg, 10, 182, 130, c_RED);\r
+\r
+       for (x = 190; x <= 250; x+=2)\r
+       {\r
+               for (y = 60; y <= 122; y+=2)\r
+               {\r
+                       z = (x+x+y+y) & 0xff;\r
+                       if (read_point(x, y) != z)\r
+                       {\r
+                               error_out (Error2);\r
+                       }\r
+               }\r
+       }\r
+\r
+       print_str (Demo_Msg, 23, X_Center - 92, 20, c_bRED, c_BLUE);\r
+\r
+       x = X_Center - 124;\r
+       print_str (Scrn_Msg, 28, x, 30, c_bGREEN, c_BLACK);\r
+\r
+       sprintf (Text, "%3d", X_max);\r
+       print_str (Text, 3, x+168, 30, c_bPURPLE, c_BLACK);\r
+\r
+       sprintf (Text, "%3d", Y_max);\r
+       print_str (Text, 3, x + 224, 30, c_bWHITE, c_BLACK);\r
+\r
+       for (x = 0; x <= 15; x++)\r
+       {\r
+               set_dac_register (230+x, 63-x*4, 0, 15+x*3);\r
+               draw_line (30+x, Y_max-6-x, X_max-20-x, Y_max-6-x, 230+x);\r
+       }\r
+\r
+       tprint_str (Cont_Msg, 27, X_Center - 103, Y_max-18, c_YELLOW);\r
+\r
+       if (get_key () == Ky_ESC)\r
+       {\r
+               error_out (Abort_Msg);\r
+       }\r
+\r
+       return ;\r
+\r
+}\r
+\r
+\r
+       /* Wait for a Keystroke */\r
+\r
+\r
+int get_key(void)\r
+{\r
+\r
+int    c = 0;\r
+\r
+       while (c == 0)\r
+       {\r
+               c = scan_keyboard ();\r
+       }\r
+\r
+       return (c);\r
+\r
+}\r
+\r
+\r
+       /* Error Handling Routine */\r
+\r
+\r
+void error_out (char * text)\r
+{\r
+\r
+       set_video_mode (3);\r
+       dos_print (text);\r
+       exit (EXIT_SUCCESS);\r
+\r
+}\r
+\r
+\r
+       /* Routine to generate random sprites */\r
+\r
+\r
+void load_shapes ()\r
+{\r
+\r
+unsigned char  Grid[33][33];\r
+\r
+char   *Error1 = "Bad Shape Selected Error";\r
+\r
+int            Shape;\r
+int            x, y, z;\r
+int            Style, Color;\r
+int            X_Width, Y_Width, Center, S_Width;\r
+int            Hollow_X, Hollow_Y;\r
+\r
+       for (Shape = 0; Shape < MAX_SHAPES; Shape++)\r
+       {\r
+               for (y = 0; y <= 32; y++)\r
+               {\r
+                       for (x = 0; x <= 32; x++)\r
+                       {\r
+                               Grid[x][y] = c_BLACK;\r
+                       }\r
+               }\r
+\r
+               Style = random_int (6);\r
+               Color = 1 + random_int (15);\r
+\r
+               switch (Style)\r
+\r
+               {\r
+                               /* SOLID BOXES */\r
+\r
+                       case 0:\r
+\r
+                       {\r
+                               do\r
+                               {\r
+                                       X_Width = 3 + random_int(30);\r
+                                       Y_Width = 3 + random_int(30);\r
+\r
+                               } while ( (X_Width * Y_Width) >= 512);\r
+\r
+                               for (x = 1; x <= X_Width; x++)\r
+                               {\r
+                                       for (y = 1; y <= Y_Width; y++)\r
+                                       {\r
+                                          Grid[x][y] = Color;\r
+                                       }\r
+                               }\r
+\r
+                               break;\r
+\r
+                       }\r
+                               /* HOLLOW BOXES */\r
+\r
+                       case 1:\r
+\r
+                       {\r
+                               do {\r
+                                       X_Width = 6 + random_int(27);\r
+                                       Y_Width = 6 + random_int(27);\r
+                               } while ( (X_Width * Y_Width) >= 512);\r
+\r
+                               for (y = 1; y <= Y_Width; y++)\r
+                               {\r
+                                       for (x = 1; x <= X_Width; x++)\r
+                                       {\r
+                                               Grid[x][y] = Color;\r
+                                       }\r
+                               }\r
+\r
+                               Hollow_X = 1 + random_int ((X_Width / 2) -1);\r
+                               Hollow_Y = 1 + random_int ((Y_Width / 2) -1);\r
+\r
+                               for (y = Hollow_Y+1; y <= Y_Width-Hollow_Y; y++)\r
+                               {\r
+                                       for (x = Hollow_X+1; x <= X_Width-Hollow_X; x++)\r
+                                       {\r
+                                               Grid[x][y] = c_BLACK;\r
+                                       }\r
+                               }\r
+\r
+                               break;\r
+\r
+                       }\r
+\r
+                               /* SOLID DIAMOND */\r
+\r
+                       case 2:\r
+\r
+                       {\r
+\r
+                               X_Width = 3 + 2 * random_int(10);\r
+                               Y_Width = X_Width;\r
+                               Center = X_Width / 2;\r
+\r
+                               for (y = 0; y <= Center; y++)\r
+                               {\r
+                                       for (x = 0; x <= y; x++)\r
+                                       {\r
+                                               Grid [Center-x+1][y+1] = Color;\r
+                                               Grid [Center+x+1][y+1] = Color;\r
+                                               Grid [Center-x+1][Y_Width-y] = Color;\r
+                                               Grid [Center+x+1][Y_Width-y] = Color;\r
+                                       }\r
+                               }\r
+\r
+                               break;\r
+\r
+                       }\r
+\r
+                               /* HOLLOW DIAMOND */\r
+\r
+                       case 3:\r
+\r
+                       {\r
+\r
+                               X_Width = 3 + 2 * random_int(10);\r
+                               Y_Width = X_Width;\r
+                               Center = X_Width / 2;\r
+                               S_Width = random_int (Center);\r
+\r
+                               for (y = 0; y <= Center; y++)\r
+                               {\r
+                                       for (x = 0; x <= y; x++)\r
+                                       {\r
+                                               if ( x+(Center-y) >= S_Width )\r
+                                               {\r
+                                                       Grid [Center-x+1][y+1] = Color;\r
+                                                       Grid [Center+x+1][y+1] = Color;\r
+                                                       Grid [Center-x+1][Y_Width-y] = Color;\r
+                                                       Grid [Center+x+1][Y_Width-y] = Color;\r
+                                               }\r
+                                       }\r
+                               }\r
+\r
+                               break;\r
+\r
+                       }\r
+\r
+                               /* BALL */\r
+\r
+                       case 4:\r
+\r
+                       {\r
+\r
+                               X_Width = 7 + 2 * random_int (8);\r
+                               Y_Width = X_Width;\r
+                               Center  = 1 + X_Width / 2;\r
+\r
+                               for (y = 1; y <= Y_Width; y++)\r
+                               {\r
+                                       for (x = 1; x <= X_Width; x++)\r
+                                       {\r
+                                               z = int_sqrt(Center-x, Center-y);\r
+                                               if (z < Center)\r
+                                               {\r
+                                                       Grid[x][y] = 150 + Color * 2 + z * 3;\r
+                                               }\r
+                                       }\r
+                               }\r
+\r
+                               break;\r
+                       }\r
+\r
+                               /* HOLLOW BALLS */\r
+\r
+                       case 5:\r
+\r
+                       {\r
+                               X_Width = 7 + 2 * random_int (8);\r
+                               Y_Width = X_Width;\r
+                               Center  = 1 + X_Width / 2;\r
+                               S_Width = random_int (X_Width);\r
+\r
+                               for (y = 1; y <= Y_Width; y++)\r
+                               {\r
+                                       for (x = 1; x <= X_Width; x++)\r
+                                       {\r
+                                               z = int_sqrt(Center-x, Center-y);\r
+                                               if ( (z < Center) && (z >= S_Width) )\r
+                                               {\r
+                                                       Grid[x][y] = 150 + Color * 2 + z * 3;\r
+                                               }\r
+                                       }\r
+                               }\r
+\r
+\r
+                               break;\r
+                       }\r
+\r
+                       default:\r
+\r
+                       {\r
+                               error_out (Error1);\r
+                               break;\r
+\r
+                       }\r
+\r
+               }\r
+\r
+               z = 0;\r
+               for (y = 1; y <= Y_Width; y++)\r
+               {\r
+                       for (x = 1; x <= X_Width; x++)\r
+                       {\r
+                               Img[Shape].Image[z] = Grid[x][y];\r
+                               z++;\r
+                       }\r
+               }\r
+\r
+               Img[Shape].X_Width = X_Width;\r
+               Img[Shape].Y_Width = Y_Width;\r
+\r
+       }\r
+\r
+       return;\r
+}\r
+\r
+\r
+       /* Quickie Psuedo Integer Square Root Routine */\r
+\r
+\r
+int int_sqrt ( int x, int y )\r
+{\r
+\r
+int    Sqr_Table[12] = {1, 4, 9, 6, 25, 36, 49, 64, 81, 100, 121, 144};\r
+\r
+int    r, d;\r
+\r
+       d = (x * x) + (y * y);\r
+       r = 0;\r
+\r
+       while ( d >= Sqr_Table[r] )\r
+       {\r
+               r++;\r
+       }\r
+\r
+       return (r);\r
+\r
+}\r
+\r
+\r
+       /* The Bit Sprite Demo */\r
+\r
+\r
+void page_demo ()\r
+{\r
+\r
+char   *Error1 = "Failure during SET_VGA_MODEX (0, 320, 200, 2) call";\r
+\r
+int            Last_Objects[2], Visible_Objects;\r
+\r
+int            Screen_X = 384;\r
+int            Screen_Y = 224;\r
+\r
+int            x, y, z;\r
+int            c, dc;\r
+int            x1, y1, x2, y2;\r
+\r
+int            Sprite_X, Sprite_Y;\r
+int            Current_Page;\r
+int            New_X, New_Y;\r
+\r
+int            View_X, View_Y, View_Max, View_Cnt, View_XD, View_YD;\r
+int            Set_Color, Prev_Color, S_Dir, P_Dir;\r
+\r
+int            Demo_Running = True;\r
+int            redo, code;\r
+\r
+int pee;\r
+pee = set_vga_modex(Mode_320x200, Screen_X, Screen_Y, 3);\r
+       if ( pee > 0)\r
+       {\r
+               set_video_mode (3);\r
+               dos_print (Error1);\r
+               fprintf(stdout, "return value is %d\n", pee);\r
+               //error_out (Error1);\r
+               exit (EXIT_SUCCESS);\r
+       }\r
+\r
+       set_active_page (0);\r
+       clear_vga_screen (c_BLACK);\r
+\r
+       print_str ("This is a Test of the Following Functions:", 99, 10, 9, c_bWHITE, c_BLACK);\r
+\r
+       draw_line (10, 18, 350, 18, c_YELLOW);\r
+       print_str ("SET_ACTIVE_PAGE", 99, 10, 20, c_bBLUE, c_BLACK);\r
+       print_str ("SET_DISPLAY_PAGE", 99, 10, 30, c_GREEN, c_BLACK);\r
+       print_str ("SET_DAC_REGISTER", 99, 10, 40, c_RED, c_BLACK);\r
+       print_str ("CLEAR_VGA_SCREEN", 99, 10, 50, c_CYAN, c_BLACK);\r
+\r
+       print_str ("TDRAW_BITMAP", 99, 10, 60, c_PURPLE, c_BLACK);\r
+       print_str ("COPY_PAGE", 99, 10, 70, c_GREEN, c_BLACK);\r
+       print_str ("COPY_BITMAP", 99, 10, 80, c_CYAN, c_BLACK);\r
+\r
+       print_str ("GPRINTC", 99, 10, 90, c_BLUE, c_BLACK);\r
+       print_str ("TGPRINTC", 99, 10, 100, c_GREEN, c_BLACK);\r
+       print_str ("SET_WINDOW", 99, 10, 110, c_RED, c_BLACK);\r
+\r
+       print_str ("VIRTUAL SCREEN SIZES", 20, 190, 20, c_bBLUE, c_BLACK);\r
+       print_str ("    SMOOTH SCROLLING", 20, 190, 30, c_GREEN, c_BLACK);\r
+       print_str ("    SPRITE ANIMATION", 20, 190, 40, c_CYAN, c_BLACK);\r
+       print_str ("       PAGE FLIPPING", 20, 190, 50, c_RED, c_BLACK);\r
+       print_str ("       COLOR CYCLING", 20, 190, 60, c_PURPLE, c_BLACK);\r
+\r
+       for (x = 0; x <=60; x++)\r
+       {\r
+               set_dac_register (50 + x, 3 + x, 0, 60 - x);\r
+               set_dac_register (150 + x, 3 + x, 0, 60 - x);\r
+       }\r
+\r
+       c = 0;\r
+       dc = 1;\r
+       for (x = 0; x <= (Screen_X / 2); x++)\r
+       {\r
+               draw_line (Screen_X / 2 - 1, Screen_Y / 4, x, Screen_Y - 1, c + 50);\r
+               draw_line (Screen_X / 2, Screen_Y / 4, Screen_X - x - 1, Screen_Y - 1, c + 50);\r
+               c+= dc;\r
+               if ((c == 0) || (c == 60) ) { dc = -dc;}\r
+       }\r
+\r
+       tprint_str ("Press <ANY KEY> to Continue", 99, 72, 190, c_bWHITE);\r
+       tprint_str ("< > = Faster   < > = Slower", 99, 72, 204, c_bGREEN);\r
+       tprint_str ("< > = Fewer Shapes  < > = More Shapes", 99, 32, 218, c_bCYAN);\r
+\r
+       tgprintc (43, 80, 204, c_YELLOW);\r
+       tgprintc (45, 200, 204, c_YELLOW);\r
+\r
+       tgprintc (25, 40, 218, c_YELLOW);\r
+       tgprintc (24, 200, 218, c_YELLOW);\r
+\r
+       copy_page (0, 1);\r
+       copy_page (0, 2);\r
+\r
+       for (x = 0; x < MAX_SPRITES; x++)\r
+       {\r
+               do {\r
+                       Obj[x].X_Dir = random_int(7) - 3;\r
+                       Obj[x].Y_Dir = random_int(7) - 3;\r
+               } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) );\r
+\r
+               Obj[x].Shape = x % MAX_SHAPES;\r
+\r
+               Sprite_X = Img[Obj[x].Shape].X_Width;\r
+               Sprite_Y = Img[Obj[x].Shape].Y_Width;\r
+\r
+               Obj[x].X_pos = 1 + random_int(Screen_X - Sprite_X - 2);\r
+               Obj[x].Y_pos = 1 + random_int(Screen_Y - Sprite_Y - 2);\r
+\r
+               Obj[x].Last_X[0] = Obj[x].X_pos;\r
+               Obj[x].Last_X[1] = Obj[x].X_pos;\r
+               Obj[x].Last_Y[0] = Obj[x].Y_pos;\r
+               Obj[x].Last_Y[1] = Obj[x].Y_pos;\r
+\r
+       }\r
+\r
+       Current_Page = 0;\r
+\r
+       View_X = 0;\r
+       View_Y = 0;\r
+       View_Max = 3;\r
+       View_Cnt = 0;\r
+       View_XD = 1;\r
+       View_YD = 1;\r
+\r
+       Set_Color = 3;\r
+       S_Dir = 1;\r
+       Prev_Color = 0;\r
+       P_Dir = 1;\r
+\r
+       Visible_Objects = MAX_SPRITES / 2;\r
+       Last_Objects[0] = 0;\r
+       Last_Objects[1] = 0;\r
+\r
+       while (Demo_Running)\r
+       {\r
+\r
+               set_active_page (Current_Page);\r
+\r
+                       /* Erase Old Images */\r
+\r
+               for (x = 0; x <= Last_Objects[Current_Page]; x++)\r
+               {\r
+                       z = 2;\r
+                       y = Obj[x].Shape;\r
+                       x1 = Obj[x].Last_X[Current_Page];\r
+                       y1 = Obj[x].Last_Y[Current_Page];\r
+                       x2 = x1 + Img[y].X_Width -1;\r
+                       y2 = y1 + Img[y].Y_Width -1;\r
+\r
+                       x1 = x1 & 0xfffc;\r
+                       x2 = x2 | 0x0003;\r
+\r
+                       copy_bitmap (z, x1, y1, x2, y2, Current_Page, x1, y1);\r
+               }\r
+\r
+                       /* Draw new images */\r
+\r
+               for (x = 0; x <= Visible_Objects; x++)\r
+               {\r
+                       Sprite_X = Img[Obj[x].Shape].X_Width;\r
+                       Sprite_Y = Img[Obj[x].Shape].Y_Width;\r
+\r
+                       /*  Move Sprite */\r
+\r
+                       do\r
+                       {\r
+                               redo = False;\r
+                               New_X = Obj[x].X_pos + Obj[x].X_Dir;\r
+\r
+                               if (( New_X < 0 ) || (New_X + Sprite_X > Screen_X) )\r
+                               {\r
+                                       Obj[x].X_Dir = -Obj[x].X_Dir;\r
+                                       if (random_int(20) == 1)\r
+                                       {\r
+                                               do\r
+                                               {\r
+                                                       Obj[x].X_Dir = random_int(7) - 3;\r
+                                                       Obj[x].Y_Dir = random_int(7) - 3;\r
+                                               } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) );\r
+                                               redo = True;\r
+                                       }\r
+                               }\r
+                       } while (redo);\r
+                       Obj[x].X_pos = Obj[x].X_pos + Obj[x].X_Dir;\r
+\r
+\r
+                       do\r
+                       {\r
+                               redo = False;\r
+                               New_Y = Obj[x].Y_pos + Obj[x].Y_Dir;\r
+\r
+                               if ( (New_Y < 0) || (New_Y + Sprite_Y > Screen_Y) )\r
+                               {\r
+                                       Obj[x].Y_Dir = -Obj[x].Y_Dir;\r
+                                       if (random_int(20) == 1)\r
+                                       {\r
+                                               do\r
+                                               {\r
+                                                       Obj[x].X_Dir = random_int(7) - 3;\r
+                                                       Obj[x].Y_Dir = random_int(7) - 3;\r
+                                               } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) );\r
+                                               redo = True;\r
+                                       }\r
+                               }\r
+                       } while (redo);\r
+\r
+                       Obj[x].Y_pos = Obj[x].Y_pos + Obj[x].Y_Dir;\r
+\r
+                       /* Draw Sprite */\r
+\r
+                       tdraw_bitmap ((char far*) &Img[Obj[x].Shape], Obj[x].X_pos, Obj[x].Y_pos, Sprite_X, Sprite_Y);\r
+\r
+                       Obj[x].Last_X[Current_Page] = Obj[x].X_pos;\r
+                       Obj[x].Last_Y[Current_Page] = Obj[x].Y_pos;\r
+\r
+               }\r
+\r
+               Last_Objects[Current_Page] = Visible_Objects;\r
+\r
+\r
+               /* Pan Screen Back & Forth */\r
+\r
+               View_Cnt++;\r
+               if (View_Cnt >= View_Max)\r
+               {\r
+                       View_X+= View_XD;\r
+                       if ( (View_X == 0) || (View_X == 39) ) {View_XD = -View_XD;}\r
+                       if (View_XD < 0)\r
+                       {\r
+                               View_Y+= View_YD;\r
+                               if ( (View_Y == 0) || (View_Y == 39) ) {View_YD = -View_YD;}\r
+                       }\r
+\r
+                       set_window (Current_Page, View_X, View_Y);\r
+\r
+                       View_Cnt = 0;\r
+               }\r
+               else\r
+               {\r
+                       set_display_page (Current_Page);\r
+               }\r
+\r
+               /* Cycle Colors */\r
+\r
+               set_dac_register (50 + Prev_Color, 3 + Prev_Color, 0, 60 - Prev_Color);\r
+               set_dac_register (50 + Set_Color, Set_Color, 10, 63 - Set_Color);\r
+\r
+               set_dac_register (150 + Prev_Color, 3 + Prev_Color, 0, 60 - Prev_Color);\r
+               set_dac_register (150 + Set_Color, 63, 63, Set_Color);\r
+\r
+               Set_Color+= S_Dir;\r
+               if ( (Set_Color == 60) || (Set_Color == 0) ) {S_Dir = -S_Dir;}\r
+\r
+               Prev_Color+= P_Dir;\r
+               if ( (Prev_Color == 60) || (Prev_Color == 0) ) {P_Dir = -P_Dir;}\r
+\r
+               /* Check for Keystroke */\r
+\r
+               Current_Page = Current_Page ^ 0x01;\r
+\r
+               code = scan_keyboard ();\r
+\r
+               if (code == Ky_ESC) {Demo_Running = False;}\r
+\r
+               if (code == Ky_Plus)\r
+               {\r
+                       if (View_Max < 12) {View_Max++;}\r
+               }\r
+\r
+               if (code == Ky_Minus)\r
+               {\r
+                       if (View_Max > 1) {View_Max--;}\r
+                       if (View_Cnt >= View_Max) {View_Cnt = 0;}\r
+               }\r
+\r
+               if (code == Ky_Up)\r
+               {\r
+                       if (Visible_Objects < MAX_SPRITES-1) {Visible_Objects++;}\r
+               }\r
+\r
+               if (code == Ky_Down)\r
+               {\r
+                       if (Visible_Objects > 0) {Visible_Objects--;}\r
+               }\r
+\r
+       }\r
+\r
+}\r
diff --git a/src/lib/modex/demos/c/x-demo.dsk b/src/lib/modex/demos/c/x-demo.dsk
new file mode 100755 (executable)
index 0000000..5573e71
Binary files /dev/null and b/src/lib/modex/demos/c/x-demo.dsk differ
diff --git a/src/lib/modex/demos/c/x-demo.exe b/src/lib/modex/demos/c/x-demo.exe
new file mode 100755 (executable)
index 0000000..b4fee91
Binary files /dev/null and b/src/lib/modex/demos/c/x-demo.exe differ
diff --git a/src/lib/modex/demos/c/x-demo.prj b/src/lib/modex/demos/c/x-demo.prj
new file mode 100755 (executable)
index 0000000..b3f307e
Binary files /dev/null and b/src/lib/modex/demos/c/x-demo.prj differ
diff --git a/src/lib/modex/demos/c/x.exe b/src/lib/modex/demos/c/x.exe
new file mode 100755 (executable)
index 0000000..7742d14
Binary files /dev/null and b/src/lib/modex/demos/c/x.exe differ
diff --git a/src/lib/modex/demos/chardemo.exe b/src/lib/modex/demos/chardemo.exe
new file mode 100755 (executable)
index 0000000..4015bdf
Binary files /dev/null and b/src/lib/modex/demos/chardemo.exe differ
diff --git a/src/lib/modex/demos/pascal/test5.pas b/src/lib/modex/demos/pascal/test5.pas
new file mode 100755 (executable)
index 0000000..7cc56bb
--- /dev/null
@@ -0,0 +1,488 @@
+{                      ModeX Turbo Pascal Demo Program                       }\r
+{                  Converted to Turbo Pascal by Scott Wyatt                  }\r
+{          Original program written in QuickBasic by Matt Prichard           }\r
+{                       Released to the Public Domain                        }\r
+{                                                                            }\r
+{          Thanks to Matt Prichard for his *EXCELLENT* ModeX Library         }\r
+{                 Additional Comments by Matt Pritchard                                                         }\r
+\r
+Uses Crt;\r
+\r
+{$L modex2.obj}                { This file is the external ModeX Library .OBJ }\r
+{$F+}\r
+\r
+       { Mode Setting Routines }\r
+\r
+Function SET_VGA_MODEX (Mode,MaxXpos,MaxYpos,Pages : integer) : integer; external;\r
+Function SET_MODEX (Mode:integer) : Integer; external;\r
+\r
+       { Graphics Primitives }\r
+\r
+Procedure CLEAR_VGA_SCREEN (Color:integer); external;\r
+Procedure SET_POINT (Xpos,Ypos,Color : integer); external;\r
+Function READ_POINT (Xpos,Ypos:integer) : integer; external;\r
+Procedure FILL_BLOCK (Xpos1,Ypos1,Xpos2,Ypos2,Color:integer); external;\r
+Procedure DRAW_LINE (Xpos1,Ypos1,Xpos2,Ypos2,Color:integer); external;\r
+\r
+       { VGA DAC Routines }\r
+\r
+Procedure SET_DAC_REGISTER (RegNo,Red,Green,Blue:integer); external;\r
+Procedure GET_DAC_REGISTER (RegNo,Red,Green,Blue:integer); external;\r
+\r
+       { Page and Window Control Routines }\r
+\r
+Procedure SET_ACTIVE_PAGE (PageNo:integer); external;\r
+Function GET_ACTIVE_PAGE : integer; external;\r
+Procedure SET_DISPLAY_PAGE (PageNo:integer); external;\r
+Function GET_DISPLAY_PAGE : integer; external;\r
+Procedure SET_WINDOW (DisplayPage,XOffset,YOffset : integer); external;\r
+Function GET_X_OFFSET : integer; external;\r
+Function GET_Y_OFFSET : integer; external;\r
+Procedure SYNC_DISPLAY; external;\r
+\r
+       { Text Display Routines }\r
+\r
+Procedure GPRINTC (CharNum,Xpos,Ypos,ColorF,ColorB:integer); external;\r
+Procedure TGPRINTC ( CharNum,Xpos,Ypos,ColorF : integer); external;\r
+Procedure PRINT_STR (Var Text;MaxLen,Xpos,Ypos,ColorF,ColorB:integer); external;\r
+Procedure TPRINT_STR (Var Text;MaxLen,Xpos,Ypos,ColorF:integer); external;\r
+Procedure SET_DISPLAY_FONT (Var FontData;FontNumber:integer); external;\r
+\r
+       { Sprite and VGA memory -> Vga memory Copy Routines }\r
+\r
+Procedure DRAW_BITMAP (Var Image;Xpos,Ypos,Width,Height:integer); external;\r
+Procedure TDRAW_BITMAP (Var Image;Xpos,Ypos,Width,Height:integer); external;\r
+Procedure COPY_PAGE (SourcePage,DestPage:integer); external;\r
+Procedure COPY_BITMAP (SourcePage,X1,Y1,X2,Y2,DestPage,DestX1,DestY1:integer); external;\r
+\r
+{$F-}\r
+\r
+\r
+TYPE Sprite = Record\r
+       Xpos : INTEGER;\r
+       Ypos : INTEGER;\r
+       XDir : INTEGER;\r
+       YDir : INTEGER;\r
+       Shape : INTEGER;\r
+       LastX : INTEGER;\r
+       LastY : INTEGER;\r
+     END;\r
+\r
+\r
+CONST MaxShapes = 32;\r
+      Circle_16 : Array[1..16,1..16] of byte =\r
+      ((  0,  0,  0,  0,  0,  0, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0),\r
+       (  0,  0,  0,  0, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0),\r
+       (  0,  0,  0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0),\r
+       (  0,  0, 20, 20, 20, 20,  0,  0,  0,  0, 20, 20, 20, 20,  0,  0),\r
+       (  0, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0, 20, 20, 20, 20,  0),\r
+       (  0, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0, 20, 20, 20,  0),\r
+       ( 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20, 20, 20),\r
+       ( 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20, 20, 20),\r
+       ( 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20, 20, 20),\r
+       ( 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20, 20, 20),\r
+       (  0, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0, 20, 20, 20,  0),\r
+       (  0, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0, 20, 20, 20, 20,  0),\r
+       (  0,  0, 20, 20, 20, 20,  0,  0,  0,  0, 20, 20, 20, 20,  0,  0),\r
+       (  0,  0,  0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0),\r
+       (  0,  0,  0,  0, 20, 20, 20, 20, 20, 20, 20, 20,  0,  0,  0,  0),\r
+       (  0,  0,  0,  0,  0,  0, 20, 20, 20, 20,  0,  0,  0,  0,  0,  0));\r
+      Square_16 : Array[1..16,1..16] of byte =\r
+      (( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21),\r
+       ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21),\r
+       ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21),\r
+       ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21),\r
+       ( 21, 21, 21, 21,  0,  0,  0,  0,  0,  0,  0,  0, 21, 21, 21, 21),\r
+       ( 21, 21, 21, 21,  0,  0,  0,  0,  0,  0,  0,  0, 21, 21, 21, 21),\r
+       ( 21, 21, 21, 21,  0,  0,  0,  0,  0,  0,  0,  0, 21, 21, 21, 21),\r
+       ( 21, 21, 21, 21,  0,  0,  0,  0,  0,  0,  0,  0, 21, 21, 21, 21),\r
+       ( 21, 21, 21, 21,  0,  0,  0,  0,  0,  0,  0,  0, 21, 21, 21, 21),\r
+       ( 21, 21, 21, 21,  0,  0,  0,  0,  0,  0,  0,  0, 21, 21, 21, 21),\r
+       ( 21, 21, 21, 21,  0,  0,  0,  0,  0,  0,  0,  0, 21, 21, 21, 21),\r
+       ( 21, 21, 21, 21,  0,  0,  0,  0,  0,  0,  0,  0, 21, 21, 21, 21),\r
+       ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21),\r
+       ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21),\r
+       ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21),\r
+       ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21));\r
+       Diamond : Array[1..8,1..8] of byte =\r
+      ((  0,  0,  0, 22, 22,  0,  0,  0),\r
+       (  0,  0, 22, 22, 22, 22,  0,  0),\r
+       (  0, 22, 22,  0,  0, 22, 22,  0),\r
+       ( 22, 22,  0,  0,  0,  0, 22, 22),\r
+       ( 22, 22,  0,  0,  0,  0, 22, 22),\r
+       (  0, 22, 22,  0,  0, 22, 22,  0),\r
+       (  0,  0, 22, 22, 22, 22,  0,  0),\r
+       (  0,  0,  0, 22, 22,  0,  0,  0));\r
+       Rectangle : Array[1..8,1..3] of byte =\r
+      (( 23, 23, 23),\r
+       ( 23, 23, 23),\r
+       ( 23, 23, 23),\r
+       ( 23, 23, 23),\r
+       ( 23, 23, 23),\r
+       ( 23, 23, 23),\r
+       ( 23, 23, 23),\r
+       ( 23, 23, 23));\r
+\r
+          { Global Variables ? }\r
+\r
+Var\r
+  XCenter,X1,Y1,X2,Y2,Z,Colr,XChars,YChars,X,Y,N,Gap : Integer;\r
+  s : string;\r
+  s1 : Array[1..35] of Char;\r
+  ch : Char;\r
+  obj : Array[1..64] of Sprite;\r
+  ScreenX,ScreenY : Integer;\r
+  c, dc, SpriteX, SpriteY, CurrentPage, LastPage : Integer;\r
+  SetColor, SDir, PrevColor, PDir : Byte;\r
+  XView, YView : Integer;\r
+  XView_Change, YView_Change : Integer;\r
+  Right : Boolean;\r
+  Number_Of_Shapes : Byte;\r
+\r
+\r
+       { Error Handler - Returns to Text Mode & Displays Error }\r
+\r
+Procedure ERROR_OUT(s : string);\r
+  Begin\r
+    asm\r
+      mov ah,0\r
+      mov al,3\r
+      int 10h\r
+    end;\r
+  WriteLn(s);\r
+  Halt(0);\r
+END;\r
+\r
+       { Routine to Print a PASCAL string using Print_Str }\r
+\r
+Procedure Print_Text(s : string; X,Y,BColor,FColor : integer);\r
+Var\r
+  s1 : Array[1..135] of Char;\r
+  i : byte;\r
+Begin\r
+  For i := 1 to Length(s) DO\r
+    s1[i] := s[i];\r
+  Print_Str(s1,Length(s),X,Y,BColor,FColor);\r
+End;\r
+\r
+       { Routine to Transparently Print a PASCAL string using TPrint_Str }\r
+\r
+Procedure TPrint_Text(s : string; X,Y,Color : integer);\r
+Var\r
+  s1 : Array[1..135] of Char;\r
+  i : byte;\r
+Begin\r
+  For i := 1 to Length(s) DO\r
+    s1[i] := s[i];\r
+  TPrint_Str(s1,Length(s),X,Y,Color);\r
+End;\r
+\r
+       { Routines to show test patterns for a given mode }\r
+\r
+Procedure Demo_Res(Mode, Xmax, Ymax : integer);\r
+Begin\r
+\r
+  Str(mode,s);\r
+  If Set_ModeX(Mode) = 0 Then\r
+    Error_Out('Unable to SET_MODEX '+s);\r
+  Clear_VGA_Screen(0);\r
+\r
+  XCenter := Xmax div 2;\r
+  X1 := 10;\r
+  Y1 := 10;\r
+  X2 := Xmax - 1;\r
+  Y2 := Ymax - 1;\r
+\r
+  FOR Z := 0 TO 3 DO\r
+    Begin\r
+      Colr := 31 - Z * 2;\r
+      Draw_Line(X1 + Z, Y1 + Z, X2 - Z, Y1 + Z, Colr);\r
+      Draw_Line(X1 + Z, Y1 + Z, X1 + Z, Y2 - Z, Colr);\r
+      Draw_Line(X1 + Z, Y2 - Z, X2 - Z, Y2 - Z, Colr);\r
+      Draw_Line(X2 - Z, Y1 + Z, X2 - Z, Y2 - Z, Colr);\r
+    End;\r
+\r
+  XChars := Xmax div 10;\r
+  YChars := Ymax div 10;\r
+\r
+  FOR X := 0 TO XChars - 1 DO\r
+    Begin\r
+      TGPRINTC(48 + ((X + 1) MOD 10), X * 10 + 1, 1, 9 + ((X div 8) MOD 7));\r
+      DRAW_LINE(X * 10 + 9, 0, X * 10 + 9, 3, 15);\r
+    End;\r
+  FOR Y := 0 TO YChars - 1 DO\r
+    Begin\r
+      TGPRINTC(48 + ((Y + 1) MOD 10), 1, Y * 10 + 1, 9 + ((Y div 10) MOD 7));\r
+      DRAW_LINE(0, Y * 10 + 9, 3, Y * 10 + 9, 15);\r
+    End;\r
+\r
+   { Test Line Drawing }\r
+\r
+  FOR X := 0 TO 63 DO\r
+    Begin\r
+      N := 15 + ((X * 3) div 4);\r
+      SET_DAC_REGISTER(64 + X, N, N, N);\r
+      SET_DAC_REGISTER(128 + X, 0, N, N);\r
+      DRAW_LINE(103 - X, 60, 40 + X, 123, 64 + X);\r
+      DRAW_LINE(40, 60 + X, 103, 123 - X, 128 + X);\r
+    End;\r
+  s := 'Line Test';\r
+  PRINT_Text(s,37,130,1,0);\r
+\r
+  { Test Block Fills }\r
+\r
+  Y := 60;\r
+  Gap := 0;\r
+  FOR X := 0 TO 9 DO\r
+    Begin\r
+      FILL_BLOCK(120, Y, 120 + X, Y + Gap, 64 + X);\r
+      FILL_BLOCK(140 - (15 - X), Y, 150 + X, Y + Gap, 230 + X);\r
+      FILL_BLOCK(170 - (15 - X), Y, 170, Y + Gap, 128 + X);\r
+      Y := Y + Gap + 2;\r
+      Gap := Gap + 1;\r
+    End;\r
+  s := 'Fill Test';\r
+  Print_Text(s,110, 46, 2,0);\r
+\r
+  { Test Pixel Write and Read }\r
+\r
+  FOR X := 190 TO 250 DO\r
+    FOR Y := 60 TO 122 DO\r
+      SET_POINT( X, Y, X + Y + X + Y);\r
+\r
+  s := 'Pixel Test';\r
+  Print_Text(s,182, 130, 3,0);\r
+\r
+  FOR X := 190 TO 250 DO\r
+    FOR Y := 60 TO 122 DO\r
+      IF READ_POINT(X, Y) <> ((X + Y + X + Y) AND 255) THEN\r
+        WriteLn('READ_PIXEL Failure');\r
+\r
+       { Display rest of screen }\r
+\r
+  s := ' This is a MODE X demo ';\r
+  Print_Text(s,XCenter - (Length(s) * 4), 20, 3, 1);\r
+  s := 'Screen Resolution is     by    ';\r
+  X := XCenter - (Length(s) * 4);\r
+  Print_Text(s,X,30,4,0);\r
+  Str(XMax,s);\r
+  Print_Text(s, X + 8 * 21, 30, 8, 0);\r
+  Str(YMax,s);\r
+  Print_Text(s, X + 8 * 28, 30, 15, 0);\r
+\r
+  FOR X := 0 TO 15 DO\r
+    Begin\r
+      SET_DAC_REGISTER( 230 + X, 63 - X * 4, 0, 15 + X * 3);\r
+      DRAW_LINE(30 + X, Ymax - 6 - X, Xmax - 20 - X, Ymax - 6 - X, 230 + X);\r
+    End;\r
+  s := 'Press <ANY KEY> to Continue';\r
+  For x := 1 to length(s) DO\r
+    s1[x] := s[x];\r
+  TPrint_Str(s1, length(s), XCenter - (26 * 4), Ymax - 18, 5);\r
+\r
+  Ch := ReadKey;\r
+  IF Ch = #27 Then\r
+    Error_Out('Abort');\r
+\r
+End;\r
+\r
+\r
+       { Initialize Sprites for Sprite Demo }\r
+\r
+Procedure Init_Sprites;\r
+Var i : byte;\r
+Begin\r
+  For i := 1 to 64 DO\r
+    Begin\r
+      Obj[i].XPos := Random(300)+10;\r
+      Obj[i].YPos := Random(200)+20;\r
+      Obj[i].XDir := Random(10)-5;\r
+      Obj[i].YDir := Random(10)-5;\r
+      If (Obj[i].XDir = 0) AND (Obj[i].YDir = 0) Then\r
+        Begin\r
+          Obj[i].XDir := Random(5) + 1;\r
+          Obj[i].YDir := Random(5) + 1;\r
+        End;\r
+      Obj[i].Shape := Random(4)+1;\r
+      Obj[i].LastX := obj[i].XPos;\r
+      Obj[i].LastY := obj[i].YPos;\r
+    End;\r
+End;\r
+\r
+Procedure Set_Sprites(number : byte);\r
+Var i : Byte;\r
+Begin\r
+  For i := 1 to number DO\r
+    Begin\r
+      obj[i].LastX := obj[i].XPos;\r
+      obj[i].LastY := obj[i].YPos;\r
+      obj[i].XPos := obj[i].XPos + obj[i].XDir;\r
+      obj[i].YPos := obj[i].YPos + obj[i].YDir;\r
+      If (obj[i].XPos > 335) OR (obj[i].XPos < 5 ) Then\r
+        obj[i].XDir := -(obj[i].XDir);\r
+      If (obj[i].YPos > 220) OR (obj[i].YPos < 5) Then\r
+        obj[i].YDir := -(obj[i].YDir);\r
+    End;\r
+  For i := 1 to number DO\r
+    Case obj[i].Shape of\r
+      1 : TDraw_Bitmap(Circle_16,obj[i].XPos,obj[i].YPos,16,16);\r
+      2 : TDraw_Bitmap(Square_16,obj[i].XPos,obj[i].YPos,16,16);\r
+      3 : TDraw_Bitmap(Diamond,obj[i].XPos,obj[i].YPos,8,8);\r
+      4 : TDraw_Bitmap(Rectangle,obj[i].XPos,obj[i].YPos,3,8);\r
+    End;\r
+End;\r
+\r
+Procedure Remove_Sprites(p,number : byte);\r
+Var i : byte;\r
+Begin\r
+  For i := 1 to number DO\r
+    Copy_Bitmap(2,obj[i].LastX,obj[i].LastY,obj[i].LastX+16,obj[i].LastY+16,p,Obj[i].LastX,Obj[i].LastY);\r
+End;\r
+\r
+Procedure Page_Demo;\r
+Begin\r
+  Number_Of_Shapes := 64;\r
+  XView_Change := 1;\r
+  YView_Change := 1;\r
+  XView := 1;\r
+  YView := 1;\r
+  Right := TRUE;\r
+  ScreenX := 360;\r
+  ScreenY := 240;\r
+  PrevColor := 0;\r
+  SetColor := 3;\r
+  SDir := 1;\r
+  PDir := 1;\r
+  Str(0,s);\r
+\r
+  IF SET_VGA_MODEX(0, ScreenX, ScreenY, 3) = 0 THEN\r
+    ERROR_OUT('Unable to SET_VGA_MODEX' + S);\r
+\r
+  SET_ACTIVE_PAGE(0);\r
+  CLEAR_VGA_SCREEN(0);\r
+  PRINT_TEXT('This is a Test of the Following Functions:', 10, 9, 15, 0);\r
+  DRAW_LINE( 10, 18, 350, 18, 4);\r
+  Print_Text('SET_ACTIVE_PAGE', 10, 20, 1, 0);\r
+  Print_Text('SET_DISPLAY_PAGE', 10, 30, 3,0);\r
+  Print_Text('SET_DAC_REGISTER', 10, 40, 3, 0);\r
+  Print_Text('CLEAR_VGA_SCREEN', 10, 50, 13, 0);\r
+  Print_Text('TDRAW_BITMAP', 10, 60, 14, 0);\r
+  Print_Text('COPY_PAGE', 10, 70, 3, 0);\r
+  Print_Text('COPY_BITMAP', 10, 80, 13, 0);\r
+  Print_Text('GPRINTC', 10, 90, 1, 0);\r
+  Print_Text('TGPRINTC', 10, 100, 3, 0);\r
+  Print_Text('SYNC_DISPLAY', 10, 110, 3, 0);\r
+  Print_Text('SET_WINDOW', 10, 120, 14, 0);\r
+  Print_Text('VIRTUAL SCREEN SIZES', 190, 20, 1, 0);\r
+  Print_Text('    SMOOTH SCROLLING', 190, 30, 3, 0);\r
+  Print_Text('    SPRITE ANIMATION', 190, 40, 13, 0);\r
+  Print_Text('       PAGE FLIPPING', 190, 50, 3, 0);\r
+  Print_Text('       COLOR CYCLING', 190, 60, 14, 0);\r
+\r
+  FOR X := 0 TO 60 DO\r
+    Begin\r
+      SET_DAC_REGISTER( 50 + X, 3 + X, 0, 60 - X);\r
+      SET_DAC_REGISTER( 150 + X, 3 + X, 0, 60 - X);\r
+    End;\r
+\r
+  c := 0;\r
+  DC := 1;\r
+  FOR X := 0 TO ScreenX div 2 DO\r
+    Begin\r
+      DRAW_LINE( ScreenX div 2 - 1, ScreenY div 4, X, ScreenY - 1, c + 50);\r
+      DRAW_LINE( ScreenX div 2, ScreenY div 4, ScreenX - X - 1, ScreenY - 1, c + 50);\r
+      c := c + DC;\r
+      IF (c = 0) OR (c = 60) THEN DC := -DC;\r
+    End;\r
+\r
+  TPrint_Text('Press <ESC> to Continue', 82, 190, 15);\r
+  TPrint_Text('<+> = Fewer Shapes  <-> = More Shapes', 32, 204, 12);\r
+  COPY_PAGE( 0, 1);\r
+  COPY_PAGE( 0, 2);\r
+\r
+  Ch := #0;\r
+  CurrentPage := 1;\r
+  LastPage := 0;\r
+  Set_Sprites(Number_Of_Shapes);\r
+  For c := 1 to 4 DO\r
+    Set_Dac_Register(19+c,63-(c*10),0,0);\r
+\r
+  While Ch <> #27 DO\r
+    Begin\r
+      Set_Active_Page(currentpage);\r
+      Set_Sprites(Number_Of_Shapes);\r
+      If Right Then\r
+        Begin\r
+          XView := XView + XView_Change;\r
+          If (XView > 38) OR (XView < 2) Then\r
+            Begin\r
+              XView_Change := -(XView_Change);\r
+              Right := FALSE;\r
+            End;\r
+        End\r
+      Else\r
+        Begin\r
+          YView := YView + YView_Change;\r
+          If (YView > 38) OR (YView < 2) Then\r
+            Begin\r
+              YView_Change := -(YView_Change);\r
+              Right := TRUE;\r
+            End;\r
+        End;\r
+\r
+      Set_Window(currentpage,XView,YView);\r
+      Set_Display_Page(currentpage);\r
+      Set_Dac_Register(50 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor);\r
+      Set_Dac_Register(50 + SetColor, SetColor, 10, 63 - SetColor);\r
+      Set_Dac_Register(150 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor);\r
+      Set_Dac_Register(150 + SetColor, 63, 63, SetColor);\r
+      SetColor := SetColor + SDir;\r
+      IF (SetColor = 60) OR (SetColor = 0) THEN SDir := -SDir;\r
+      PrevColor := PrevColor + PDir;\r
+      IF (PrevColor = 60) OR (PrevColor = 0) THEN PDir := -PDir;\r
+      Remove_Sprites(lastpage,Number_Of_Shapes);\r
+\r
+      If Keypressed Then\r
+        Begin\r
+          Ch := ReadKey;\r
+          Case Ch of\r
+            '-' : If Number_Of_Shapes > 1 Then\r
+                    Begin\r
+                      c := Number_Of_Shapes;\r
+                      Copy_Bitmap(2,obj[c].XPos,obj[c].YPos,obj[c].XPos+16,obj[c].YPos+16,\r
+                         currentpage,obj[c].XPos,obj[c].YPos);\r
+                      Dec(Number_Of_Shapes);\r
+                    End;\r
+            '+' : If Number_Of_Shapes < 64 Then Inc(Number_Of_Shapes);\r
+          End;\r
+        End;\r
+      lastpage := (lastpage+1) MOD 2;\r
+      currentpage := (currentpage+1) MOD 2;\r
+    End;\r
+END;\r
+\r
+       { MAIN ROUTINE - Run Through Demos and Exit }\r
+\r
+Begin\r
+\r
+  Randomize;\r
+  Init_Sprites;\r
+\r
+  Demo_Res(0, 320, 200);\r
+  Demo_Res(1, 320, 400);\r
+  Demo_Res(2, 360, 200);\r
+  Demo_Res(3, 360, 400);\r
+  Demo_Res(4, 320, 240);\r
+  Demo_Res(5, 320, 480);\r
+  Demo_Res(6, 360, 240);\r
+  Demo_Res(7, 360, 480);\r
+  Page_Demo;\r
+\r
+  asm\r
+    mov ah,0\r
+    mov al,3\r
+    int 10h\r
+  end;\r
+  WriteLn('THIS MODE X DEMO IS FINISHED');\r
+\r
+END.
\ No newline at end of file
diff --git a/src/lib/modex/demos/qb45/make-lib.bat b/src/lib/modex/demos/qb45/make-lib.bat
new file mode 100755 (executable)
index 0000000..b04876a
--- /dev/null
@@ -0,0 +1,5 @@
+ECHO ... Building MODEX.QLB for QUICKBASIC 4.5\r
+LIB MODEX -+MODEX,,\r
+LIB MODEX -+UTILS,,\r
+DEL MODEX.BAK\r
+LINK /Q MODEX+UTILS, MODEX.QLB, NUL, C:\QB45\BQLB45.LIB;\1a\r
diff --git a/src/lib/modex/demos/qb45/modex.bi b/src/lib/modex/demos/qb45/modex.bi
new file mode 100755 (executable)
index 0000000..6b1d7af
--- /dev/null
@@ -0,0 +1,63 @@
\r
+    ' ===== SCREEN RESOLUTIONS =====\r
\r
+CONST Mode320x200 = 0, Mode320x400 = 1\r
+CONST Mode360x200 = 2, Mode360x400 = 3\r
+CONST Mode320x240 = 4, Mode320x480 = 5\r
+CONST Mode360x240 = 6, Mode360x480 = 7\r
\r
+    ' ===== MODE X SETUP ROUTINES =====\r
\r
+DECLARE FUNCTION SET.VGA.MODEX% ALIAS "SET_VGA_MODEX" (BYVAL ModeType%, BYVAL MaxXpos%, BYVAL MaxYpos%, BYVAL Pages%)\r
+DECLARE FUNCTION SET.MODEX% ALIAS "SET_MODEX" (BYVAL Mode%)\r
\r
+    ' ===== BASIC GRAPHICS PRIMITIVES =====\r
\r
+DECLARE SUB CLEAR.VGA.SCREEN ALIAS "CLEAR_VGA_SCREEN" (BYVAL ColorNum%)\r
+DECLARE SUB SET.POINT ALIAS "SET_POINT" (BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorNum%)\r
+DECLARE FUNCTION READ.POINT% ALIAS "READ_POINT" (BYVAL Xpos%, BYVAL Ypos%)\r
+DECLARE SUB FILL.BLOCK ALIAS "FILL_BLOCK" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
+DECLARE SUB DRAW.LINE ALIAS "DRAW_LINE" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
\r
+    ' ===== DAC COLOR REGISTER ROUTINES =====\r
\r
+DECLARE SUB SET.DAC.REGISTER ALIAS "SET_DAC_REGISTER" (BYVAL RegNo%, BYVAL Red%, BYVAL Green%, BYVAL Blue%)\r
+DECLARE SUB GET.DAC.REGISTER ALIAS "GET_DAC_REGISTER" (BYVAL RegNo%, Red%, Green%, Blue%)\r
+DECLARE SUB LOAD.DAC.REGISTERS ALIAS "LOAD_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%, BYVAL VSync%)\r
+DECLARE SUB READ.DAC.REGISTERS ALIAS "READ_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%)\r
\r
\r
+    ' ===== PAGE FLIPPING AND SCROLLING ROUTINES =====\r
\r
+DECLARE SUB SET.ACTIVE.PAGE ALIAS "SET_ACTIVE_PAGE" (BYVAL PageNo%)\r
+DECLARE FUNCTION GET.ACTIVE.PAGE% ALIAS "GET_ACTIVE_PAGE"\r
+DECLARE SUB SET.DISPLAY.PAGE ALIAS "SET_DISPLAY_PAGE" (BYVAL PageNo%)\r
+DECLARE FUNCTION GET.DISPLAY.PAGE% ALIAS "GET_DISPLAY_PAGE"\r
+DECLARE SUB SET.WINDOW ALIAS "SET_WINDOW" (BYVAL DisplayPage%, BYVAL XOffset%, BYVAL YOffset%)\r
+DECLARE FUNCTION GET.X.OFFSET% ALIAS "GET_X_OFFSET" ()\r
+DECLARE FUNCTION GET.Y.OFFSET% ALIAS "GET_Y_OFFSET" ()\r
+DECLARE SUB SYNC.DISPLAY ALIAS "SYNC_DISPLAY"\r
\r
+    ' ===== TEXT DISPLAY ROUTINES =====\r
\r
+DECLARE SUB GPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
+DECLARE SUB TGPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
+DECLARE SUB PRINT.STR ALIAS "PRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
+DECLARE SUB TPRINT.STR ALIAS "TPRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
+DECLARE SUB SET.DISPLAY.FONT ALIAS "SET_DISPLAY_FONT" (SEG FontData AS ANY, BYVAL FontNumber%)\r
\r
+    ' ===== BITMAP (SPRITE) DISPLAY ROUTINES =====\r
\r
+DECLARE SUB DRAW.BITMAP ALIAS "DRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
+DECLARE SUB TDRAW.BITMAP ALIAS "TDRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
\r
+    ' ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====\r
\r
+DECLARE SUB COPY.PAGE ALIAS "COPY_PAGE" (BYVAL SourcePage%, BYVAL DestPage%)\r
+DECLARE SUB COPY.BITMAP ALIAS "COPY_BITMAP" (BYVAL SourcePage%, BYVAL X1%, BYVAL Y1%, BYVAL X2%, BYVAL Y2%, BYVAL DestPage%, BYVAL DestX1%, BYVAL DestY1%)\r
\r
\r
\r
\r
\r
\r
diff --git a/src/lib/modex/demos/qb45/modex.qlb b/src/lib/modex/demos/qb45/modex.qlb
new file mode 100755 (executable)
index 0000000..90122c1
Binary files /dev/null and b/src/lib/modex/demos/qb45/modex.qlb differ
diff --git a/src/lib/modex/demos/qb45/test6a.bas b/src/lib/modex/demos/qb45/test6a.bas
new file mode 100755 (executable)
index 0000000..b2487d5
--- /dev/null
@@ -0,0 +1,561 @@
+'File:     TEST6A.BAS\r
+'Descp.:   A Mode "X" demonstration for Quickbasic 4.5\r
+'Author:   Matt Pritchard\r
+'Date:     14 April, 1993\r
+'\r
+DECLARE SUB DEMO.RES (Mode%, Xmax%, Ymax%)\r
+DECLARE SUB ERROR.OUT (Message$)\r
+DECLARE FUNCTION GET.KEY% ()\r
+DECLARE SUB LOAD.SHAPES ()\r
+DECLARE SUB PAGE.DEMO ()\r
+DECLARE SUB PRINT.TEXT (Text$, Xpos%, Ypos%, ColorF%, ColorB%)\r
+DECLARE SUB TPRINT.TEXT (Text$, Xpos%, Ypos%, ColorF%)\r
+DEFINT A-Z\r
+\r
+\r
+TYPE ShapeType\r
+       ImgData AS STRING * 512\r
+       xWidth  AS INTEGER\r
+       yWidth  AS INTEGER\r
+END TYPE\r
+\r
+TYPE Sprite\r
+       Xpos    AS INTEGER\r
+       Ypos    AS INTEGER\r
+       XDir    AS INTEGER\r
+       YDir    AS INTEGER\r
+       Shape   AS INTEGER\r
+END TYPE\r
+\r
+\r
+CONST MaxShapes = 32\r
+\r
+       REM $INCLUDE: 'UTILS.BI'\r
+       REM $INCLUDE: 'MODEX.BI'\r
+\r
+DIM SHARED Img(32) AS ShapeType\r
+COMMON SHARED Img() AS ShapeType\r
+\r
+\r
+       CALL INIT.RANDOM\r
+\r
+       CALL LOAD.SHAPES\r
+\r
+       CALL DEMO.RES(Mode320x200, 320, 200)\r
+       CALL DEMO.RES(Mode320x400, 320, 400)\r
+\r
+       CALL DEMO.RES(Mode360x200, 360, 200)\r
+       CALL DEMO.RES(Mode360x400, 360, 400)\r
+\r
+       CALL DEMO.RES(Mode320x240, 320, 240)\r
+       CALL DEMO.RES(Mode320x480, 320, 480)\r
+\r
+       CALL DEMO.RES(Mode360x240, 360, 240)\r
+       CALL DEMO.RES(Mode360x480, 360, 480)\r
+\r
+       CALL PAGE.DEMO\r
+\r
+       SET.VIDEO.MODE 3\r
+       DOS.PRINT "THIS MODE X DEMO IS FINISHED"\r
+       END\r
+\r
+SUB DEMO.RES (Mode, Xmax, Ymax)\r
+\r
+       IF SET.MODEX%(Mode) = 0 THEN\r
+               ERROR.OUT "Unable to SET_MODEX" + STR$(Mode)\r
+       END IF\r
+\r
+       XCenter = Xmax \ 2\r
+       \r
+       X1 = 10\r
+       Y1 = 10\r
+       X2 = Xmax - 1\r
+       Y2 = Ymax - 1\r
+\r
+       FOR Z = 0 TO 3\r
+               Colr = 31 - Z * 2\r
+               DRAW.LINE X1 + Z, Y1 + Z, X2 - Z, Y1 + Z, Colr\r
+               DRAW.LINE X1 + Z, Y1 + Z, X1 + Z, Y2 - Z, Colr\r
+               DRAW.LINE X1 + Z, Y2 - Z, X2 - Z, Y2 - Z, Colr\r
+               DRAW.LINE X2 - Z, Y1 + Z, X2 - Z, Y2 - Z, Colr\r
+       NEXT Z\r
+\r
+       XChars = Xmax \ 10\r
+       YChars = Ymax \ 10\r
+\r
+       FOR X = 0 TO XChars - 1\r
+               TGPRINTC 48 + ((X + 1) MOD 10), X * 10 + 1, 1, 9 + ((X \ 8) MOD 7)\r
+               DRAW.LINE X * 10 + 9, 0, X * 10 + 9, 3, 15\r
+       NEXT X\r
+\r
+       FOR Y = 0 TO YChars - 1\r
+               TGPRINTC 48 + ((Y + 1) MOD 10), 1, Y * 10 + 1, 9 + ((Y \ 10) MOD 7)\r
+               DRAW.LINE 0, Y * 10 + 9, 3, Y * 10 + 9, 15\r
+       NEXT Y\r
+\r
+       ' Draw Lines\r
+\r
+       FOR X = 0 TO 63\r
+               N = 15 + X * .75\r
+               SET.DAC.REGISTER 64 + X, N, N, N\r
+               SET.DAC.REGISTER 128 + X, 0, N, N\r
+\r
+               DRAW.LINE 103 - X, 60, 40 + X, 123, 64 + X\r
+               DRAW.LINE 40, 60 + X, 103, 123 - X, 128 + X\r
+\r
+       NEXT X\r
+       TPRINT.TEXT "LINE TEST", 37, 130, c.BLUE\r
+\r
+       Y = 60: Gap = 0\r
+       FOR X = 0 TO 9\r
+               FILL.BLOCK 120, Y, 120 + X, Y + Gap, 64 + X\r
+               FILL.BLOCK 140 - (15 - X), Y, 150 + X, Y + Gap, 230 + X\r
+               FILL.BLOCK 170 - (15 - X), Y, 170, Y + Gap, 128 + X\r
+               Y = Y + Gap + 2\r
+               Gap = Gap + 1\r
+       NEXT X\r
+       TPRINT.TEXT "FILL TEST", 110, 46, c.GREEN\r
+\r
+\r
+       FOR X = 190 TO 250 STEP 2\r
+               FOR Y = 60 TO 122 STEP 2\r
+                 SET.POINT X, Y, X + Y + X + Y\r
+               NEXT Y\r
+       NEXT X\r
+\r
+       TPRINT.TEXT "PIXEL TEST", 182, 130, c.RED\r
+\r
+       FOR X = 190 TO 250 STEP 2\r
+               FOR Y = 60 TO 122 STEP 2\r
+                 IF READ.POINT(X, Y) <> ((X + Y + X + Y) AND 255) THEN\r
+                        ERROR.OUT "READ.PIXEL Failure"\r
+                 END IF\r
+               NEXT Y\r
+       NEXT X\r
+\r
+\r
+\r
+       Msg$ = " This is a MODE X demo "\r
+       PRINT.TEXT Msg$, XCenter - (LEN(Msg$) * 4), 20, c.bRED, c.BLUE\r
+       Msg$ = "Screen Resolution is     by    "\r
+       Xp = XCenter - (LEN(Msg$) * 4)\r
+       PRINT.TEXT Msg$, Xp, 30, c.bGREEN, c.BLACK\r
+\r
+       PRINT.TEXT LTRIM$(STR$(Xmax)), Xp + 8 * 21, 30, c.bPURPLE, c.BLACK\r
+       PRINT.TEXT LTRIM$(STR$(Ymax)), Xp + 8 * 28, 30, c.bWHITE, c.BLACK\r
+\r
+       FOR X = 0 TO 15\r
+               SET.DAC.REGISTER 230 + X, 63 - X * 4, 0, 15 + X * 3\r
+               DRAW.LINE 30 + X, Ymax - 6 - X, Xmax - 20 - X, Ymax - 6 - X, 230 + X\r
+       NEXT X\r
+       TPRINT.TEXT "Press <ANY KEY> to Continue", XCenter - (26 * 4), Ymax - 18, c.YELLOW\r
+\r
+       X = GET.KEY%\r
+       IF X = KyESC THEN ERROR.OUT "ABORT"\r
+\r
+END SUB\r
+\r
+SUB ERROR.OUT (Message$)\r
+\r
+       SET.VIDEO.MODE 3\r
+       DOS.PRINT Message$\r
+       END\r
+\r
+END SUB\r
+\r
+FUNCTION GET.KEY%\r
+\r
+       DO\r
+               X = SCAN.KEYBOARD\r
+       LOOP UNTIL X\r
+\r
+       GET.KEY% = X\r
+\r
+END FUNCTION\r
+\r
+SUB LOAD.SHAPES\r
+\r
+DIM Grid(1 TO 32, 1 TO 32)\r
+\r
+       FOR Shape = 0 TO MaxShapes - 1\r
+\r
+               FOR Y = 1 TO 32\r
+               FOR X = 1 TO 32\r
+                       Grid(X, Y) = 0\r
+               NEXT X\r
+               NEXT Y\r
+\r
+               Style = RANDOM.INT(6)\r
+               Colour = 1 + RANDOM.INT(15)\r
+               \r
+               SELECT CASE Style\r
+\r
+               CASE 0:         ' Solid Box\r
+\r
+                       DO\r
+                               xWidth = 3 + RANDOM.INT(30)\r
+                               yWidth = 3 + RANDOM.INT(30)\r
+                       LOOP UNTIL ((xWidth * yWidth) <= 512)\r
+\r
+                       FOR Y = 1 TO yWidth\r
+                               FOR X = 1 TO xWidth\r
+                                       Grid(X, Y) = Colour\r
+                               NEXT X\r
+                       NEXT Y\r
+\r
+               CASE 1:         ' Hollow Box\r
+\r
+                       DO\r
+                               xWidth = 5 + RANDOM.INT(28)\r
+                               yWidth = 5 + RANDOM.INT(28)\r
+                       LOOP UNTIL ((xWidth * yWidth) <= 512)\r
+\r
+                       FOR Y = 1 TO yWidth\r
+                               FOR X = 1 TO xWidth\r
+                                       Grid(X, Y) = Colour\r
+                               NEXT X\r
+                       NEXT Y\r
+\r
+                       HollowX = 1 + RANDOM.INT(xWidth \ 2 - 1)\r
+                       HollowY = 1 + RANDOM.INT(yWidth \ 2 - 1)\r
+\r
+                       FOR Y = HollowY + 1 TO yWidth - HollowY\r
+                               FOR X = HollowX + 1 TO xWidth - HollowX\r
+                                       Grid(X, Y) = nil\r
+                               NEXT X\r
+                       NEXT Y\r
+\r
+               CASE 2:         ' Solid Diamond\r
+\r
+                       xWidth = 3 + 2 * RANDOM.INT(10)\r
+                       yWidth = xWidth\r
+                       Centre = xWidth \ 2\r
+\r
+                       FOR Y = 0 TO Centre\r
+                               FOR X = 0 TO Y\r
+                                       Grid(Centre - X + 1, Y + 1) = Colour\r
+                                       Grid(Centre + X + 1, Y + 1) = Colour\r
+                                       Grid(Centre - X + 1, yWidth - Y) = Colour\r
+                                       Grid(Centre + X + 1, yWidth - Y) = Colour\r
+                               NEXT X\r
+                       NEXT Y\r
+\r
+\r
+               CASE 3:         ' Hollow Diamond\r
+\r
+\r
+                       xWidth = 3 + 2 * RANDOM.INT(10)\r
+                       yWidth = xWidth\r
+                       Centre = xWidth \ 2\r
+                       sWidth = RANDOM.INT(Centre)\r
+\r
+                       FOR Y = 0 TO Centre\r
+                               FOR X = 0 TO Y\r
+                                       IF X + (Centre - Y) >= sWidth THEN\r
+                                               Grid(Centre - X + 1, Y + 1) = Colour\r
+                                               Grid(Centre + X + 1, Y + 1) = Colour\r
+                                               Grid(Centre - X + 1, yWidth - Y) = Colour\r
+                                               Grid(Centre + X + 1, yWidth - Y) = Colour\r
+                                       END IF\r
+                               NEXT X\r
+                       NEXT Y\r
+\r
+               CASE 4:         ' Ball\r
+\r
+                       xWidth = 7 + 2 * RANDOM.INT(8)\r
+                       yWidth = xWidth\r
+                       Centre = 1 + xWidth \ 2\r
+\r
+                       FOR Y = 1 TO yWidth\r
+                               FOR X = 1 TO xWidth\r
+                                       D = SQR(((Centre - X) * (Centre - X)) + ((Centre - Y) * (Centre - Y)))\r
+                                       IF D < Centre THEN Grid(X, Y) = 150 + Colour * 2 + D * 3\r
+                               NEXT X\r
+                       NEXT Y\r
+\r
+               CASE 5:         ' Ball\r
+\r
+\r
+                       xWidth = 7 + 2 * RANDOM.INT(8)\r
+                       yWidth = xWidth\r
+                       Centre = 1 + xWidth \ 2\r
+                       sWidth = RANDOM.INT(xWidth)\r
+\r
+                       FOR Y = 1 TO yWidth\r
+                               FOR X = 1 TO xWidth\r
+                                       D = SQR(((Centre - X) * (Centre - X)) + ((Centre - Y) * (Centre - Y)))\r
+                                       IF D < Centre AND D >= sWidth THEN Grid(X, Y) = 150 + Colour * 2 + D * 3\r
+                               NEXT X\r
+                       NEXT Y\r
+\r
+               END SELECT\r
+\r
+               Img(Shape).xWidth = xWidth\r
+               Img(Shape).yWidth = yWidth\r
+\r
+               A$ = STRING$(xWidth * yWidth, nil)\r
+\r
+               c = 1\r
+               FOR Y = 1 TO yWidth\r
+                       FOR X = 1 TO xWidth\r
+                               MID$(A$, c, 1) = CHR$(Grid(X, Y))\r
+                               c = c + 1\r
+                       NEXT X\r
+               NEXT Y\r
+\r
+               Img(Shape).ImgData = A$\r
+               \r
+\r
+       NEXT Shape\r
+\r
+END SUB\r
+\r
+SUB PAGE.DEMO\r
+\r
+CONST MaxSprites = 64\r
+\r
+DIM Obj(MaxSprites) AS Sprite\r
+DIM LastX(MaxSprites, 1), LastY(MaxSprites, 1)\r
+DIM LastObjects(1)\r
+\r
+       ScreenX = 360: ScreenY = 240\r
+\r
+       IF SET.VGA.MODEX%(Mode320x200, ScreenX, ScreenY, 3) = 0 THEN\r
+               ERROR.OUT "Unable to SET_VGA_MODEX" + STR$(Mode)\r
+       END IF\r
+\r
+       SET.ACTIVE.PAGE 0\r
+\r
+       CLEAR.VGA.SCREEN c.BLACK\r
+                               \r
+       PRINT.TEXT "This is a Test of the Following Functions:", 10, 9, c.bWHITE, c.BLACK\r
+\r
+       DRAW.LINE 10, 18, 350, 18, c.YELLOW\r
+       PRINT.TEXT "SET_ACTIVE_PAGE", 10, 20, c.bBLUE, c.BLACK\r
+       PRINT.TEXT "SET_DISPLAY_PAGE", 10, 30, c.GREEN, c.BLACK\r
+       PRINT.TEXT "SET_DAC_REGISTER", 10, 40, c.RED, c.BLACK\r
+       PRINT.TEXT "CLEAR_VGA_SCREEN", 10, 50, c.CYAN, c.BLACK\r
+\r
+       PRINT.TEXT "TDRAW_BITMAP", 10, 60, c.PURPLE, c.BLACK\r
+       PRINT.TEXT "COPY_PAGE", 10, 70, c.GREEN, c.BLACK\r
+       PRINT.TEXT "COPY_BITMAP", 10, 80, c.CYAN, c.BLACK\r
+\r
+       PRINT.TEXT "GPRINTC", 10, 90, c.BLUE, c.BLACK\r
+       PRINT.TEXT "TGPRINTC", 10, 100, c.GREEN, c.BLACK\r
+       PRINT.TEXT "SET_WINDOW", 10, 110, c.RED, c.BLACK\r
+\r
+       PRINT.TEXT "VIRTUAL SCREEN SIZES", 190, 20, c.bBLUE, c.BLACK\r
+       PRINT.TEXT "    SMOOTH SCROLLING", 190, 30, c.GREEN, c.BLACK\r
+       PRINT.TEXT "    SPRITE ANIMATION", 190, 40, c.CYAN, c.BLACK\r
+       PRINT.TEXT "       PAGE FLIPPING", 190, 50, c.RED, c.BLACK\r
+       PRINT.TEXT "       COLOR CYCLING", 190, 60, c.PURPLE, c.BLACK\r
+\r
+\r
+       FOR X = 0 TO 60\r
+               SET.DAC.REGISTER 50 + X, 3 + X, 0, 60 - X\r
+               SET.DAC.REGISTER 150 + X, 3 + X, 0, 60 - X\r
+       NEXT X\r
+\r
+       c = 0: DC = 1\r
+       FOR X = 0 TO ScreenX \ 2\r
+               DRAW.LINE ScreenX \ 2 - 1, ScreenY \ 4, X, ScreenY - 1, c + 50\r
+               DRAW.LINE ScreenX \ 2, ScreenY \ 4, ScreenX - X - 1, ScreenY - 1, c + 50\r
+               c = c + DC\r
+               IF c = 0 OR c = 60 THEN DC = -DC\r
+       NEXT X\r
+                               \r
+       TPRINT.TEXT "Press <ANY KEY> to Continue", 72, 190, c.bWHITE\r
+       TPRINT.TEXT "< > = Faster   < > = Slower", 72, 204, c.bGREEN\r
+       TPRINT.TEXT "< > = Fewer Shapes  < > = More Shapes", 32, 218, c.bCYAN\r
+\r
+       TGPRINTC 43, 80, 204, c.YELLOW\r
+       TGPRINTC 45, 200, 204, c.YELLOW\r
+\r
+       TGPRINTC 25, 40, 218, c.YELLOW\r
+       TGPRINTC 24, 200, 218, c.YELLOW\r
+\r
+       COPY.PAGE 0, 1\r
+       COPY.PAGE 0, 2\r
+\r
+       FOR X = 1 TO MaxSprites\r
+               DO\r
+                       Obj(X).XDir = RANDOM.INT(7) - 3\r
+                       Obj(X).YDir = RANDOM.INT(7) - 3\r
+               LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0)\r
+\r
+               Obj(X).Shape = X MOD MaxShapes\r
+\r
+               SpriteX = Img(Obj(X).Shape).xWidth\r
+               SpriteY = Img(Obj(X).Shape).yWidth\r
+\r
+               Obj(X).Xpos = 1 + RANDOM.INT(ScreenX - SpriteX - 2)\r
+               Obj(X).Ypos = 1 + RANDOM.INT(ScreenY - SpriteY - 2)\r
+\r
+               LastX(X, 0) = Obj(X).Xpos\r
+               LastX(X, 1) = Obj(X).Xpos\r
+               LastY(X, 0) = Obj(X).Ypos\r
+               LastY(X, 1) = Obj(X).Ypos\r
+       NEXT X\r
+\r
+       CurrentPage = 0\r
+\r
+       'View Shift...\r
+\r
+       ViewX = 0\r
+       ViewY = 0\r
+       ViewMax = 3\r
+       ViewCnt = 0\r
+       ViewXD = 1\r
+       ViewYD = 1\r
+\r
+       SetColor = 3: SDir = 1\r
+       PrevColor = 0: PDir = 1\r
+\r
+       VisObjects = MaxSprites \ 2\r
+       LastObjects(0) = 0\r
+       LastObjects(1) = 0\r
+\r
+DRAW.LOOP:\r
+\r
+\r
+       SET.ACTIVE.PAGE CurrentPage\r
+\r
+       ' Erase Old Images\r
+\r
+       FOR X = 1 TO LastObjects(CurrentPage)\r
+       \r
+               X1 = LastX(X, CurrentPage) AND &HFFFC\r
+               Y1 = LastY(X, CurrentPage)\r
+               X2 = ((LastX(X, CurrentPage) + Img(Obj(X).Shape).xWidth)) OR 3\r
+               Y2 = Y1 + Img(Obj(X).Shape).yWidth - 1\r
+\r
+               COPY.BITMAP 2, X1, Y1, X2, Y2, CurrentPage, X1, Y1\r
+       \r
+       NEXT X\r
+\r
+       ' Draw new images\r
+\r
+       FOR X = 1 TO VisObjects\r
+\r
+               SpriteX = Img(Obj(X).Shape).xWidth\r
+               SpriteY = Img(Obj(X).Shape).yWidth\r
+\r
+               ' Move Sprite\r
+\r
+REDOX:\r
+               NewX = Obj(X).Xpos + Obj(X).XDir\r
+               IF NewX < 0 OR NewX + SpriteX > ScreenX THEN\r
+                       Obj(X).XDir = -Obj(X).XDir\r
+                       IF RANDOM.INT(20) = 1 THEN\r
+                               DO\r
+                                       Obj(X).XDir = RANDOM.INT(7) - 3\r
+                                       Obj(X).YDir = RANDOM.INT(7) - 3\r
+                               LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0)\r
+                               GOTO REDOX\r
+                       END IF\r
+               END IF\r
+               Obj(X).Xpos = Obj(X).Xpos + Obj(X).XDir\r
+\r
+REDOY:\r
+               NewY = Obj(X).Ypos + Obj(X).YDir\r
+               IF NewY < 0 OR NewY + SpriteY > ScreenY THEN\r
+                       Obj(X).YDir = -Obj(X).YDir\r
+                       IF RANDOM.INT(20) = 1 THEN\r
+                               DO\r
+                                       Obj(X).XDir = RANDOM.INT(7) - 3\r
+                                       Obj(X).YDir = RANDOM.INT(7) - 3\r
+                               LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0)\r
+                               GOTO REDOY\r
+                       END IF\r
+               END IF\r
+               Obj(X).Ypos = Obj(X).Ypos + Obj(X).YDir\r
+\r
+               'Draw Sprite\r
+\r
+               TDRAW.BITMAP Img(Obj(X).Shape), Obj(X).Xpos, Obj(X).Ypos, SpriteX, SpriteY\r
+\r
+               LastX(X, CurrentPage) = Obj(X).Xpos\r
+               LastY(X, CurrentPage) = Obj(X).Ypos\r
+\r
+       NEXT X\r
+\r
+       LastObjects(CurrentPage) = VisObjects\r
+\r
+       ' Pan Screen Back & Forth\r
+\r
+       ViewCnt = ViewCnt + 1\r
+       IF ViewCnt >= ViewMax THEN\r
+               ViewX = ViewX + ViewXD\r
+               IF ViewX = 0 OR ViewX = 39 THEN ViewXD = -ViewXD\r
+               IF ViewXD < 0 THEN\r
+                       ViewY = ViewY + ViewYD\r
+                       IF ViewY = 0 OR ViewY = 39 THEN ViewYD = -ViewYD\r
+               END IF\r
+       \r
+               SET.WINDOW CurrentPage, ViewX, ViewY\r
+\r
+               ViewCnt = 0\r
+       ELSE\r
+               SET.DISPLAY.PAGE CurrentPage\r
+       END IF\r
+\r
+       ' Cycle Colors\r
+\r
+       SET.DAC.REGISTER 50 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor\r
+       SET.DAC.REGISTER 50 + SetColor, SetColor, 10, 63 - SetColor\r
+\r
+       SET.DAC.REGISTER 150 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor\r
+       SET.DAC.REGISTER 150 + SetColor, 63, 63, SetColor\r
+\r
+       SetColor = SetColor + SDir\r
+       IF SetColor = 60 OR SetColor = 0 THEN SDir = -SDir\r
+\r
+       PrevColor = PrevColor + PDir\r
+       IF PrevColor = 60 OR PrevColor = 0 THEN PDir = -PDir\r
+\r
+       CurrentPage = 1 - CurrentPage\r
+\r
+       Code = SCAN.KEYBOARD\r
+\r
+       IF Code = False THEN GOTO DRAW.LOOP\r
+\r
+       IF Code = KyPlus THEN\r
+               IF ViewMax < 12 THEN ViewMax = ViewMax + 1\r
+               GOTO DRAW.LOOP\r
+       END IF\r
+\r
+       IF Code = KyMinus THEN\r
+               IF ViewMax > 1 THEN ViewMax = ViewMax - 1\r
+               IF ViewCnt >= ViewMax THEN ViewCnt = 0\r
+               GOTO DRAW.LOOP\r
+       END IF\r
+\r
+       IF Code = KyUp THEN\r
+               IF VisObjects < MaxSprites THEN VisObjects = VisObjects + 1\r
+               GOTO DRAW.LOOP\r
+       END IF\r
+               \r
+       IF Code = KyDown THEN\r
+               IF VisObjects > 1 THEN VisObjects = VisObjects - 1\r
+               GOTO DRAW.LOOP\r
+       END IF\r
+\r
+\r
+END SUB\r
+\r
+SUB PRINT.TEXT (Text$, Xpos, Ypos, ColorF, ColorB)\r
+\r
+       IF LEN(Text$) = 0 THEN EXIT SUB\r
+       PRINT.STR VARSEG(Text$), SADD(Text$), LEN(Text$), Xpos, Ypos, ColorF, ColorB\r
+\r
+\r
+END SUB\r
+\r
+SUB TPRINT.TEXT (Text$, Xpos, Ypos, ColorF)\r
+\r
+       IF LEN(Text$) = 0 THEN EXIT SUB\r
+\r
+       TPRINT.STR VARSEG(Text$), SADD(Text$), LEN(Text$), Xpos, Ypos, ColorF\r
+\r
+END SUB\r
+\r
diff --git a/src/lib/modex/demos/qb45/test6a.exe b/src/lib/modex/demos/qb45/test6a.exe
new file mode 100755 (executable)
index 0000000..e61d038
Binary files /dev/null and b/src/lib/modex/demos/qb45/test6a.exe differ
diff --git a/src/lib/modex/demos/qb45/uasm-qb4.bat b/src/lib/modex/demos/qb45/uasm-qb4.bat
new file mode 100755 (executable)
index 0000000..e4aa87e
--- /dev/null
@@ -0,0 +1 @@
+MASM utils, utils, utils, nul;
\ No newline at end of file
diff --git a/src/lib/modex/demos/qb45/utils.asm b/src/lib/modex/demos/qb45/utils.asm
new file mode 100755 (executable)
index 0000000..811b8f8
--- /dev/null
@@ -0,0 +1,406 @@
+;=======================================================\r
+;===  UTILS.ASM  - Asm Utilities for QuickBasic/BC7  ===\r
+;=======================================================\r
+\r
+       PAGE    255, 132\r
+\r
+       .MODEL Medium\r
+       .286\r
+\r
+       ; ==== MACROS ====\r
+\r
+       ; macros to PUSH and POP multiple registers\r
+\r
+PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+       IFNB <R1>\r
+               push    R1                              ; Save R1\r
+               PUSHx   R2, R3, R4, R5, R6, R7, R8\r
+       ENDIF\r
+ENDM\r
+\r
+POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+       IFNB <R1>\r
+               pop             R1                              ; Restore R1\r
+               POPx    R2, R3, R4, R5, R6, R7, R8\r
+       ENDIF\r
+ENDM\r
+\r
+       ; Macro to Clear a Register to 0\r
+\r
+CLR MACRO Register\r
+       xor             Register, Register              ; Set Register = 0\r
+ENDM\r
+\r
+       ; Macros to Decrement Counter & Jump on Condition\r
+\r
+LOOPx MACRO Register, Destination\r
+       dec             Register                                ; Counter--\r
+       jnz             Destination                             ; Jump if not 0\r
+ENDM\r
+\r
+LOOPjz MACRO Register, Destination\r
+       dec             Register                                ; Counter--\r
+       jz              Destination                             ; Jump if 0\r
+ENDM\r
+\r
+\r
+       ; ==== General Constants ====\r
+\r
+       False   EQU     0\r
+       True    EQU     -1\r
+       nil             EQU 0\r
+\r
+       b               EQU     BYTE PTR\r
+       w               EQU     WORD PTR\r
+       d               EQU     DWORD PTR\r
+       o               EQU     OFFSET\r
+       f               EQU FAR PTR\r
+       s               EQU     SHORT\r
+       ?x4             EQU <?,?,?,?>\r
+       ?x3             EQU <?,?,?>\r
+\r
+\r
+IFDEF FARSTRINGS\r
+\r
+       EXTRN   stringaddress:far\r
+       EXTRN   stringlength:far\r
+\r
+ENDIF\r
+\r
+\r
+       .Data\r
+\r
+       EVEN\r
+\r
+RND_Seed       DW      7397, 29447, 802\r
+RND_Mult       DW      179, 183, 182\r
+RND_ModV       DW      32771, 32779, 32783\r
+\r
+CR_LF          DB      13, 10                  ; the CRLF data\r
+\r
+       .Code\r
+\r
+;=================\r
+;DOS_PRINT (Text$)\r
+;=================\r
+;\r
+; Prints Text Directly to DOS console w/ CR/LF\r
+;\r
+\r
+       PUBLIC  DOS_PRINT\r
+\r
+DP_Stack       STRUC\r
+                               DW      ?x4     ; DI, SI, DS, BP\r
+                               DD      ?       ; Caller\r
+       DP_Text         DW      ?       ; Address of Text$ Descriptor\r
+DP_Stack       ENDS\r
+\r
+\r
+DOS_PRINT       PROC    FAR\r
+\r
+       PUSHx   BP, DS, SI, DI          ; Preserve Important Registers\r
+       mov             BP, SP                          ; Set up Stack Frame\r
+\r
+       mov     SI, [BP].DP_Text                ; Get Addr of Text$ descriptor\r
+\r
+IFDEF FARSTRINGS\r
+       push    SI                                      ; Push Addr of BC7 Decriptor Ptr\r
+       call    stringaddress           ; Get Address + Len of string!!!\r
+                                                               ; DX:AX = Addr  CX = Len\r
+       mov             DS, DX                          ; DS = DX = Segment of string\r
+       mov             DX, AX                          ; DX = AX = Offset of String\r
+ELSE\r
+       mov     CX, [SI]                ; put its length into CX\r
+    mov     DX, [SI+02]        ; now DS:DX points to the String\r
+ENDIF\r
+\r
+       jcxz    @No_Print                       ; Don't Print if empty\r
+\r
+       mov             BX, 1                           ; 1= DOS Handle for Display\r
+       mov             AH, 40h                         ; Write Text Function\r
+       int             21h                                     ; Call DOS to do it\r
+\r
+@No_Print:\r
+       mov             AX, SEG DGROUP          ; Restore DGroup\r
+       mov             DS, AX\r
+\r
+       mov             DX, o CR_LF                     ; Get Addr of CR/LF pair\r
+       mov             CX, 2                           ; 2 Characters to Write         \r
+       mov             BX, 1                           ; 1= DOS Handle for Display\r
+\r
+       mov             AH, 40h                         ; Write Text Function\r
+       int             21h                                     ; Call DOS to do it\r
+\r
+       cld                                                     ; Reset Direction Flag          \r
+       POPx    DI, SI, DS, BP          ; Restore Saved Registers\r
+       ret             2                                       ; Exit & Clean Up Stack\r
+\r
+DOS_PRINT       ENDP\r
+\r
+\r
+;==================\r
+;DOS_PRINTS (Text$)\r
+;==================\r
+; \r
+; Print Text$ Directly to DOS console \r
+; without a trailing CR/LF\r
+;\r
+\r
+       PUBLIC  DOS_PRINTS\r
+\r
+DOS_PRINTS      PROC    FAR\r
+\r
+       PUSHx   BP, DS, SI, DI          ; Preserve Important Registers\r
+       mov             BP, SP                          ; Set up Stack Frame\r
+\r
+    mov     SI, [BP].DP_Text   ; Get Addr of Text$ descriptor\r
+\r
+IFDEF FARSTRINGS\r
+       push    SI                                      ; Push Addr of BC7 Decriptor Ptr\r
+       call    stringaddress           ; Get Address + Len of string!!!\r
+                                                               ; DX:AX = Addr  CX = Len\r
+       mov             DS, DX                          ; DS = DX = Segment of string\r
+       mov             DX, AX                          ; DX = AX = Offset of String\r
+ELSE\r
+       mov     CX, [SI]                ; put its length into CX\r
+    mov     DX, [SI+02]        ; now DS:DX points to the String\r
+ENDIF\r
+\r
+       jcxz    @DPS_Exit                       ; Don't Print if empty\r
+\r
+       mov             BX, 1                           ; 1= DOS Handle for Display\r
+       mov             AH, 40h                         ; Write Text Function\r
+       int             21h                                     ; Call DOS to do it\r
+\r
+@DPS_Exit:\r
+       cld                                                     ; Reset Direction Flag          \r
+       POPx    DI, SI, DS, BP          ; Restore Saved Registers\r
+       ret             2                                       ; Exit & Clean Up Stack\r
+\r
+DOS_PRINTS      ENDP\r
+\r
+\r
+;======================\r
+;SET_VIDEO_MODE (Mode%) \r
+;======================\r
+;\r
+; Sets the Video Mode through the BIOS\r
+;\r
+\r
+       PUBLIC  SET_VIDEO_MODE\r
+\r
+SVM_Stack      STRUC\r
+                               DW      ?x4     ; DI, SI, DS, BP\r
+                               DD      ?       ; Caller\r
+       SVM_Mode        DB      ?,? ; Desired Video Mode\r
+SVM_Stack      ENDS\r
+\r
+\r
+SET_VIDEO_MODE PROC    FAR\r
+\r
+       PUSHx   BP, DS, SI, DI          ; Preserve Important Registers\r
+       mov             BP, SP                          ; Set up Stack Frame\r
+\r
+       CLR             AH                                      ; Function 0\r
+       mov             AL, [BP].SVM_Mode       ; Get Mode #\r
+\r
+       int             10H                                     ; Change Video Modes\r
+\r
+@SVM_Exit:\r
+       POPx    DI, SI, DS, BP          ; Restore Saved Registers\r
+       ret             2                                       ; Exit & Clean Up Stack\r
+\r
+SET_VIDEO_MODE ENDP\r
+\r
+\r
+;==============\r
+;SCAN_KEYBOARD%\r
+;==============\r
+;\r
+; Function to scan keyboard for a pressed key\r
+;\r
+\r
+       PUBLIC  SCAN_KEYBOARD\r
+\r
+SCAN_KEYBOARD  PROC    FAR\r
+\r
+       PUSHx   BP, DS, SI, DI          ; Preserve Important Registers\r
+\r
+       mov             AH, 01H                         ; Function #1\r
+       int             16H                                     ; Call Keyboard Driver\r
+       jz              @SK_NO_KEY                      ; Exit if Zero flag set\r
+\r
+       mov             AH,     00H                             ; Remove Key from Buffer\r
+       int             16H                                     ; Get Keycode in AX\r
+\r
+       or              AL, AL                          ; Low Byte Set (Ascii?)\r
+       jz              @SK_Exit                        ; if not, it's a F-Key\r
+\r
+       CLR             AH                                      ; Clear ScanCode if Ascii\r
+       jmp             s @SK_Exit                      ; Return Key in AX\r
+\r
+@SK_NO_KEY:\r
+       CLR             AX                                      ; Return Nil (no Keypress)\r
+\r
+@SK_Exit:\r
+       cld                                                     ; Reset Direction Flag          \r
+       POPx    DI, SI, DS, BP          ; Restore Saved Registers\r
+       ret                                                     ; Exit & Clean Up Stack\r
+\r
+SCAN_KEYBOARD  ENDP\r
+\r
+\r
+;====================\r
+;RANDOM_INT (MaxInt%)\r
+;====================\r
+;\r
+; Returns a pseudo-random number in the range of (0.. MaxInt-1)\r
+;\r
+\r
+\r
+       PUBLIC  RANDOM_INT\r
+\r
+RI_Stack       STRUC\r
+                               DW      ?       ; BP\r
+                               DD      ?       ; Caller\r
+       RI_MaxVal       DW      ?       ; Maximum Value to Return + 1\r
+RI_Stack       ENDS\r
+\r
+\r
+RANDOM_INT     PROC    FAR\r
+\r
+       push    BP                                      ; Preserve Important Registers\r
+       mov             BP, SP                          ; Set up Stack Frame\r
+\r
+       CLR             BX                                      ; BX is the data index\r
+       CLR             CX                              ; CX is the accumulator\r
+\r
+REPT 3\r
+       mov             AX, RND_Seed[BX]        ; load the initial seed\r
+       mul             RND_Mult[BX]            ; multiply it\r
+       div             RND_ModV[BX]            ; and obtain the Mod value\r
+       mov             RND_Seed[BX], DX        ; save that for the next time\r
+\r
+       add             CX, DX                          ; add it into the accumulator\r
+       inc             BX\r
+       inc             BX                      ; point to the next set of values\r
+ENDM\r
+\r
+       mov             AX, CX                          ; AX = Random #\r
+       CLR             DX                                      ; DX = 0\r
+       div             [BP].RI_MaxVal          ; DX = DX:AX / MAxVal Remainder\r
+\r
+       mov             AX, DX\r
+\r
+       pop             BP                                      ; Restore BP\r
+       ret             2                               ; back to BASIC with AX holding the result\r
+\r
+RANDOM_INT     ENDP\r
+\r
+\r
+;===========\r
+;INIT_RANDOM\r
+;===========\r
+;\r
+; Scrambles the psuedo-random number sequence\r
+; (XOR's the seed value with the timer)\r
+;\r
+\r
+       PUBLIC  INIT_RANDOM\r
+\r
+INIT_RANDOM    PROC    FAR\r
+\r
+       clr             AX                                      ; Segment = 0000\r
+       mov             ES, AX\r
+       mov             AX, ES:[046Ch]      ; Get Timer Lo Word\r
+\r
+       xor             RND_Seed, AX            ; Scramble 1st Seed\r
+\r
+       ret                                                     ; Exit & Clean Up Stack\r
+\r
+INIT_RANDOM    ENDP\r
+\r
+\r
+;====================\r
+;INT_SQR (X%, Round%)\r
+;====================\r
+;\r
+; Returns the Integer Square Root of (X)\r
+; Round allows the return value to be rounded to the \r
+; nearest integer value by passing 0x80.  Passing 0\r
+; return the Integer Portion only.  The rounding amound is\r
+; a number from 0 to 1 multiplied by 256, thus \r
+; 0.5 * 0x100 = 0x80!\r
+;\r
+\r
+ISQ_Stack      STRUC\r
+                                       DW      ?,?     ; BP, DI\r
+                                       DD      ?       ; Caller\r
+       ISQ_Round               DW      ?       ; Amount to Round Result * 256\r
+       ISQ_X                   DW      ?       ; "X"\r
+ISQ_Stack      ENDS\r
+\r
+       PUBLIC  INT_SQR\r
+\r
+INT_SQR                PROC    FAR\r
+\r
+    PUSHx   BP, DI                             ; Save BP\r
+    mov     BP, SP                             ; Set up Stack Frame\r
+\r
+       xor     AX, AX                          ; {xor eax,eax}\r
+       xor     DX, DX                          ; {xor edx,edx}\r
+       mov     DI, [BP].ISQ_X          ; {mov edi,x}\r
+\r
+       mov     CX, 16                          ; {mov cx, 32}\r
+\r
+@ISQ_L:\r
+\r
+       shl     DI, 1                           ; {shl edi,1}\r
+       rcl     DX, 1                           ; {rcl edx,1}\r
+       shl     DI, 1                           ; {shl edi,1}\r
+       rcl     DX, 1                           ; {rcl edx,1}\r
+       shl     AX, 1                           ; {shl eax,1}\r
+       mov     BX, AX                          ; {mov ebx,eax}\r
+       shl     BX, 1                           ; {shl ebx,1}\r
+       inc     BX                                      ; {inc ebx}\r
+       cmp     DX, BX                          ; {cmp edx,ebx}\r
+       jl              @ISQ_S\r
+\r
+       sub     DX, BX                          ; {sub edx,ebx}\r
+       inc     AX                                      ; {inc eax}\r
+\r
+@ISQ_S: \r
+       loop    @ISQ_L\r
+\r
+       add     ax, [BP].ISQ_Round      ; {add eax,$00008000}  \r
+                                                               ; {*round* result in hi word: ie. +0.5}\r
+       shr     ax, 8                           ; {shr eax,16}  {to ax (result)}\r
+\r
+       POPx    DI, BP                          ; Restore Registers     \r
+       ret             4                                       ; Exit\r
+\r
+INT_SQR                ENDP\r
+\r
+\r
+;============\r
+;TIMER_COUNT&\r
+;============\r
+;\r
+; Returns the current timer value as an integer/long integer\r
+;\r
+\r
+\r
+       PUBLIC  TIMER_COUNT\r
+\r
+TIMER_COUNT      PROC    FAR\r
+\r
+       clr             AX                                      ; Segment = 0000\r
+       mov             ES, AX                          ; use ES to get at data\r
+       mov             AX, ES:[046Ch]      ; Get Timer Lo Word\r
+       mov             DX, ES:[046Eh]          ; Get Timer Hi Word\r
+       ret                                                     ; Exit & Return value in DX:AX\r
+\r
+TIMER_COUNT      ENDP\r
+\r
+\r
+       END\r
diff --git a/src/lib/modex/demos/qb45/utils.bi b/src/lib/modex/demos/qb45/utils.bi
new file mode 100755 (executable)
index 0000000..aeafeef
--- /dev/null
@@ -0,0 +1,51 @@
+\r
+       ' Misc Constants\r
+\r
+CONST True = -1, False = 0, nil = 0\r
+\r
+       ' Keyboard Codes: Extended\r
+\r
+CONST KyF1 = &H3B00, KyF2 = &H3C00, KyF3 = &H3D00, KyF4 = &H3E00, KyF5 = &H3F00\r
+CONST KyF6 = &H4000, KyF7 = &H4100, KyF8 = &H4200, KyF9 = &H4300, KyF10 = &H4400\r
+\r
+CONST KyUp = &H4800, KyLeft = &H4B00, KyRight = &H4D00, KyDown = &H5000\r
+CONST KySLeft = &HCB00, KySRight = &HCD00, KySUp = &HC800, KySDown = &HD000\r
+\r
+CONST KyHome = &H4700, KyPgUp = &H4900, KyEnd = &H4F00, KyPgDn = &H5100\r
+CONST KySHome = &HC700, KySPgUp = &HC900, KySEnd = &HCF00, KySPgDn = &HD100\r
+\r
+CONST KyIns = &H5200, KyDel = &H5300, KyRvsTab = &H8F00\r
+CONST KySIns = &HC200, KySDel = &HC300\r
+\r
+CONST KyAltA = &H1E00, KyAltB = &H3000, KyAltC = &H2E00, KyAltD = &H2000\r
+CONST KyAltE = &H1200, KyAltF = &H2100, KyAltG = &H2200, KyAltH = &H2300\r
+CONST KyAltI = &H1700, KyAltJ = &H2400, KyAltK = &H2500, KyAltL = &H2600\r
+CONST KyAltM = &H3200, KyAltN = &H3100, KyAltO = &H1800, KyAltP = &H1900\r
+CONST KyAltQ = &H1000, KyAltR = &H1300, KyAltS = &H1F00, KyAltT = &H1400\r
+CONST KyAltU = &H1600, KyAltV = &H2F00, KyAltW = &H1100, KyAltX = &H2D00\r
+CONST KyAltY = &H1500, KyAltZ = &H2C00\r
+\r
+       ' Keyboard Codes: Ascii\r
+\r
+CONST KyBS = 8, KyTab = 9, KyCR = 13, KyESC = &H1B, KyClr = &H7F\r
+CONST KyPlus = 45, KyMinus = 43\r
+\r
+       ' Color Constants\r
+\r
+CONST c.BLACK = 0, c.BLUE = 1, c.GREEN = 2, c.CYAN = 3\r
+CONST c.RED = 4, c.PURPLE = 5, c.BROWN = 6, c.WHITE = 7\r
+CONST c.GREY = 8, c.bBLUE = 9, c.bGREEN = 10, c.bCYAN = 11\r
+CONST c.bRED = 12, c.bPURPLE = 13, c.YELLOW = 14, c.bWHITE = 15\r
+CONST c.BRIGHT = 8\r
+\r
+       ' From UTILS.ASM\r
+\r
+DECLARE SUB DOS.PRINT ALIAS "DOS_PRINT" (Text$)\r
+DECLARE SUB DOS.PRINTS ALIAS "DOS_PRINTS" (Text$)\r
+DECLARE SUB SET.VIDEO.MODE ALIAS "SET_VIDEO_MODE" (BYVAL Mode%)\r
+DECLARE FUNCTION SCAN.KEYBOARD% ALIAS "SCAN_KEYBOARD"\r
+DECLARE FUNCTION RANDOM.INT ALIAS "RANDOM_INT" (BYVAL MaxInt%)\r
+DECLARE SUB INIT.RANDOM ALIAS "INIT_RANDOM"\r
+DECLARE FUNCTION TIMER.COUNT& ALIAS "TIMER_COUNT"\r
+DECLARE FUNCTION INT.SQR ALIAS "INT_SQR" (BYVAL X%, BYVAL Round%)\r
+\r
diff --git a/src/lib/modex/demos/rom_8x8.fnt b/src/lib/modex/demos/rom_8x8.fnt
new file mode 100755 (executable)
index 0000000..708a4f9
Binary files /dev/null and b/src/lib/modex/demos/rom_8x8.fnt differ
diff --git a/src/lib/modex/demos/spaceage.fnt b/src/lib/modex/demos/spaceage.fnt
new file mode 100755 (executable)
index 0000000..029bae4
Binary files /dev/null and b/src/lib/modex/demos/spaceage.fnt differ
diff --git a/src/lib/modex/demos/system.fnt b/src/lib/modex/demos/system.fnt
new file mode 100755 (executable)
index 0000000..9a1965e
Binary files /dev/null and b/src/lib/modex/demos/system.fnt differ
diff --git a/src/lib/modex/demos/test6.exe b/src/lib/modex/demos/test6.exe
new file mode 100755 (executable)
index 0000000..5682c47
Binary files /dev/null and b/src/lib/modex/demos/test6.exe differ
diff --git a/src/lib/modex/fontedit/charsets.cs b/src/lib/modex/fontedit/charsets.cs
new file mode 100755 (executable)
index 0000000..97fe608
Binary files /dev/null and b/src/lib/modex/fontedit/charsets.cs differ
diff --git a/src/lib/modex/fontedit/csedit.doc b/src/lib/modex/fontedit/csedit.doc
new file mode 100755 (executable)
index 0000000..97ff07e
--- /dev/null
@@ -0,0 +1,196 @@
+\r
+CSEDIT - A Simple Font Editor by Matt Pritchard\r
\r
\r
+CSEDIT is distributed with MODEXnnn.ZIP, the general purpose MODE X\r
+Library for VGA Graphics.\r
\r
+WHAT YOU NEED TO RUN CSEDIT:\r
\r
+    * A Vga Monitor\r
+    * A Microsoft Compatible Mouse\r
\r
+    A Mouse is most definitely required, as the keyboard is used for\r
+    nothing except entering file names.\r
\r
+FILES NEEDED IN THE CURRENT DIRECTORY:\r
\r
+    CSEDIT.EXE  - The Font Editor Program\r
+    CHARSETS.CS - The Font Editor's Internal Fonts\r
+    PALETTE.CS  - The Font Editor's Palette\r
+    MOUSEIMG.CS - The Font Editor's Mouse Pointer\r
\r
+SAMPLE FONT FILE THAT SHOULD BE INCLUDED:\r
\r
+    SYSTEM.FNT   - The Font used by CSEDIT.EXE\r
+    INVERSE.FNT  - An Inverted version of SYSTEM.FNT\r
+    SPACEAGE.FNT - A Futuristic, Tech style font\r
+    ROM_8X8.FNT  - The Lower 128 characters from the VGA BIOS Rom\r
\r
+WHAT IT EDITS:\r
\r
+    8 by 8 character fonts, 128 characters at a time. 2 fonts at a time.\r
\r
+HOW IT WORKS/FEATURES:\r
\r
+    CSEDIT allows the user to edit 2 different font groups at a time,\r
+    which may be loaded and saved separately.\r
\r
+    A enlarged character grid allows the user to edit individual pixels\r
+    on a selected character.\r
\r
+    The Following operations can be performed on a single character or\r
+    simultaneously on a selected block of characters.\r
\r
+       * Shift the selected character(s) in any direction\r
+         with or without clipping at the edges.\r
+       * Vertically Flip the selected character(s)\r
+       * Horizontally Flip the selected character(s)\r
+       * Rotate the selected character(s) 90 Degrees Clockwise\r
+       * Rotate the selected character(s) 90 Degrees Counterclockwise\r
+       * Clear the selected character(s)\r
+       * Invert the selected character(s)\r
+       * XOR the selected character(s) with other character(s)\r
+       * AND the selected character(s) with other character(s)\r
+       * OR the selected character(s) with other character(s)\r
+       * Copy the selected character(s) to another position or font.\r
\r
+    An UNDO feature allows the reversal of the most recent operation.\r
\r
+DESCRIPTION OF OBJECTS/FEATURES FROM THE TOP DOWN:\r
\r
+    Character Grid:  (RED) Box in Upper Left corner of screen.  This is\r
+        where you edit an individual character. The Left Button sets the\r
+        pixel the mouse pointer is on, while the Right Button clears that\r
+        pixel.\r
\r
+    Scroll Buttons:  The Four Scroll Buttons are labeled with directional\r
+        arrows, and arranged in a diamond pattern.  Left Clicking on a\r
+        directional button will scroll the currently selected character\r
+        in that direction, with the pixels on the edge rolling off and\r
+        appearing on the other size.  Right Clicking will prevent the\r
+        pixels from rolling to the other side.\r
\r
+    Vertical Flip Button:\r
+    Horizontal Flip Button:  Clicking these buttons will flip the pattern\r
+        of the currently selected character(s) around the indicated axis.\r
+        i.e. the top row will be swapped with the bottom row, etc. or the\r
+        left row column will be swapped with right column, etc.\r
+        depending upon which button you push.\r
\r
+    Invert Button:  Clicking this button causes all pixels in the selected\r
+        character(s) to flip flop between on and off.\r
\r
+    Clear Button: Clicking this button erases the selected characters\r
\r
+    Rotate Buttons: Clicking these buttons will rotate the pattern in the\r
+        selected character(s) 90 degrees in the indicated direction.\r
\r
+    XOR Button: Clicking this button will let you XOR the currently\r
+        selected character(s) with other character(s) in either font.\r
+        The Button will turn RED, indicating that it is waiting for\r
+        you to click on the desired character (or upper left corner\r
+        of the desired block of characters) in either the Red or Green\r
+        Character Set Displays.  Clicking anywhere else will abort this\r
+        process without doing anything.  If you click on (any of) the\r
+        selected character(s) the operation is aborted.  If a block is\r
+        selected and the character you click on is in a position where\r
+        it can't represent the upper left corner of a block of the same\r
+        size, then the operation is not performed.\r
\r
+    AND Button & OR Button:  These buttons work just like the XOR Button\r
+        except that the Binary operation performed is either an AND or OR\r
+        depending upon which button you have selected.\r
\r
+    COPY Button: This button lets you copy a character or selected block\r
+        of characters to another area in the current font or the other\r
+        font.  After clicking, the button turns RED and works much like\r
+        the XOR Button.  Clicking on a valid position in either font\r
+        window will copy the selected character(s) to that location.\r
\r
+    MODE Button: Clicking this button toggles the editor between BLOCK\r
+        mode and CHARACTER mode.  The current mode is displayed on a plate\r
+        at the top of the screen, just to the right of the enlarged\r
+        character grid.  In character mode the plate will read "CHAR" and\r
+        the currently selected character is displayed just to the right\r
+        of the plate.  In Block mode the plate will read "BLOCK" and the\r
+        enlarged character grid is disabled.\r
\r
+    UNDO Button: Clicking this Button will UNDO or reverse the effects of\r
+        the most recent operation.\r
\r
+    QUIT Button: Clicking this button will return you to DOS.  Any loaded\r
+        fonts are not saved, and no confirmation is given.\r
\r
\r
+    GREEN FONT AREA:  This area displays one of the current fonts which\r
+        can be edited.  The characters are display in order from #0 to #127\r
+        from the upper left, going right, then down.  The Font Box is 32\r
+        characters wide and 4 characters Tall.  When the editor is in\r
+        character mode, just point at and Left Click on the character you\r
+        wish to edit and a Cyan box will appear around that character.\r
+\r
+      * If you Right Click on a character, the last current character,\r
+        which will still appear in the enlarged character grid, will be\r
+        copied onto the character you pointed at, replacing it.  This is\r
+        a shortcut for copying characters: You can hold the right button\r
+        down an fill in a large area with a single character pattern.\r
+        When the editor is in Block Mode, you select an area by clicking\r
+        on any corner of the desired block.  Then drag the mouse to the\r
+        opposite corner while holding down the left button.  A Cyan Box\r
+        will stretch to surround the selected block of characters.\r
\r
+    GREEN FONT FILE NAME BOX:  This Text Box is used to enter the name\r
+        of a font file to load or the name to save the current Green font\r
+        as.  Just click on the Box, and it will change color and a\r
+        flashing cursor will appear.  Now you type in a filename or edit\r
+        the existing filename.  Press <RETURN> or click outside the text\r
+        box to end editing.\r
\r
+    GREEN FONT LOAD BUTTON:  Clicking this button will load the font file\r
+        that is named in the Green File name box.  If no name is given or\r
+        no such file exists, then nothing will be loaded.\r
\r
+    GREEN FONT SAVE BUTTON:  Clicking this button will save the current\r
+        font in the Green Font Area under the name given in the File Name\r
+        Box.  If a Valid name is not provided, nothing will be saved.\r
\r
+    RED FONT AREA:  This is just the same as the GREEN FONT AREA; providing\r
+        you with the ability to copy and edit between multiple fonts.\r
\r
+    RED FONT FILE NAME BOX:  This works just like the GREEN FONT FILE\r
+        NAME BOX.\r
\r
+    RED FONT LOAD BUTTON:  This works just like the GREEN FONT LOAD BUTTON.\r
\r
+    RED FONT SAVE BUTTON:  This works just like the GREEN FONT SAVE BUTTON.\r
\r
+    Message Bar:  At the very bottom of the screen, this Bar will display\r
+        information and messages for various functions.\r
\r
\r
+FONT FILE FORMAT:\r
\r
+    BINARY Image, in order of character.  The format is identical to that\r
+    used by the VGA ROM.  The Files will be exactly 1024 (128 * 8) bytes\r
+    long.\r
\r
+    CHARACTER: 8 Bytes\r
\r
+    FONT: Array (0 to 127) of CHARACTER\r
\r
\r
+COMMENTS, QUESTIONS, BUG REPORTS, etc:\r
\r
+    Send the to the Author:  Matt Pritchard\r
\r
+    Through the 80xxx Fidonet Echo or\r
\r
+    Matt Pritchard\r
+    P.O. Box 140264\r
+    Irving, TX  75014\r
\r
+CREDITS:\r
\r
+    This Font Editor was written in QuickBASIC 4.5\r
\r
diff --git a/src/lib/modex/fontedit/csedit.exe b/src/lib/modex/fontedit/csedit.exe
new file mode 100755 (executable)
index 0000000..58b0732
Binary files /dev/null and b/src/lib/modex/fontedit/csedit.exe differ
diff --git a/src/lib/modex/fontedit/inverse.fnt b/src/lib/modex/fontedit/inverse.fnt
new file mode 100755 (executable)
index 0000000..5901c51
Binary files /dev/null and b/src/lib/modex/fontedit/inverse.fnt differ
diff --git a/src/lib/modex/fontedit/mouseimg.cs b/src/lib/modex/fontedit/mouseimg.cs
new file mode 100755 (executable)
index 0000000..101e208
Binary files /dev/null and b/src/lib/modex/fontedit/mouseimg.cs differ
diff --git a/src/lib/modex/fontedit/palette.cs b/src/lib/modex/fontedit/palette.cs
new file mode 100755 (executable)
index 0000000..09c5549
Binary files /dev/null and b/src/lib/modex/fontedit/palette.cs differ
diff --git a/src/lib/modex/fontedit/rom_8x8.fnt b/src/lib/modex/fontedit/rom_8x8.fnt
new file mode 100755 (executable)
index 0000000..708a4f9
Binary files /dev/null and b/src/lib/modex/fontedit/rom_8x8.fnt differ
diff --git a/src/lib/modex/fontedit/spaceage.fnt b/src/lib/modex/fontedit/spaceage.fnt
new file mode 100755 (executable)
index 0000000..029bae4
Binary files /dev/null and b/src/lib/modex/fontedit/spaceage.fnt differ
diff --git a/src/lib/modex/fontedit/system.fnt b/src/lib/modex/fontedit/system.fnt
new file mode 100755 (executable)
index 0000000..9a1965e
Binary files /dev/null and b/src/lib/modex/fontedit/system.fnt differ
diff --git a/src/lib/modex/makefile b/src/lib/modex/makefile
new file mode 100755 (executable)
index 0000000..fdf9d91
--- /dev/null
@@ -0,0 +1,30 @@
+!ifdef __LINUX__
+REMOVECOMMAND=rm -f
+COPYCOMMAND=cp -f
+DIRSEP=/
+OBJ=o
+!else
+REMOVECOMMAND=del
+COPYCOMMAND=copy /y
+DIRSEP=\
+OBJ=obj
+!endif
+
+CFLAGS=-d2 -0 -mc
+
+all: x_demo.exe
+
+x_demo.exe: x_demo.$(OBJ) modex.$(OBJ) c_utils.$(OBJ)
+       wcl $(CFLAGS) x_demo.$(OBJ) modex.$(OBJ) c_utils.$(OBJ)
+x_demo.$(OBJ): x_demo.c
+       wcl -c $(CFLAGS) x_demo.c
+
+c_utils.$(OBJ): c_utils.asm
+       wcl -c $(CFLAGS) c_utils.asm
+modex.$(OBJ): modex.asm
+       wcl -c $(CFLAGS) modex.asm
+
+clean: .symbolic
+       @$(REMOVECOMMAND) x-demo.exe
+       @$(REMOVECOMMAND) *.$(OBJ)
+       @$(REMOVECOMMAND) *.err
diff --git a/src/lib/modex/mode-x.txt b/src/lib/modex/mode-x.txt
new file mode 100755 (executable)
index 0000000..4e18d96
--- /dev/null
@@ -0,0 +1,44 @@
+The following is a FAQ (Frequently Asked Question) summary of \r
+information and assembly routines for Mode "X" Graphics.\r
+\r
+An overview of Mode "X" for the VGA Adaptor:\r
+\r
+1) Mode "X" is a 256 color graphics mode that is available on *ANY* VGA\r
+card with the minimum of 256K video RAM.  It is capable of providing\r
+higher resoultions than the only "Official" 256 color mode, mode 13h.\r
+(In quickbasic that is mode 13)\r
+\r
+2) Mode "X" comes in 8 different flavors: 320 or 360 pixels\r
+horizontally, and 200, 240, 400, and 480 pixels vertically.\r
+\r
+3) Since mode X is not supported by the VGA BIOS, there is no built in\r
+support for it.  A program must provide its own routines for *ALL*\r
+operations in Mode "X", including setting up the video mode.\r
+\r
+4) Unlike Mode 13h, which has one display page, Mode "X" allows from 1\r
+to 4 video pages, depending upon the resoultion selected.  The reason\r
+that Mode 13h has but one page is that it activates a VGA hardware\r
+feature known as CHAIN4, which prevents access to all but 64K of VGA's\r
+video RAM.  CHAIN4 is what provides mode 13h's linear addres space.\r
+\r
+5) Unlike Mode 13h, where each 256 color (1-byte) pixel has a unique\r
+address in the E000: segement, in Mode X there are Four (4) Pixels\r
+at each address in E000: segment.  The VGA's control registers allow you\r
+to control which of the 4 pixels is currently available at an address.\r
+\r
+6) It is possible to use the VGA's control registers to operate on 2 or\r
+more of the Pixels at the same address at the same time.  The CPU can\r
+write one color value, and set up to 4 pixels with that value at the\r
+same time.\r
+\r
+7) Video RAM that is not being used for the current screen display can\r
+be used to store images and patterns.  These images and patterns can be\r
+copied to other parts of the Video RAM 4 bytes (32 bits) at a time,\r
+which is much faster than the 8 bits (1 byte) at time that is possible\r
+over the ISA BUS.  (16 Bit BUS operations can produce erroneous results)\r
+\r
+If anything is unclear, inadequate, or you just plain want to know more \r
+or have other specific questions, please send me a message.\r
+\r
+\r
+-Matt Pritchard\r
diff --git a/src/lib/modex/modex.asm b/src/lib/modex/modex.asm
new file mode 100755 (executable)
index 0000000..f2b1b51
--- /dev/null
@@ -0,0 +1,3505 @@
+;========================================================\r
+; MODEX.ASM - A Complete Mode X Library\r
+;\r
+; Version 1.04 Release, 3 May 1993, By Matt Pritchard\r
+; With considerable input from Michael Abrash\r
+;\r
+; The following information is donated to the public domain in\r
+; the hopes that save other programmers much frustration.\r
+;\r
+; If you do use this code in a product, it would be nice if\r
+; you include a line like "Mode X routines by Matt Pritchard"\r
+; in the credits.\r
+;\r
+; =========================================================\r
+;\r
+; All of this code is designed to be assembled with MASM 5.10a\r
+; but TASM 3.0 could be used as well.\r
+;\r
+; The routines contained are designed for use in a MEDIUM model\r
+; program.  All Routines are FAR, and is assumed that a DGROUP\r
+; data segment exists and that DS will point to it on entry.\r
+;\r
+; For all routines, the AX, BX, CX, DX, ES and FLAGS registers\r
+; will not be preserved, while the DS, BP, SI and DI registers\r
+; will be preserved.\r
+;\r
+; Unless specifically noted, All Parameters are assumed to be\r
+; "PASSED BY VALUE".  That is, the actual value is placed on\r
+; the stack.  When a reference is passed it is assumed to be\r
+; a near pointer to a variable in the DGROUP segment.\r
+;\r
+; Routines that return a single 16-Bit integer value will\r
+; return that value in the AX register.\r
+;\r
+; This code will *NOT* run on an 8086/8088 because 80286+\r
+; specific instructions are used.   If you have an 8088/86\r
+; and VGA, you can buy an 80386-40 motherboard for about\r
+; $160 and move into the 90's.\r
+;\r
+; This code is reasonably optimized: Most drawing loops have\r
+; been unrolled once and memory references are minimized by\r
+; keeping stuff in registers when possible.\r
+;\r
+; Error Trapping varies by Routine.  No Clipping is performed\r
+; so the caller should verify that all coordinates are valid.\r
+;\r
+; Several Macros are used to simplify common 2 or 3 instruction\r
+; sequences.  Several Single letter Text Constants also\r
+; simplify common assembler expressions like "WORD PTR".\r
+;\r
+; ------------------ Mode X Variations ------------------\r
+;\r
+;  Mode #  Screen Size    Max Pages   Aspect Ratio (X:Y)\r
+;\r
+;    0      320 x 200      4 Pages         1.2:1\r
+;    1      320 x 400      2 Pages         2.4:1\r
+;    2      360 x 200      3 Pages        1.35:1\r
+;    3      360 x 400      1 Page          2.7:1\r
+;    4      320 x 240      3 Pages           1:1\r
+;    5      320 x 480      1 Page            2:1\r
+;    6      360 x 240      3 Pages       1.125:1\r
+;    7      360 x 480      1 Page         2.25:1\r
+;\r
+; -------------------- The Legal Stuff ------------------\r
+;\r
+; No warranty, either written or implied, is made as to\r
+; the accuracy and usability of this code product.  Use\r
+; at your own risk.  Batteries not included.  Pepperoni\r
+; and extra cheese available for an additional charge.\r
+;\r
+; ----------------------- The Author --------------------\r
+;\r
+; Matt Pritchard is a paid programmer who'd rather be\r
+; writing games.  He can be reached at: P.O. Box 140264,\r
+; Irving, TX  75014  USA.  Michael Abrash is a living\r
+; god, who now works for Bill Gates (Microsoft).\r
+;\r
+; -------------------- Revision History -----------------\r
+; 4-12-93: v1.02 - SET_POINT & READ_POINT now saves DI\r
+;          SET_MODEX now saves SI\r
+; 5-3-93:  v1.04 - added LOAD_DAC_REGISTERS and\r
+;          READ_DAC_REGISTERS.  Expanded CLR Macro\r
+;          to handle multiple registers\r
+;\r
+\r
+    PAGE    255, 132\r
+\r
+    .MODEL Huge\r
+    ;.286\r
+\r
+    ; ===== MACROS =====\r
+\r
+    ; Macro to OUT a 16 bit value to an I/O port\r
+\r
+OUT_16 MACRO Register, Value\r
+    IFDIFI <Register>, <DX>         ; If DX not setup\r
+        MOV     DX, Register        ; then Select Register\r
+    ENDIF\r
+    IFDIFI <Value>, <AX>            ; If AX not setup\r
+        MOV     AX, Value           ; then Get Data Value\r
+    ENDIF\r
+        OUT     DX, AX              ; Set I/O Register(s)\r
+ENDM\r
+\r
+    ; Macro to OUT a 8 bit value to an I/O Port\r
+\r
+OUT_8 MACRO Register, Value\r
+    IFDIFI <Register>, <DX>         ; If DX not setup\r
+        MOV     DX, Register        ; then Select Register\r
+    ENDIF\r
+    IFDIFI <Value>, <AL>            ; If AL not Setup\r
+        MOV     AL, Value           ; then Get Data Value\r
+    ENDIF\r
+        OUT     DX, AL              ; Set I/O Register\r
+ENDM\r
+\r
+    ; macros to PUSH and POP multiple registers\r
+\r
+; PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+;     IFNB <R1>\r
+;         PUSH    R1              ; Save R1\r
+;         PUSHx   R2, R3, R4, R5, R6, R7, R8\r
+;     ENDIF\r
+; ENDM\r
+;\r
+; POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+;     IFNB <R1>\r
+;         POP     R1              ; Restore R1\r
+;         POPx    R2, R3, R4, R5, R6, R7, R8\r
+;     ENDIF\r
+; ENDM\r
+\r
+    ; Macro to Clear Registers to 0\r
+\r
+; CLR MACRO Register, R2, R3, R4;, R5, R6\r
+;     IFNB <Register>\r
+;         XOR     Register, Register      ; Set Register = 0\r
+;         CLR R2, R3, R4;, R5, R6\r
+;     ENDIF\r
+; ENDM\r
+\r
+    ; Macros to Decrement Counter & Jump on Condition\r
+\r
+LOOPx MACRO Register, Destination\r
+    DEC     Register                ; Counter--\r
+    JNZ     Destination             ; Jump if not 0\r
+ENDM\r
+\r
+LOOPjz MACRO Register, Destination\r
+    DEC     Register                ; Counter--\r
+    JZ      Destination             ; Jump if 0\r
+ENDM\r
+\r
+\r
+    ; ===== General Constants =====\r
+\r
+    False   EQU 0\r
+    True    EQU -1\r
+    nil     EQU 0\r
+\r
+    b       EQU BYTE PTR\r
+    w       EQU WORD PTR\r
+    d       EQU DWORD PTR\r
+    o       EQU OFFSET\r
+    f       EQU FAR PTR\r
+    s       EQU SHORT\r
+    ?x1     EQU <?>\r
+\r
+    ; ===== VGA Register Values =====\r
+\r
+    VGA_Segment     EQU 0A000h  ; Vga Memory Segment\r
+\r
+    ATTRIB_Ctrl     EQU 03C0h   ; VGA Attribute Controller\r
+    GC_Index        EQU 03CEh   ; VGA Graphics Controller\r
+    SC_Index        EQU 03C4h   ; VGA Sequencer Controller\r
+    SC_Data         EQU 03C5h   ; VGA Sequencer Data Port\r
+    CRTC_Index      EQU 03D4h   ; VGA CRT Controller\r
+    CRTC_Data       EQU 03D5h   ; VGA CRT Controller Data\r
+    MISC_OUTPUT     EQU 03C2h   ; VGA Misc Register\r
+    INPUT_1         EQU 03DAh   ; Input Status #1 Register\r
+\r
+    DAC_WRITE_ADDR  EQU 03C8h   ; VGA DAC Write Addr Register\r
+    DAC_READ_ADDR   EQU 03C7h   ; VGA DAC Read Addr Register\r
+    PEL_DATA_REG    EQU 03C9h   ; VGA DAC/PEL data Register R/W\r
+\r
+    PIXEL_PAN_REG   EQU 033h    ; Attrib Index: Pixel Pan Reg\r
+    MAP_MASK        EQU 002h    ; Sequ Index: Write Map Mask reg\r
+    READ_MAP        EQU 004h    ; GC Index: Read Map Register\r
+    START_DISP_HI   EQU 00Ch    ; CRTC Index: Display Start Hi\r
+    START_DISP_LO   EQU 00Dh    ; CRTC Index: Display Start Lo\r
+\r
+    MAP_MASK_PLANE1 EQU 00102h  ; Map Register + Plane 1\r
+    MAP_MASK_PLANE2 EQU 01102h  ; Map Register + Plane 1\r
+    ALL_PLANES_ON   EQU 00F02h  ; Map Register + All Bit Planes\r
+\r
+    CHAIN4_OFF      EQU 00604h  ; Chain 4 mode Off\r
+    ASYNC_RESET     EQU 00100h  ; (A)synchronous Reset\r
+    SEQU_RESTART    EQU 00300h  ; Sequencer Restart\r
+\r
+    LATCHES_ON      EQU 00008h  ; Bit Mask + Data from Latches\r
+    LATCHES_OFF     EQU 0FF08h  ; Bit Mask + Data from CPU\r
+\r
+    VERT_RETRACE    EQU 08h     ; INPUT_1: Vertical Retrace Bit\r
+    PLANE_BITS      EQU 03h     ; Bits 0-1 of Xpos = Plane #\r
+    ALL_PLANES      EQU 0Fh     ; All Bit Planes Selected\r
+    CHAR_BITS       EQU 0Fh     ; Bits 0-3 of Character Data\r
+\r
+    GET_CHAR_PTR    EQU 01130h  ; VGA BIOS Func: Get Char Set\r
+    ROM_8x8_Lo      EQU 03h     ; ROM 8x8 Char Set Lo Pointer\r
+    ROM_8x8_Hi      EQU 04h     ; ROM 8x8 Char Set Hi Pointer\r
+\r
+    ; Constants Specific for these routines\r
+\r
+    NUM_MODES       EQU 8       ; # of Mode X Variations\r
+\r
+    ; Specific Mode Data Table format...\r
+\r
+Mode_Data_Table STRUC\r
+    M_MiscR         DB  ?       ; Value of MISC_OUTPUT register\r
+    M_Pages         DB  ?       ; Maximum Possible # of pages\r
+    M_XSize         DW  ?       ; X Size Displayed on screen\r
+    M_YSize         DW  ?       ; Y Size Displayed on screen\r
+    M_XMax          DW  ?       ; Maximum Possible X Size\r
+    M_YMax          DW  ?       ; Maximum Possible Y Size\r
+    M_CRTC          DW  ?       ; Table of CRTC register values\r
+Mode_Data_Table ENDS\r
+\r
+    ; ===== DGROUP STORAGE NEEDED (42 BYTES) =====\r
+\r
+    .DATA?\r
+\r
+SCREEN_WIDTH    DW  0       ; Width of a line in Bytes\r
+SCREEN_HEIGHT   DW  0       ; Vertical Height in Pixels\r
+\r
+LAST_PAGE       DW  0       ; # of Display Pages\r
+PAGE_ADDR       DW  4 DUP (0)   ; Offsets to start of each page\r
+\r
+PAGE_SIZE       DW  0       ; Size of Page in Addr Bytes\r
+\r
+DISPLAY_PAGE    DW  0       ; Page # currently displayed\r
+ACTIVE_PAGE     DW  0       ; Page # currently active\r
+\r
+CURRENT_PAGE    DW  0       ; Offset of current Page\r
+CURRENT_SEGMENT DW  0       ; Segment of VGA memory\r
+\r
+CURRENT_XOFFSET DW  0       ; Current Display X Offset\r
+CURRENT_YOFFSET DW  0       ; Current Display Y Offset\r
+\r
+CURRENT_MOFFSET DW  0       ; Current Start Offset\r
+\r
+MAX_XOFFSET     DW  0       ; Current Display X Offset\r
+MAX_YOFFSET     DW  0       ; Current Display Y Offset\r
+\r
+CHARSET_LOW     DW  0, 0    ; Far Ptr to Char Set: 0-127\r
+CHARSET_HI      DW  0, 0    ; Far Ptr to Char Set: 128-255\r
+\r
+    .CODE\r
+\r
+    ; ===== DATA TABLES =====\r
+\r
+    ; Data Tables, Put in Code Segment for Easy Access\r
+    ; (Like when all the other Segment Registers are in\r
+    ; use!!) and reduced DGROUP requirements...\r
+\r
+    ; Bit Mask Tables for Left/Right/Character Masks\r
+\r
+Left_Clip_Mask      DB  0FH, 0EH, 0CH, 08H\r
+\r
+Right_Clip_Mask     DB  01H, 03H, 07H, 0FH\r
+\r
+    ; Bit Patterns for converting character fonts\r
+\r
+Char_Plane_Data     DB  00H,08H,04H,0CH,02H,0AH,06H,0EH\r
+                    DB  01H,09H,05H,0DH,03H,0BH,07H,0FH\r
+\r
+        ; CRTC Register Values for Various Configurations\r
+\r
+MODE_Single_Line:       ; CRTC Setup Data for 400/480 Line modes\r
+        DW  04009H      ; Cell Height (1 Scan Line)\r
+        DW  00014H      ; Dword Mode off\r
+        DW  0E317H      ; turn on Byte Mode\r
+        DW  nil         ; End of CRTC Data for 400/480 Line Mode\r
+\r
+MODE_Double_Line:       ; CRTC Setup Data for 200/240 Line modes\r
+        DW  04109H      ; Cell Height (2 Scan Lines)\r
+        DW  00014H      ; Dword Mode off\r
+        DW  0E317H      ; turn on Byte Mode\r
+        DW  nil         ; End of CRTC Data for 200/240 Line Mode\r
+\r
+MODE_320_Wide:          ; CRTC Setup Data for 320 Horz Pixels\r
+        DW  05F00H      ; Horz total\r
+        DW  04F01H      ; Horz Displayed\r
+        DW  05002H      ; Start Horz Blanking\r
+        DW  08203H      ; End Horz Blanking\r
+        DW  05404H      ; Start H Sync\r
+        DW  08005H      ; End H Sync\r
+        DW  nil         ; End of CRTC Data for 320 Horz pixels\r
+\r
+MODE_360_Wide:          ; CRTC Setup Data for 360 Horz Pixels\r
+        DW  06B00H      ; Horz total\r
+        DW  05901H      ; Horz Displayed\r
+        DW  05A02H      ; Start Horz Blanking\r
+        DW  08E03H      ; End Horz Blanking\r
+        DW  05E04H      ; Start H Sync\r
+        DW  08A05H      ; End H Sync\r
+        DW  nil         ; End of CRTC Data for 360 Horz pixels\r
+\r
+MODE_200_Tall:\r
+MODE_400_Tall:          ; CRTC Setup Data for 200/400 Line modes\r
+        DW  0BF06H      ; Vertical Total\r
+        DW  01F07H      ; Overflow\r
+        DW  09C10H      ; V Sync Start\r
+        DW  08E11H      ; V Sync End/Prot Cr0 Cr7\r
+        DW  08F12H      ; Vertical Displayed\r
+        DW  09615H      ; V Blank Start\r
+        DW  0B916H      ; V Blank End\r
+        DW  nil         ; End of CRTC Data for 200/400 Lines\r
+\r
+MODE_240_Tall:\r
+MODE_480_Tall:          ; CRTC Setup Data for 240/480 Line modes\r
+        DW  00D06H      ; Vertical Total\r
+        DW  03E07H      ; Overflow\r
+        DW  0EA10H      ; V Sync Start\r
+        DW  08C11H      ; V Sync End/Prot Cr0 Cr7\r
+        DW  0DF12H      ; Vertical Displayed\r
+        DW  0E715H      ; V Blank Start\r
+        DW  00616H      ; V Blank End\r
+        DW  nil         ; End of CRTC Data for 240/480 Lines\r
+\r
+        ; Table of Display Mode Tables\r
+\r
+MODE_TABLE:\r
+        DW  o MODE_320x200, o MODE_320x400\r
+        DW  o MODE_360x200, o MODE_360x400\r
+        DW  o MODE_320x240, o MODE_320x480\r
+        DW  o MODE_360x240, o MODE_360x480\r
+\r
+        ; Table of Display Mode Components\r
+\r
+MODE_320x200:           ; Data for 320 by 200 Pixels\r
+\r
+        DB  063h        ; 400 scan Lines & 25 Mhz Clock\r
+        DB  4           ; Maximum of 4 Pages\r
+        DW  320, 200    ; Displayed Pixels (X,Y)\r
+        DW  1302, 816   ; Max Possible X and Y Sizes\r
+\r
+        DW  o MODE_320_Wide, o MODE_200_Tall\r
+        DW  o MODE_Double_Line, nil\r
+\r
+MODE_320x400:           ; Data for 320 by 400 Pixels\r
+\r
+        DB  063h        ; 400 scan Lines & 25 Mhz Clock\r
+        DB  2           ; Maximum of 2 Pages\r
+        DW  320, 400    ; Displayed Pixels X,Y\r
+        DW  648, 816    ; Max Possible X and Y Sizes\r
+\r
+        DW  o MODE_320_Wide, o MODE_400_Tall\r
+        DW  o MODE_Single_Line, nil\r
+\r
+MODE_360x240:           ; Data for 360 by 240 Pixels\r
+\r
+        DB  0E7h        ; 480 scan Lines & 28 Mhz Clock\r
+        DB  3           ; Maximum of 3 Pages\r
+        DW  360, 240    ; Displayed Pixels X,Y\r
+        DW  1092, 728   ; Max Possible X and Y Sizes\r
+\r
+        DW  o MODE_360_Wide, o MODE_240_Tall\r
+        DW  o MODE_Double_Line , nil\r
+\r
+MODE_360x480:           ; Data for 360 by 480 Pixels\r
+\r
+        DB  0E7h        ; 480 scan Lines & 28 Mhz Clock\r
+        DB  1           ; Only 1 Page Possible\r
+        DW  360, 480    ; Displayed Pixels X,Y\r
+        DW  544, 728    ; Max Possible X and Y Sizes\r
+\r
+        DW  o MODE_360_Wide, o MODE_480_Tall\r
+        DW  o MODE_Single_Line , nil\r
+\r
+MODE_320x240:           ; Data for 320 by 240 Pixels\r
+\r
+        DB  0E3h        ; 480 scan Lines & 25 Mhz Clock\r
+        DB  3           ; Maximum of 3 Pages\r
+        DW  320, 240    ; Displayed Pixels X,Y\r
+        DW  1088, 818   ; Max Possible X and Y Sizes\r
+\r
+        DW  o MODE_320_Wide, o MODE_240_Tall\r
+        DW  o MODE_Double_Line, nil\r
+\r
+MODE_320x480:           ; Data for 320 by 480 Pixels\r
+\r
+        DB  0E3h        ; 480 scan Lines & 25 Mhz Clock\r
+        DB  1           ; Only 1 Page Possible\r
+        DW  320, 480    ; Displayed Pixels X,Y\r
+        DW  540, 818    ; Max Possible X and Y Sizes\r
+\r
+        DW  o MODE_320_WIDE, o MODE_480_Tall\r
+        DW  o MODE_Single_Line, nil\r
+\r
+MODE_360x200:           ; Data for 360 by 200 Pixels\r
+\r
+        DB  067h        ; 400 scan Lines & 28 Mhz Clock\r
+        DB  3           ; Maximum of 3 Pages\r
+        DW  360, 200    ; Displayed Pixels (X,Y)\r
+        DW  1302, 728   ; Max Possible X and Y Sizes\r
+\r
+        DW  o MODE_360_Wide, MODE_200_Tall\r
+        DW  o MODE_Double_Line, nil\r
+\r
+MODE_360x400:           ; Data for 360 by 400 Pixels\r
+\r
+        DB  067h        ; 400 scan Lines & 28 Mhz Clock\r
+        DB  1           ; Maximum of 1 Pages\r
+        DW  360, 400    ; Displayed Pixels X,Y\r
+        DW  648, 816    ; Max Possible X and Y Sizes\r
+\r
+        DW  o MODE_360_Wide, MODE_400_Tall\r
+        DW  o MODE_Single_Line, nil\r
+\r
+\r
+    ; ===== MODE X SETUP ROUTINES =====\r
+\r
+;======================================================\r
+;SET_VGA_MODEX% (ModeType%, MaxXPos%, MaxYpos%, Pages%)\r
+;======================================================\r
+;\r
+; Sets Up the specified version of Mode X.  Allows for\r
+; the setup of multiple video pages, and a virtual\r
+; screen which can be larger than the displayed screen\r
+; (which can then be scrolled a pixel at a time)\r
+;\r
+; ENTRY: ModeType = Desired Screen Resolution (0-7)\r
+;\r
+;     0 =  320 x 200, 4 Pages max,   1.2:1 Aspect Ratio\r
+;     1 =  320 x 400, 2 Pages max,   2.4:1 Aspect Ratio\r
+;     2 =  360 x 200, 3 Pages max,  1.35:1 Aspect Ratio\r
+;     3 =  360 x 400, 1 Page  max,   2.7:1 Aspect Ratio\r
+;     4 =  320 x 240, 3 Pages max,     1:1 Aspect Ratio\r
+;     5 =  320 x 480, 1 Page  max,     2:1 Aspect Ratio\r
+;     6 =  360 x 240, 3 Pages max, 1.125:1 Aspect Ratio\r
+;     7 =  360 x 480, 1 Page  max,  2.25:1 Aspect Ratio\r
+;\r
+;        MaxXpos = The Desired Virtual Screen Width\r
+;        MaxYpos = The Desired Virtual Screen Height\r
+;        Pages   = The Desired # of Video Pages\r
+;\r
+; EXIT:  AX = Success Flag:   >0 = Failure / 0 = Success\r
+;\r
+\r
+SVM_STACK   STRUC\r
+    SVM_Table   DW  ?   ; Offset of Mode Info Table\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DD  ?   ; Caller\r
+    SVM_Pages   DW  ?   ; # of Screen Pages desired\r
+    SVM_Ysize   DW  ?   ; Vertical Screen Size Desired\r
+    SVM_Xsize   DW  ?   ; Horizontal Screen Size Desired\r
+    SVM_Mode    DW  ?   ; Display Resolution Desired\r
+SVM_STACK   ENDS\r
+\r
+    PUBLIC  SET_VGA_MODEX\r
+\r
+SET_VGA_MODEX   PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+       push    di\r
+    SUB     SP, 2               ; Allocate workspace\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    ; Check Legality of Mode Request....\r
+\r
+    MOV     BX, [BP].SVM_Mode   ; Get Requested Mode #\r
+    CMP     BX, NUM_MODES       ; Is it 0..7?\r
+    JAE     @SVM_BadModeSetup1   ; If Not, Error out\r
+\r
+    SHL     BX, 1                   ; Scale BX\r
+    MOV     SI, w MODE_TABLE[BX]    ; CS:SI -> Mode Info\r
+    MOV     [BP].SVM_Table, SI      ; Save ptr for later use\r
+\r
+    ; Check # of Requested Display Pages\r
+\r
+    MOV     CX, [BP].SVM_Pages  ; Get # of Requested Pages\r
+    ;CLR       CH                  ; Set Hi Word = 0!\r
+    mov        ch,0                  ; Set Hi Word = 0!\r
+    CMP     CL, CS:[SI].M_Pages ; Check # Pages for mode\r
+    JA      @SVM_BadModeSetup2   ; Report Error if too Many Pages\r
+    JCXZ    @SVM_BadModeSetup3   ; Report Error if 0 Pages\r
+\r
+    ; Check Validity of X Size\r
+\r
+    AND     [BP].SVM_XSize, 0FFF8h  ; X size Mod 8 Must = 0\r
+\r
+    MOV     AX, [BP].SVM_XSize  ; Get Logical Screen Width\r
+    CMP     AX, CS:[SI].M_XSize ; Check against Displayed X\r
+    JB      @SVM_BadModeSetup4   ; Report Error if too small\r
+    CMP     AX, CS:[SI].M_XMax  ; Check against Max X\r
+    JA      @SVM_BadModeSetup5   ; Report Error if too big\r
+\r
+    ; Check Validity of Y Size\r
+\r
+    MOV     BX, [BP].SVM_YSize  ; Get Logical Screen Height\r
+    CMP     BX, CS:[SI].M_YSize ; Check against Displayed Y\r
+    JB      @SVM_BadModeSetup6   ; Report Error if too small\r
+    CMP     BX, CS:[SI].M_YMax  ; Check against Max Y\r
+    JA      @SVM_BadModeSetup7   ; Report Error if too big\r
+\r
+    ; Enough memory to Fit it all?\r
+\r
+    SHR     AX, 1               ; # of Bytes:Line = XSize/4\r
+    SHR     AX, 1               ; # of Bytes:Line = XSize/4\r
+    MUL     CX                  ; AX = Bytes/Line * Pages\r
+    MUL     BX                  ; DX:AX = Total VGA mem needed\r
+    JNO     @SVM_Continue       ; Exit if Total Size > 256K\r
+\r
+    DEC     DX                  ; Was it Exactly 256K???\r
+    OR      DX, AX              ; (DX = 1, AX = 0000)\r
+    JZ      @SVM_Continue       ; if so, it's valid...\r
+\r
+       jmp      @SVM_Continue;0000\r
+\r
+@SVM_BadModeSetup:\r
+    mov ax,8                  ; Return Value = False\r
+    JMP     @SVM_Exit           ; Normal Exit\r
+@SVM_BadModeSetup1:\r
+    mov ax,1                  ; Return Value = False\r
+    JMP     @SVM_Exit           ; Normal Exit\r
+@SVM_BadModeSetup2:\r
+    mov ax,2                  ; Return Value = False\r
+    JMP     @SVM_Exit           ; Normal Exit\r
+@SVM_BadModeSetup3:\r
+    mov ax,3                  ; Return Value = False\r
+    JMP     @SVM_Exit           ; Normal Exit\r
+@SVM_BadModeSetup4:\r
+    mov ax,4                  ; Return Value = False\r
+    JMP     @SVM_Exit           ; Normal Exit\r
+@SVM_BadModeSetup5:\r
+    mov ax,5                  ; Return Value = False\r
+    JMP     @SVM_Exit           ; Normal Exit\r
+@SVM_BadModeSetup6:\r
+    mov ax,6                  ; Return Value = False\r
+    JMP     @SVM_Exit           ; Normal Exit\r
+@SVM_BadModeSetup7:\r
+    mov ax,7                  ; Return Value = False\r
+    JMP     @SVM_Exit           ; Normal Exit\r
+\r
+@SVM_Continue:\r
+\r
+    MOV     AX, 13H             ; Start with Mode 13H\r
+    INT     10H                 ; Let BIOS Set Mode\r
+\r
+    OUT_16  SC_INDEX, CHAIN4_OFF            ; Disable Chain 4 Mode\r
+    OUT_16  SC_INDEX, ASYNC_RESET           ; (A)synchronous Reset\r
+    OUT_8   MISC_OUTPUT, CS:[SI].M_MiscR    ; Set New Timing/Size\r
+    OUT_16  SC_INDEX, SEQU_RESTART          ; Restart Sequencer ...\r
+\r
+    OUT_8   CRTC_INDEX, 11H     ; Select Vert Retrace End Register\r
+    INC     DX                  ; Point to Data\r
+    IN      AL, DX              ; Get Value, Bit 7 = Protect\r
+    AND     AL, 7FH             ; Mask out Write Protect\r
+    OUT     DX, AL              ; And send it back\r
+\r
+    MOV     DX, CRTC_INDEX      ; Vga Crtc Registers\r
+    ADD     SI, M_CRTC          ; SI -> CRTC Parameter Data\r
+\r
+    ; Load Tables of CRTC Parameters from List of Tables\r
+\r
+@SVM_Setup_Table:\r
+\r
+    MOV     DI, CS:[SI]         ; Get Pointer to CRTC Data Tbl\r
+    ADD     SI, 2               ; Point to next Ptr Entry\r
+    OR      DI, DI              ; A nil Ptr means that we have\r
+    JZ      @SVM_Set_Data       ; finished CRTC programming\r
+\r
+@SVM_Setup_CRTC:\r
+    MOV     AX, CS:[DI]         ; Get CRTC Data from Table\r
+    ADD     DI, 2               ; Advance Pointer\r
+    OR      AX, AX              ; At End of Data Table?\r
+    JZ      @SVM_Setup_Table    ; If so, Exit & get next Table\r
+\r
+    OUT     DX, AX              ; Reprogram VGA CRTC reg\r
+    JMP     s @SVM_Setup_CRTC   ; Process Next Table Entry\r
+\r
+    ; Initialize Page & Scroll info, DI = 0\r
+\r
+@SVM_Set_Data:\r
+    MOV     DISPLAY_PAGE, DI    ; Display Page = 0\r
+    MOV     ACTIVE_PAGE, DI     ; Active Page = 0\r
+    MOV     CURRENT_PAGE, DI    ; Current Page (Offset) = 0\r
+    MOV     CURRENT_XOFFSET, DI ; Horz Scroll Index = 0\r
+    MOV     CURRENT_YOFFSET, DI ; Vert Scroll Index = 0\r
+    MOV     CURRENT_MOFFSET, DI ; Memory Scroll Index = 0\r
+\r
+    MOV     AX, VGA_SEGMENT     ; Segment for VGA memory\r
+    MOV     CURRENT_SEGMENT, AX ; Save for Future LES's\r
+\r
+    ; Set Logical Screen Width, X Scroll and Our Data\r
+\r
+    MOV     SI, [BP].SVM_Table  ; Get Saved Ptr to Mode Info\r
+    MOV     AX, [BP].SVM_Xsize  ; Get Display Width\r
+\r
+    MOV     CX, AX              ; CX = Logical Width\r
+    SUB     CX, CS:[SI].M_XSize ; CX = Max X Scroll Value\r
+    MOV     MAX_XOFFSET, CX     ; Set Maximum X Scroll\r
+\r
+    SHR     AX, 1               ; Bytes = Pixels / 4\r
+    SHR     AX, 1               ; Bytes = Pixels / 4\r
+    MOV     SCREEN_WIDTH, AX    ; Save Width in Pixels\r
+\r
+    SHR     AX, 1               ; Offset Value = Bytes / 2\r
+    MOV     AH, 13h             ; CRTC Offset Register Index\r
+    XCHG    AL, AH              ; Switch format for OUT\r
+    OUT     DX, AX              ; Set VGA CRTC Offset Reg\r
+\r
+    ; Setup Data table, Y Scroll, Misc for Other Routines\r
+\r
+    MOV     AX, [BP].SVM_Ysize  ; Get Logical Screen Height\r
+\r
+    MOV     CX, AX              ; CX = Logical Height\r
+    SUB     BX, CS:[SI].M_YSize ; CX = Max Y Scroll Value\r
+    MOV     MAX_YOFFSET, CX     ; Set Maximum Y Scroll\r
+\r
+    MOV     SCREEN_HEIGHT, AX   ; Save Height in Pixels\r
+    MUL     SCREEN_WIDTH        ; AX = Page Size in Bytes,\r
+    MOV     PAGE_SIZE, AX       ; Save Page Size\r
+\r
+    MOV     CX, [BP].SVM_Pages  ; Get # of Pages\r
+    MOV     LAST_PAGE, CX       ; Save # of Pages\r
+\r
+    mov bx,0                  ; Page # = 0\r
+    MOV     DX, BX              ; Page 0 Offset = 0\r
+\r
+@SVM_Set_Pages:\r
+\r
+    MOV     PAGE_ADDR[BX], DX   ; Set Page #(BX) Offset\r
+    ADD     BX, 2               ; Page#++\r
+    ADD     DX, AX              ; Compute Addr of Next Page\r
+    LOOPx   CX, @SVM_Set_Pages  ; Loop until all Pages Set\r
+\r
+    ; Clear VGA Memory\r
+\r
+    OUT_16  SC_INDEX, ALL_PLANES_ON ; Select All Planes\r
+    LES     DI, d CURRENT_PAGE      ; -> Start of VGA memory\r
+\r
+    mov ax,0                  ; AX = 0\r
+    CLD                         ; Block Xfer Forwards\r
+    MOV     CX, 8000H           ; 32K * 4 * 2 = 256K\r
+    REP     STOSW               ; Clear dat memory!\r
+\r
+    ; Setup Font Pointers\r
+\r
+    MOV     BH, ROM_8x8_Lo      ; Ask for 8x8 Font, 0-127\r
+    MOV     AX, GET_CHAR_PTR    ; Service to Get Pointer\r
+    INT     10h                 ; Call VGA BIOS\r
+\r
+    MOV     CHARSET_LOW, BP     ; Save Char Set Offset\r
+    MOV     CHARSET_LOW+2, ES   ; Save Char Set Segment\r
+\r
+    MOV     BH, ROM_8x8_Hi      ; Ask for 8x8 Font, 128-255\r
+    MOV     AX, GET_CHAR_PTR    ; Service to Get Pointer\r
+    INT     10h                 ; Call VGA BIOS\r
+\r
+    MOV     CHARSET_HI, BP      ; Save Char Set Offset\r
+    MOV     CHARSET_HI+2, ES    ; Save Char Set Segment\r
+\r
+    MOV     AX, True            ; Return Success Code\r
+\r
+@SVM_EXIT:\r
+    ADD     SP, 2               ; Deallocate workspace\r
+    ;POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    RET     8                   ; Exit & Clean Up Stack\r
+\r
+SET_VGA_MODEX   ENDP\r
+\r
+\r
+;==================\r
+;SET_MODEX% (Mode%)\r
+;==================\r
+;\r
+; Quickie Mode Set - Sets Up Mode X to Default Configuration\r
+;\r
+; ENTRY: ModeType = Desired Screen Resolution (0-7)\r
+;        (See SET_VGA_MODEX for list)\r
+;\r
+; EXIT:  AX = Success Flag:   0 = Failure / -1= Success\r
+;\r
+\r
+SM_STACK    STRUC\r
+                DW  ?,? ; BP, SI\r
+                DD  ?   ; Caller\r
+    SM_Mode     DW  ?   ; Desired Screen Resolution\r
+SM_STACK    ENDS\r
+\r
+    PUBLIC  SET_MODEX\r
+\r
+SET_MODEX   PROC    FAR\r
+\r
+    ;PUSHx   BP, SI              ; Preserve Important registers\r
+    push       bp\r
+       push    si\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    mov ax,0                  ; Assume Failure\r
+    MOV     BX, [BP].SM_Mode    ; Get Desired Mode #\r
+    CMP     BX, NUM_MODES       ; Is it a Valid Mode #?\r
+    JAE     @SMX_Exit           ; If Not, don't Bother\r
+\r
+    PUSH    BX                  ; Push Mode Parameter\r
+\r
+    SHL     BX, 1                   ; Scale BX to word Index\r
+    MOV     SI, w MODE_TABLE[BX]    ; CS:SI -> Mode Info\r
+\r
+    PUSH    CS:[SI].M_XSize     ; Push Default X Size\r
+    PUSH    CS:[SI].M_Ysize     ; Push Default Y size\r
+    MOV     AL, CS:[SI].M_Pages ; Get Default # of Pages\r
+    mov ah,0                  ; Hi Byte = 0\r
+    PUSH    AX                  ; Push # Pages\r
+\r
+    CALL    f SET_VGA_MODEX     ; Set up Mode X!\r
+\r
+@SMX_Exit:\r
+    ;POPx    SI, BP              ; Restore Registers\r
+       pop     si\r
+       pop     bp\r
+    RET     2                   ; Exit & Clean Up Stack\r
+\r
+SET_MODEX   ENDP\r
+\r
+\r
+    ; ===== BASIC GRAPHICS PRIMITIVES =====\r
+\r
+;============================\r
+;CLEAR_VGA_SCREEN (ColorNum%)\r
+;============================\r
+;\r
+; Clears the active display page\r
+;\r
+; ENTRY: ColorNum = Color Value to fill the page with\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+CVS_STACK   STRUC\r
+                DW  ?,? ; DI, BP\r
+                DD  ?   ; Caller\r
+    CVS_COLOR   DB  ?,? ; Color to Set Screen to\r
+CVS_STACK   ENDS\r
+\r
+    PUBLIC  CLEAR_VGA_SCREEN\r
+\r
+CLEAR_VGA_SCREEN    PROC    FAR\r
+\r
+    ;PUSHx   BP, DI              ; Preserve Important Registers\r
+    push       bp\r
+       push    di\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    OUT_16  SC_INDEX, ALL_PLANES_ON ; Select All Planes\r
+    LES     DI, d CURRENT_PAGE      ; Point to Active VGA Page\r
+\r
+    MOV     AL, [BP].CVS_COLOR  ; Get Color\r
+    MOV     AH, AL              ; Copy for Word Write\r
+    CLD                         ; Block fill Forwards\r
+\r
+    MOV     CX, PAGE_SIZE       ; Get Size of Page\r
+    SHR     CX, 1               ; Divide by 2 for Words\r
+    REP     STOSW               ; Block Fill VGA memory\r
+\r
+    ;POPx    DI, BP              ; Restore Saved Registers\r
+    pop        di\r
+       pop     bp\r
+    RET     2                   ; Exit & Clean Up Stack\r
+\r
+CLEAR_VGA_SCREEN    ENDP\r
+\r
+\r
+;===================================\r
+;SET_POINT (Xpos%, Ypos%, ColorNum%)\r
+;===================================\r
+;\r
+; Plots a single Pixel on the active display page\r
+;\r
+; ENTRY: Xpos     = X position to plot pixel at\r
+;        Ypos     = Y position to plot pixel at\r
+;        ColorNum = Color to plot pixel with\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+SP_STACK    STRUC\r
+                DW  ?,? ; BP, DI\r
+                DD  ?   ; Caller\r
+    SETP_Color  DB  ?,? ; Color of Point to Plot\r
+    SETP_Ypos   DW  ?   ; Y pos of Point to Plot\r
+    SETP_Xpos   DW  ?   ; X pos of Point to Plot\r
+SP_STACK    ENDS\r
+\r
+        PUBLIC SET_POINT\r
+\r
+SET_POINT   PROC    FAR\r
+\r
+    ;PUSHx   BP, DI              ; Preserve Registers\r
+    push       bp\r
+       push    di\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+\r
+    MOV     AX, [BP].SETP_Ypos  ; Get Line # of Pixel\r
+    MUL     SCREEN_WIDTH        ; Get Offset to Start of Line\r
+\r
+    MOV     BX, [BP].SETP_Xpos  ; Get Xpos\r
+    MOV     CX, BX              ; Copy to extract Plane # from\r
+    SHR     BX, 1               ; X offset (Bytes) = Xpos/4\r
+    SHR     BX, 1               ; X offset (Bytes) = Xpos/4\r
+    ADD     BX, AX              ; Offset = Width*Ypos + Xpos/4\r
+\r
+    MOV     AX, MAP_MASK_PLANE1 ; Map Mask & Plane Select Register\r
+    AND     CL, PLANE_BITS      ; Get Plane Bits\r
+    SHL     AH, CL              ; Get Plane Select Value\r
+    OUT_16  SC_Index, AX        ; Select Plane\r
+\r
+    MOV     AL,[BP].SETP_Color  ; Get Pixel Color\r
+    MOV     ES:[DI+BX], AL      ; Draw Pixel\r
+\r
+    ;POPx    DI, BP              ; Restore Saved Registers\r
+    pop        di\r
+       pop     bp\r
+    RET     6                   ; Exit and Clean up Stack\r
+\r
+SET_POINT        ENDP\r
+\r
+\r
+;==========================\r
+;READ_POINT% (Xpos%, Ypos%)\r
+;==========================\r
+;\r
+; Read the color of a pixel from the Active Display Page\r
+;\r
+; ENTRY: Xpos = X position of pixel to read\r
+;        Ypos = Y position of pixel to read\r
+;\r
+; EXIT:  AX   = Color of Pixel at (Xpos, Ypos)\r
+;\r
+\r
+RP_STACK    STRUC\r
+            DW  ?,? ; BP, DI\r
+            DD  ?   ; Caller\r
+    RP_Ypos DW  ?   ; Y pos of Point to Read\r
+    RP_Xpos DW  ?   ; X pos of Point to Read\r
+RP_STACK    ENDS\r
+\r
+        PUBLIC  READ_POINT\r
+\r
+READ_POINT      PROC    FAR\r
+\r
+    ;PUSHx   BP, DI              ; Preserve Registers\r
+    push       bp\r
+       push    di\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+\r
+    MOV     AX, [BP].RP_Ypos    ; Get Line # of Pixel\r
+    MUL     SCREEN_WIDTH        ; Get Offset to Start of Line\r
+\r
+    MOV     BX, [BP].RP_Xpos    ; Get Xpos\r
+    MOV     CX, BX\r
+    SHR     BX, 1               ; X offset (Bytes) = Xpos/4\r
+    SHR     BX, 1               ; X offset (Bytes) = Xpos/4\r
+    ADD     BX, AX              ; Offset = Width*Ypos + Xpos/4\r
+\r
+    MOV     AL, READ_MAP        ; GC Read Mask Register\r
+    MOV     AH, CL              ; Get Xpos\r
+    AND     AH, PLANE_BITS      ; & mask out Plane #\r
+    OUT_16  GC_INDEX, AX        ; Select Plane to read in\r
+\r
+    mov ah,0                  ; Clear Return Value Hi byte\r
+    MOV     AL, ES:[DI+BX]      ; Get Color of Pixel\r
+\r
+    ;POPx    DI, BP              ; Restore Saved Registers\r
+    pop        di\r
+       pop     bp\r
+    RET     4                   ; Exit and Clean up Stack\r
+\r
+READ_POINT        ENDP\r
+\r
+\r
+;======================================================\r
+;FILL_BLOCK (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%)\r
+;======================================================\r
+;\r
+; Fills a rectangular block on the active display Page\r
+;\r
+; ENTRY: Xpos1    = Left X position of area to fill\r
+;        Ypos1    = Top Y position of area to fill\r
+;        Xpos2    = Right X position of area to fill\r
+;        Ypos2    = Bottom Y position of area to fill\r
+;        ColorNum = Color to fill area with\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+FB_STACK    STRUC\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DD  ?   ; Caller\r
+    FB_Color    DB  ?,? ; Fill Color\r
+    FB_Ypos2    DW  ?   ; Y pos of Lower Right Pixel\r
+    FB_Xpos2    DW  ?   ; X pos of Lower Right Pixel\r
+    FB_Ypos1    DW  ?   ; Y pos of Upper Left Pixel\r
+    FB_Xpos1    DW  ?   ; X pos of Upper Left Pixel\r
+FB_STACK    ENDS\r
+\r
+        PUBLIC    FILL_BLOCK\r
+\r
+FILL_BLOCK  PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+       push    di\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+    CLD                         ; Direction Flag = Forward\r
+\r
+    OUT_8   SC_INDEX, MAP_MASK  ; Set up for Plane Select\r
+\r
+    ; Validate Pixel Coordinates\r
+    ; If necessary, Swap so X1 <= X2, Y1 <= Y2\r
+\r
+    MOV     AX, [BP].FB_Ypos1   ; AX = Y1   is Y1< Y2?\r
+    MOV     BX, [BP].FB_Ypos2   ; BX = Y2\r
+    CMP     AX, BX\r
+    JLE     @FB_NOSWAP1\r
+\r
+    MOV     [BP].FB_Ypos1, BX   ; Swap Y1 and Y2 and save Y1\r
+    XCHG    AX, BX              ; on stack for future use\r
+\r
+@FB_NOSWAP1:\r
+    SUB     BX, AX              ; Get Y width\r
+    INC     BX                  ; Add 1 to avoid 0 value\r
+    MOV     [BP].FB_Ypos2, BX   ; Save in Ypos2\r
+\r
+    MUL     SCREEN_WIDTH        ; Mul Y1 by Bytes per Line\r
+    ADD     DI, AX              ; DI = Start of Line Y1\r
+\r
+    MOV     AX, [BP].FB_Xpos1   ; Check X1 <= X2\r
+    MOV     BX, [BP].FB_Xpos2   ;\r
+    CMP     AX, BX\r
+    JLE     @FB_NOSWAP2         ; Skip Ahead if Ok\r
+\r
+    MOV     [BP].FB_Xpos2, AX   ; Swap X1 AND X2 and save X2\r
+    XCHG    AX, BX              ; on stack for future use\r
+\r
+    ; All our Input Values are in order, Now determine\r
+    ; How many full "bands" 4 pixels wide (aligned) there\r
+    ; are, and if there are partial bands (<4 pixels) on\r
+    ; the left and right edges.\r
+\r
+@FB_NOSWAP2:\r
+    MOV     DX, AX              ; DX = X1 (Pixel Position)\r
+    SHR     DX, 1               ; DX/4 = Bytes into Line\r
+    SHR     DX, 1               ; DX/4 = Bytes into Line\r
+    ADD     DI, DX              ; DI = Addr of Upper-Left Corner\r
+\r
+    MOV     CX, BX              ; CX = X2 (Pixel Position)\r
+    SHR     CX, 1               ; CX/4 = Bytes into Line\r
+    SHR     CX, 1               ; CX/4 = Bytes into Line\r
+\r
+    CMP     DX, CX              ; Start and end in same band?\r
+    JNE     @FB_NORMAL          ; if not, check for l & r edges\r
+    JMP     @FB_ONE_BAND_ONLY   ; if so, then special processing\r
+\r
+@FB_NORMAL:\r
+    SUB     CX, DX              ; CX = # bands -1\r
+    MOV     SI, AX              ; SI = PLANE#(X1)\r
+    AND     SI, PLANE_BITS      ; if Left edge is aligned then\r
+    JZ      @FB_L_PLANE_FLUSH   ; no special processing..\r
+\r
+    ; Draw "Left Edge" vertical strip of 1-3 pixels...\r
+\r
+    OUT_8   SC_Data, Left_Clip_Mask[SI] ; Set Left Edge Plane Mask\r
+\r
+    MOV     SI, DI              ; SI = Copy of Start Addr (UL)\r
+\r
+    MOV     DX, [BP].FB_Ypos2   ; Get # of Lines to draw\r
+    MOV     AL, [BP].FB_Color   ; Get Fill Color\r
+    MOV     BX, SCREEN_WIDTH    ; Get Vertical increment Value\r
+\r
+@FB_LEFT_LOOP:\r
+    MOV     ES:[SI], AL         ; Fill in Left Edge Pixels\r
+    ADD     SI, BX              ; Point to Next Line (Below)\r
+    LOOPjz  DX, @FB_LEFT_CONT   ; Exit loop if all Lines Drawn\r
+\r
+    MOV     ES:[SI], AL         ; Fill in Left Edge Pixels\r
+    ADD     SI, BX              ; Point to Next Line (Below)\r
+    LOOPx   DX, @FB_LEFT_LOOP   ; loop until left strip is drawn\r
+\r
+@FB_LEFT_CONT:\r
+\r
+    INC     DI                  ; Point to Middle (or Right) Block\r
+    DEC     CX                  ; Reset CX instead of JMP @FB_RIGHT\r
+\r
+@FB_L_PLANE_FLUSH:\r
+    INC     CX                  ; Add in Left band to middle block\r
+\r
+    ; DI = Addr of 1st middle Pixel (band) to fill\r
+    ; CX = # of Bands to fill -1\r
+\r
+@FB_RIGHT:\r
+    MOV     SI, [BP].FB_Xpos2   ; Get Xpos2\r
+    AND     SI, PLANE_BITS      ; Get Plane values\r
+    CMP     SI, 0003            ; Plane = 3?\r
+    JE      @FB_R_EDGE_FLUSH    ; Hey, add to middle\r
+\r
+    ; Draw "Right Edge" vertical strip of 1-3 pixels...\r
+\r
+    OUT_8   SC_Data, Right_Clip_Mask[SI]    ; Right Edge Plane Mask\r
+\r
+    MOV     SI, DI              ; Get Addr of Left Edge\r
+    ADD     SI, CX              ; Add Width-1 (Bands)\r
+    DEC     SI                  ; To point to top of Right Edge\r
+\r
+    MOV     DX, [BP].FB_Ypos2   ; Get # of Lines to draw\r
+    MOV     AL, [BP].FB_Color   ; Get Fill Color\r
+    MOV     BX, SCREEN_WIDTH    ; Get Vertical increment Value\r
+\r
+@FB_RIGHT_LOOP:\r
+    MOV     ES:[SI], AL         ; Fill in Right Edge Pixels\r
+    ADD     SI, BX              ; Point to Next Line (Below)\r
+    LOOPjz  DX, @FB_RIGHT_CONT  ; Exit loop if all Lines Drawn\r
+\r
+    MOV     ES:[SI], AL         ; Fill in Right Edge Pixels\r
+    ADD     SI, BX              ; Point to Next Line (Below)\r
+    LOOPx   DX, @FB_RIGHT_LOOP  ; loop until left strip is drawn\r
+\r
+@FB_RIGHT_CONT:\r
+\r
+    DEC     CX                  ; Minus 1 for Middle bands\r
+    JZ      @FB_EXIT            ; Uh.. no Middle bands...\r
+\r
+@FB_R_EDGE_FLUSH:\r
+\r
+    ; DI = Addr of Upper Left block to fill\r
+    ; CX = # of Bands to fill in (width)\r
+\r
+    OUT_8   SC_Data, ALL_PLANES ; Write to All Planes\r
+\r
+    MOV     DX, SCREEN_WIDTH    ; DX = DI Increment\r
+    SUB     DX, CX              ;  = Screen_Width-# Planes Filled\r
+\r
+    MOV     BX, CX              ; BX = Quick Refill for CX\r
+    MOV     SI, [BP].FB_Ypos2   ; SI = # of Line to Fill\r
+    MOV     AL, [BP].FB_Color   ; Get Fill Color\r
+\r
+@FB_MIDDLE_LOOP:\r
+    REP     STOSB               ; Fill in entire line\r
+\r
+    MOV     CX, BX              ; Recharge CX (Line Width)\r
+    ADD     DI, DX              ; Point to start of Next Line\r
+    LOOPx   SI, @FB_MIDDLE_LOOP ; Loop until all lines drawn\r
+\r
+    JMP     s @FB_EXIT          ; Outa here\r
+\r
+@FB_ONE_BAND_ONLY:\r
+    MOV     SI, AX                  ; Get Left Clip Mask, Save X1\r
+    AND     SI, PLANE_BITS          ; Mask out Row #\r
+    MOV     AL, Left_Clip_Mask[SI]  ; Get Left Edge Mask\r
+    MOV     SI, BX                  ; Get Right Clip Mask, Save X2\r
+    AND     SI, PLANE_BITS          ; Mask out Row #\r
+    AND     AL, Right_Clip_Mask[SI] ; Get Right Edge Mask byte\r
+\r
+    OUT_8   SC_Data, AL         ; Clip For Left & Right Masks\r
+\r
+    MOV     CX, [BP].FB_Ypos2   ; Get # of Lines to draw\r
+    MOV     AL, [BP].FB_Color   ; Get Fill Color\r
+    MOV     BX, SCREEN_WIDTH    ; Get Vertical increment Value\r
+\r
+@FB_ONE_LOOP:\r
+    MOV     ES:[DI], AL         ; Fill in Pixels\r
+    ADD     DI, BX              ; Point to Next Line (Below)\r
+    LOOPjz  CX, @FB_EXIT        ; Exit loop if all Lines Drawn\r
+\r
+    MOV     ES:[DI], AL         ; Fill in Pixels\r
+    ADD     DI, BX              ; Point to Next Line (Below)\r
+    LOOPx   CX, @FB_ONE_LOOP    ; loop until left strip is drawn\r
+\r
+@FB_EXIT:\r
+    ;POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    RET     10                  ; Exit and Clean up Stack\r
+\r
+FILL_BLOCK   ENDP\r
+\r
+\r
+;=====================================================\r
+;DRAW_LINE (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%)\r
+;=====================================================\r
+;\r
+; Draws a Line on the active display page\r
+;\r
+; ENTRY: Xpos1    = X position of first point on line\r
+;        Ypos1    = Y position of first point on line\r
+;        Xpos2    = X position of last point on line\r
+;        Ypos2    = Y position of last point on line\r
+;        ColorNum = Color to draw line with\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+DL_STACK    STRUC\r
+                DW  ?x1 ; DI, SI, BP\r
+                DW  ?x1 ; DI, SI, BP\r
+                DW  ?x1 ; DI, SI, BP\r
+                DD  ?   ; Caller\r
+    DL_ColorF   DB  ?,? ; Line Draw Color\r
+    DL_Ypos2    DW  ?   ; Y pos of last point\r
+    DL_Xpos2    DW  ?   ; X pos of last point\r
+    DL_Ypos1    DW  ?   ; Y pos of first point\r
+    DL_Xpos1    DW  ?   ; X pos of first point\r
+DL_STACK    ENDS\r
+\r
+        PUBLIC DRAW_LINE\r
+\r
+DRAW_LINE   PROC    FAR\r
+\r
+    ;PUSHx   BP, SI, DI          ; Preserve Important Registers\r
+    push       bp\r
+       push    si\r
+       push    di\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+    CLD                         ; Direction Flag = Forward\r
+\r
+    OUT_8   SC_INDEX, MAP_MASK  ; Set up for Plane Select\r
+    MOV     CH, [BP].DL_ColorF  ; Save Line Color in CH\r
+\r
+    ; Check Line Type\r
+\r
+    MOV     SI, [BP].DL_Xpos1   ; AX = X1   is X1< X2?\r
+    MOV     DI, [BP].DL_Xpos2   ; DX = X2\r
+    CMP     SI, DI              ; Is X1 < X2\r
+    JE      @DL_VLINE           ; If X1=X2, Draw Vertical Line\r
+    JL      @DL_NOSWAP1         ; If X1 < X2, don't swap\r
+\r
+    XCHG    SI, DI              ; X2 IS > X1, SO SWAP THEM\r
+\r
+@DL_NOSWAP1:\r
+\r
+    ; SI = X1, DI = X2\r
+\r
+    MOV     AX, [BP].DL_Ypos1   ; AX = Y1   is Y1 <> Y2?\r
+    CMP     AX, [BP].DL_Ypos2   ; Y1 = Y2?\r
+    JE      @DL_HORZ            ; If so, Draw a Horizontal Line\r
+\r
+    JMP     @DL_BREZHAM         ; Diagonal line... go do it...\r
+\r
+    ; This Code draws a Horizontal Line in Mode X where:\r
+    ; SI = X1, DI = X2, and AX = Y1/Y2\r
+\r
+@DL_HORZ:\r
+\r
+    MUL     SCREEN_WIDTH        ; Offset = Ypos * Screen_Width\r
+    MOV     DX, AX              ; CX = Line offset into Page\r
+\r
+    MOV     AX, SI                  ; Get Left edge, Save X1\r
+    AND     SI, PLANE_BITS          ; Mask out Row #\r
+    MOV     BL, Left_Clip_Mask[SI]  ; Get Left Edge Mask\r
+    MOV     CX, DI                  ; Get Right edge, Save X2\r
+    AND     DI, PLANE_BITS          ; Mask out Row #\r
+    MOV     BH, Right_Clip_Mask[DI] ; Get Right Edge Mask byte\r
+\r
+    SHR     AX, 1               ; Get X1 Byte # (=X1/4)\r
+    SHR     CX, 1               ; Get X2 Byte # (=X2/4)\r
+    SHR     AX, 1               ; Get X1 Byte # (=X1/4)\r
+    SHR     CX, 1               ; Get X2 Byte # (=X2/4)\r
+\r
+    LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+    ADD     DI, DX              ; Point to Start of Line\r
+    ADD     DI, AX              ; Point to Pixel X1\r
+\r
+    SUB     CX, AX              ; CX = # Of Bands (-1) to set\r
+    JNZ     @DL_LONGLN          ; jump if longer than one segment\r
+\r
+    AND     BL, BH              ; otherwise, merge clip masks\r
+\r
+@DL_LONGLN:\r
+\r
+    OUT_8   SC_Data, BL         ; Set the Left Clip Mask\r
+\r
+    MOV     AL, [BP].DL_ColorF  ; Get Line Color\r
+    MOV     BL, AL              ; BL = Copy of Line Color\r
+    STOSB                       ; Set Left (1-4) Pixels\r
+\r
+    JCXZ    @DL_EXIT            ; Done if only one Line Segment\r
+\r
+    DEC     CX                  ; CX = # of Middle Segments\r
+    JZ      @DL_XRSEG           ; If no middle segments....\r
+\r
+    ; Draw Middle Segments\r
+\r
+    OUT_8   DX, ALL_PLANES      ; Write to ALL Planes\r
+\r
+    MOV     AL, BL              ; Get Color from BL\r
+    REP     STOSB               ; Draw Middle (4 Pixel) Segments\r
+\r
+@DL_XRSEG:\r
+    OUT_8   DX, BH              ; Select Planes for Right Clip Mask\r
+    MOV     AL, BL              ; Get Color Value\r
+    STOSB                       ; Draw Right (1-4) Pixels\r
+\r
+    JMP     s @DL_EXIT          ; We Are Done...\r
+\r
+\r
+    ; This Code Draws A Vertical Line.  On entry:\r
+    ; CH = Line Color, SI & DI = X1\r
+\r
+@DL_VLINE:\r
+\r
+    MOV     AX, [BP].DL_Ypos1   ; AX = Y1\r
+    MOV     SI, [BP].DL_Ypos2   ; SI = Y2\r
+    CMP     AX, SI              ; Is Y1 < Y2?\r
+    JLE     @DL_NOSWAP2         ; if so, Don't Swap them\r
+\r
+    XCHG    AX, SI              ; Ok, NOW Y1 < Y2\r
+\r
+@DL_NOSWAP2:\r
+\r
+    SUB     SI, AX              ; SI = Line Height (Y2-Y1+1)\r
+    INC     SI\r
+\r
+    ; AX = Y1, DI = X1, Get offset into Page into AX\r
+\r
+    MUL     SCREEN_WIDTH        ; Offset = Y1 (AX) * Screen Width\r
+    MOV     DX, DI              ; Copy Xpos into DX\r
+    SHR     DI, 1               ; DI = Xpos/4\r
+    SHR     DI, 1               ; DI = Xpos/4\r
+    ADD     AX, DI              ; DI = Xpos/4 + ScreenWidth * Y1\r
+\r
+    LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+    ADD     DI, AX              ; Point to Pixel X1, Y1\r
+\r
+    ;Select Plane\r
+\r
+    MOV     CL, DL              ; CL = Save X1\r
+    AND     CL, PLANE_BITS      ; Get X1 MOD 4 (Plane #)\r
+    MOV     AX, MAP_MASK_PLANE1 ; Code to set Plane #1\r
+    SHL     AH, CL              ; Change to Correct Plane #\r
+    OUT_16  SC_Index, AX        ; Select Plane\r
+\r
+    MOV     AL, CH              ; Get Saved Color\r
+    MOV     BX, SCREEN_WIDTH    ; Get Offset to Advance Line By\r
+\r
+@DL_VLoop:\r
+    MOV     ES:[DI], AL         ; Draw Single Pixel\r
+    ADD     DI, BX              ; Point to Next Line\r
+    LOOPjz  SI, @DL_EXIT        ; Lines--, Exit if done\r
+\r
+    MOV     ES:[DI], AL         ; Draw Single Pixel\r
+    ADD     DI, BX              ; Point to Next Line\r
+    LOOPx   SI, @DL_VLoop       ; Lines--, Loop until Done\r
+\r
+@DL_EXIT:\r
+\r
+    JMP     @DL_EXIT2           ; Done!\r
+\r
+    ; This code Draws a diagonal line in Mode X\r
+\r
+@DL_BREZHAM:\r
+    LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+\r
+    MOV     AX, [BP].DL_Ypos1   ; get Y1 value\r
+    MOV     BX, [BP].DL_Ypos2   ; get Y2 value\r
+    MOV     CX, [BP].DL_Xpos1   ; Get Starting Xpos\r
+\r
+    CMP     BX, AX              ; Y2-Y1 is?\r
+    JNC     @DL_DeltaYOK        ; if Y2>=Y1 then goto...\r
+\r
+    XCHG    BX, AX              ; Swap em...\r
+    MOV     CX, [BP].DL_Xpos2   ; Get New Starting Xpos\r
+\r
+@DL_DeltaYOK:\r
+    MUL     SCREEN_WIDTH        ; Offset = SCREEN_WIDTH * Y1\r
+\r
+    ADD     DI, AX              ; DI -> Start of Line Y1 on Page\r
+    MOV     AX, CX              ; AX = Xpos (X1)\r
+    SHR     AX, 1               ; /4 = Byte Offset into Line\r
+    SHR     AX, 1               ; /4 = Byte Offset into Line\r
+    ADD     DI, AX              ; DI = Starting pos (X1,Y1)\r
+\r
+    MOV     AL, 11h             ; Staring Mask\r
+    AND     CL, PLANE_BITS      ; Get Plane #\r
+    SHL     AL, CL              ; and shift into place\r
+    MOV     AH, [BP].DL_ColorF  ; Color in Hi Bytes\r
+\r
+    PUSH    AX                  ; Save Mask,Color...\r
+\r
+    MOV     AH, AL              ; Plane # in AH\r
+    MOV     AL, MAP_MASK        ; Select Plane Register\r
+    OUT_16  SC_Index, AX        ; Select initial plane\r
+\r
+    MOV     AX, [BP].DL_Xpos1   ; get X1 value\r
+    MOV     BX, [BP].DL_Ypos1   ; get Y1 value\r
+    MOV     CX, [BP].DL_Xpos2   ; get X2 value\r
+    MOV     DX, [BP].DL_Ypos2   ; get Y2 value\r
+\r
+    MOV     BP, SCREEN_WIDTH    ; Use BP for Line width to\r
+                                ; to avoid extra memory access\r
+\r
+    SUB     DX, BX              ; figure Delta_Y\r
+    JNC     @DL_DeltaYOK2       ; jump if Y2 >= Y1\r
+\r
+    ADD     BX, DX              ; put Y2 into Y1\r
+    NEG     DX                  ; abs(Delta_Y)\r
+    XCHG    AX, CX              ; and exchange X1 and X2\r
+\r
+@DL_DeltaYOK2:\r
+    MOV     BX, 08000H          ; seed for fraction accumulator\r
+\r
+    SUB     CX, AX              ; figure Delta_X\r
+    JC      @DL_DrawLeft        ; if negative, go left\r
+\r
+    JMP     @DL_DrawRight       ; Draw Line that slopes right\r
+\r
+@DL_DrawLeft:\r
+\r
+    NEG     CX                  ; abs(Delta_X)\r
+\r
+    CMP     CX, DX              ; is Delta_X < Delta_Y?\r
+    JB      @DL_SteepLeft       ; yes, so go do steep line\r
+                                ; (Delta_Y iterations)\r
+\r
+    ; Draw a Shallow line to the left in Mode X\r
+\r
+@DL_ShallowLeft:\r
+    mov ax,0                  ; zero low word of Delta_Y * 10000h\r
+    SUB     AX, DX              ; DX:AX <- DX * 0FFFFh\r
+    SBB     DX, 0               ; include carry\r
+    DIV     CX                  ; divide by Delta_X\r
+\r
+    MOV     SI, BX              ; SI = Accumulator\r
+    MOV     BX, AX              ; BX = Add fraction\r
+    POP     AX                  ; Get Color, Bit mask\r
+    MOV     DX, SC_Data         ; Sequence controller data register\r
+    INC     CX                  ; Inc Delta_X so we can unroll loop\r
+\r
+    ; Loop (x2) to Draw Pixels, Move Left, and Maybe Down...\r
+\r
+@DL_SLLLoop:\r
+    MOV     ES:[DI], AH         ; set first pixel, plane data set up\r
+    LOOPjz  CX, @DL_SLLExit     ; Delta_X--, Exit if done\r
+\r
+    ADD     SI, BX              ; add numerator to accumulator\r
+    JNC     @DL_SLLL2nc         ; move down on carry\r
+\r
+    ADD     DI, BP              ; Move Down one line...\r
+\r
+@DL_SLLL2nc:\r
+    DEC     DI                  ; Left one addr\r
+    ROR     AL, 1               ; Move Left one plane, back on 0 1 2\r
+    CMP     AL, 87h             ; wrap?, if AL <88 then Carry set\r
+    ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+    OUT     DX, AL              ; Set up New Bit Plane mask\r
+\r
+    MOV     ES:[DI], AH         ; set pixel\r
+    LOOPjz  CX, @DL_SLLExit     ; Delta_X--, Exit if done\r
+\r
+    ADD     SI, BX              ; add numerator to accumulator,\r
+    JNC     @DL_SLLL3nc         ; move down on carry\r
+\r
+    ADD     DI, BP              ; Move Down one line...\r
+\r
+@DL_SLLL3nc:                    ; Now move left a pixel...\r
+    DEC     DI                  ; Left one addr\r
+    ROR     AL, 1               ; Move Left one plane, back on 0 1 2\r
+    CMP     AL, 87h             ; Wrap?, if AL <88 then Carry set\r
+    ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+    OUT     DX, AL              ; Set up New Bit Plane mask\r
+    JMP     s @DL_SLLLoop       ; loop until done\r
+\r
+@DL_SLLExit:\r
+    JMP     @DL_EXIT2           ; and exit\r
+\r
+    ; Draw a steep line to the left in Mode X\r
+\r
+@DL_SteepLeft:\r
+    mov ax,0                  ; zero low word of Delta_Y * 10000h\r
+    XCHG    DX, CX              ; Delta_Y switched with Delta_X\r
+    DIV     CX                  ; divide by Delta_Y\r
+\r
+    MOV     SI, BX              ; SI = Accumulator\r
+    MOV     BX, AX              ; BX = Add Fraction\r
+    POP     AX                  ; Get Color, Bit mask\r
+    MOV     DX, SC_Data         ; Sequence controller data register\r
+    INC     CX                  ; Inc Delta_Y so we can unroll loop\r
+\r
+    ; Loop (x2) to Draw Pixels, Move Down, and Maybe left\r
+\r
+@DL_STLLoop:\r
+\r
+    MOV     ES:[DI], AH         ; set first pixel\r
+    LOOPjz  CX, @DL_STLExit     ; Delta_Y--, Exit if done\r
+\r
+    ADD     SI, BX              ; add numerator to accumulator\r
+    JNC     @DL_STLnc2          ; No carry, just move down!\r
+\r
+    DEC     DI                  ; Move Left one addr\r
+    ROR     AL, 1               ; Move Left one plane, back on 0 1 2\r
+    CMP     AL, 87h             ; Wrap?, if AL <88 then Carry set\r
+    ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+    OUT     DX, AL              ; Set up New Bit Plane mask\r
+\r
+@DL_STLnc2:\r
+    ADD     DI, BP              ; advance to next line.\r
+\r
+    MOV     ES:[DI], AH         ; set pixel\r
+    LOOPjz  CX, @DL_STLExit     ; Delta_Y--, Exit if done\r
+\r
+    ADD     SI, BX              ; add numerator to accumulator\r
+    JNC     @DL_STLnc3          ; No carry, just move down!\r
+\r
+    DEC     DI                  ; Move Left one addr\r
+    ROR     AL, 1               ; Move Left one plane, back on 0 1 2\r
+    CMP     AL, 87h             ; Wrap?, if AL <88 then Carry set\r
+    ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+    OUT     DX, AL              ; Set up New Bit Plane mask\r
+\r
+@DL_STLnc3:\r
+    ADD     DI, BP              ; advance to next line.\r
+    JMP     s @DL_STLLoop       ; Loop until done\r
+\r
+@DL_STLExit:\r
+    JMP     @DL_EXIT2           ; and exit\r
+\r
+    ; Draw a line that goes to the Right...\r
+\r
+@DL_DrawRight:\r
+    CMP     CX, DX              ; is Delta_X < Delta_Y?\r
+    JB      @DL_SteepRight      ; yes, so go do steep line\r
+                                ; (Delta_Y iterations)\r
+\r
+    ; Draw a Shallow line to the Right in Mode X\r
+\r
+@DL_ShallowRight:\r
+    mov ax,0                  ; zero low word of Delta_Y * 10000h\r
+    SUB     AX, DX              ; DX:AX <- DX * 0FFFFh\r
+    SBB     DX, 0               ; include carry\r
+    DIV     CX                  ; divide by Delta_X\r
+\r
+    MOV     SI, BX              ; SI = Accumulator\r
+    MOV     BX, AX              ; BX = Add Fraction\r
+    POP     AX                  ; Get Color, Bit mask\r
+    MOV     DX, SC_Data         ; Sequence controller data register\r
+    INC     CX                  ; Inc Delta_X so we can unroll loop\r
+\r
+    ; Loop (x2) to Draw Pixels, Move Right, and Maybe Down...\r
+\r
+@DL_SLRLoop:\r
+    MOV     ES:[DI], AH         ; set first pixel, mask is set up\r
+    LOOPjz  CX, @DL_SLRExit     ; Delta_X--, Exit if done..\r
+\r
+    ADD     SI, BX              ; add numerator to accumulator\r
+    JNC     @DL_SLR2nc          ; don't move down if carry not set\r
+\r
+    ADD     DI, BP              ; Move Down one line...\r
+\r
+@DL_SLR2nc:                     ; Now move right a pixel...\r
+    ROL     AL, 1               ; Move Right one addr if Plane = 0\r
+    CMP     AL, 12h             ; Wrap? if AL >12 then Carry not set\r
+    ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+    OUT     DX, AL              ; Set up New Bit Plane mask\r
+\r
+    MOV     ES:[DI], AH         ; set pixel\r
+    LOOPjz  CX, @DL_SLRExit     ; Delta_X--, Exit if done..\r
+\r
+    ADD     SI, BX              ; add numerator to accumulator\r
+    JNC     @DL_SLR3nc          ; don't move down if carry not set\r
+\r
+    ADD     DI, BP              ; Move Down one line...\r
+\r
+@DL_SLR3nc:\r
+    ROL     AL, 1               ; Move Right one addr if Plane = 0\r
+    CMP     AL, 12h             ; Wrap? if AL >12 then Carry not set\r
+    ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+    OUT     DX, AL              ; Set up New Bit Plane mask\r
+    JMP     s @DL_SLRLoop       ; loop till done\r
+\r
+@DL_SLRExit:\r
+    JMP     @DL_EXIT2           ; and exit\r
+\r
+    ; Draw a Steep line to the Right in Mode X\r
+\r
+@DL_SteepRight:\r
+    mov ax,0                  ; zero low word of Delta_Y * 10000h\r
+    XCHG    DX, CX              ; Delta_Y switched with Delta_X\r
+    DIV     CX                  ; divide by Delta_Y\r
+\r
+    MOV     SI, BX              ; SI = Accumulator\r
+    MOV     BX, AX              ; BX = Add Fraction\r
+    POP     AX                  ; Get Color, Bit mask\r
+    MOV     DX, SC_Data         ; Sequence controller data register\r
+    INC     CX                  ; Inc Delta_Y so we can unroll loop\r
+\r
+    ; Loop (x2) to Draw Pixels, Move Down, and Maybe Right\r
+\r
+@STRLoop:\r
+    MOV     ES:[DI], AH         ; set first pixel, mask is set up\r
+    LOOPjz  CX, @DL_EXIT2       ; Delta_Y--, Exit if Done\r
+\r
+    ADD     SI, BX              ; add numerator to accumulator\r
+    JNC     @STRnc2             ; if no carry then just go down...\r
+\r
+    ROL     AL, 1               ; Move Right one addr if Plane = 0\r
+    CMP     AL, 12h             ; Wrap? if AL >12 then Carry not set\r
+    ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+    OUT     DX, AL              ; Set up New Bit Plane mask\r
+\r
+@STRnc2:\r
+    ADD     DI, BP              ; advance to next line.\r
+\r
+    MOV     ES:[DI], AH         ; set pixel\r
+    LOOPjz  CX, @DL_EXIT2       ; Delta_Y--, Exit if Done\r
+\r
+    ADD     SI, BX              ; add numerator to accumulator\r
+    JNC     @STRnc3             ; if no carry then just go down...\r
+\r
+    ROL     AL, 1               ; Move Right one addr if Plane = 0\r
+    CMP     AL, 12h             ; Wrap? if AL >12 then Carry not set\r
+    ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+    OUT     DX, AL              ; Set up New Bit Plane mask\r
+\r
+@STRnc3:\r
+    ADD     DI, BP              ; advance to next line.\r
+    JMP     s @STRLoop          ; loop till done\r
+\r
+@DL_EXIT2:\r
+    ;POPx    DI, SI, BP          ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     bp\r
+    RET     10                  ; Exit and Clean up Stack\r
+\r
+DRAW_LINE        ENDP\r
+\r
+\r
+    ; ===== DAC COLOR REGISTER ROUTINES =====\r
+\r
+;=================================================\r
+;SET_DAC_REGISTER (Register%, Red%, Green%, Blue%)\r
+;=================================================\r
+;\r
+; Sets a single (RGB) Vga Palette Register\r
+;\r
+; ENTRY: Register = The DAC # to modify (0-255)\r
+;        Red      = The new Red Intensity (0-63)\r
+;        Green    = The new Green Intensity (0-63)\r
+;        Blue     = The new Blue Intensity (0-63)\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+SDR_STACK   STRUC\r
+                    DW  ?   ; BP\r
+                    DD  ?   ; Caller\r
+    SDR_Blue        DB  ?,? ; Blue Data Value\r
+    SDR_Green       DB  ?,? ; Green Data Value\r
+    SDR_Red         DB  ?,? ; Red Data Value\r
+    SDR_Register    DB  ?,? ; Palette Register #\r
+SDR_STACK   ENDS\r
+\r
+    PUBLIC  SET_DAC_REGISTER\r
+\r
+SET_DAC_REGISTER    PROC    FAR\r
+\r
+    PUSH    BP                  ; Save BP\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    ; Select which DAC Register to modify\r
+\r
+    OUT_8   DAC_WRITE_ADDR, [BP].SDR_Register\r
+\r
+    MOV     DX, PEL_DATA_REG    ; Dac Data Register\r
+    OUT_8   DX, [BP].SDR_Red    ; Set Red Intensity\r
+    OUT_8   DX, [BP].SDR_Green  ; Set Green Intensity\r
+    OUT_8   DX, [BP].SDR_Blue   ; Set Blue Intensity\r
+\r
+    POP     BP                  ; Restore Registers\r
+    RET     8                   ; Exit & Clean Up Stack\r
+\r
+SET_DAC_REGISTER    ENDP\r
+\r
+;====================================================\r
+;GET_DAC_REGISTER (Register%, &Red%, &Green%, &Blue%)\r
+;====================================================\r
+;\r
+; Reads the RGB Values of a single Vga Palette Register\r
+;\r
+; ENTRY: Register = The DAC # to read (0-255)\r
+;        Red      = Offset to Red Variable in DS\r
+;        Green    = Offset to Green Variable in DS\r
+;        Blue     = Offset to Blue Variable in DS\r
+;\r
+; EXIT:  The values of the integer variables Red,\r
+;        Green, and Blue are set to the values\r
+;        taken from the specified DAC register.\r
+;\r
+\r
+GDR_STACK   STRUC\r
+                    DW  ?   ; BP\r
+                    DD  ?   ; Caller\r
+    GDR_Blue        DW  ?   ; Addr of Blue Data Value in DS\r
+    GDR_Green       DW  ?   ; Addr of Green Data Value in DS\r
+    GDR_Red         DW  ?   ; Addr of Red Data Value in DS\r
+    GDR_Register    DB  ?,? ; Palette Register #\r
+GDR_STACK   ENDS\r
+\r
+    PUBLIC  GET_DAC_REGISTER\r
+\r
+GET_DAC_REGISTER    PROC    FAR\r
+\r
+    PUSH    BP                  ; Save BP\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    ; Select which DAC Register to read in\r
+\r
+    OUT_8   DAC_READ_ADDR, [BP].GDR_Register\r
+\r
+    MOV     DX, PEL_DATA_REG    ; Dac Data Register\r
+    mov ax,0                  ; Clear AX\r
+\r
+    IN      AL, DX              ; Read Red Value\r
+    MOV     BX, [BP].GDR_Red    ; Get Address of Red%\r
+    MOV     [BX], AX            ; *Red% = AX\r
+\r
+    IN      AL, DX              ; Read Green Value\r
+    MOV     BX, [BP].GDR_Green  ; Get Address of Green%\r
+    MOV     [BX], AX            ; *Green% = AX\r
+\r
+    IN      AL, DX              ; Read Blue Value\r
+    MOV     BX, [BP].GDR_Blue   ; Get Address of Blue%\r
+    MOV     [BX], AX            ; *Blue% = AX\r
+\r
+    POP     BP                  ; Restore Registers\r
+    RET     8                   ; Exit & Clean Up Stack\r
+\r
+GET_DAC_REGISTER    ENDP\r
+\r
+\r
+;===========================================================\r
+;LOAD_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%, Sync%)\r
+;===========================================================\r
+;\r
+; Sets a Block of Vga Palette Registers\r
+;\r
+; ENTRY: PalData  = Far Pointer to Block of palette data\r
+;        StartReg = First Register # in range to set (0-255)\r
+;        EndReg   = Last Register # in Range to set (0-255)\r
+;        Sync     = Wait for Vertical Retrace Flag (Boolean)\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+; NOTES: PalData is a linear array of 3 byte Palette values\r
+;        in the order: Red  (0-63), Green (0-63), Blue (0-63)\r
+;\r
+\r
+LDR_STACK   STRUC\r
+                    DW  ?x1 ; BP, DS, SI\r
+                    DW  ?x1 ; BP, DS, SI\r
+                    DW  ?x1 ; BP, DS, SI\r
+                    DD  ?   ; Caller\r
+    LDR_Sync        DW  ?   ; Vertical Sync Flag\r
+    LDR_EndReg      DB  ?,? ; Last Register #\r
+    LDR_StartReg    DB  ?,? ; First Register #\r
+    LDR_PalData     DD  ?   ; Far Ptr to Palette Data\r
+LDR_STACK   ENDS\r
+\r
+    PUBLIC  LOAD_DAC_REGISTERS\r
+\r
+LOAD_DAC_REGISTERS  PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI          ; Save Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+    mov     BP, SP              ; Set up Stack Frame\r
+\r
+    mov     AX, [BP].LDR_Sync   ; Get Vertical Sync Flag\r
+    or      AX, AX              ; is Sync Flag = 0?\r
+    jz      @LDR_Load           ; if so, skip call\r
+\r
+    call    f SYNC_DISPLAY      ; wait for vsync\r
+\r
+    ; Determine register #'s, size to copy, etc\r
+\r
+@LDR_Load:\r
+\r
+    lds     SI, [BP].LDR_PalData    ; DS:SI -> Palette Data\r
+    mov     DX, DAC_WRITE_ADDR      ; DAC register # selector\r
+\r
+    mov ax,0, BX                  ; Clear for byte loads\r
+    mov     AL, [BP].LDR_StartReg   ; Get Start Register\r
+    mov     BL, [BP].LDR_EndReg     ; Get End Register\r
+\r
+    sub     BX, AX              ; BX = # of DAC registers -1\r
+    inc     BX                  ; BX = # of DAC registers\r
+    mov     CX, BX              ; CX = # of DAC registers\r
+    add     CX, BX              ; CX =  "   " * 2\r
+    add     CX, BX              ; CX =  "   " * 3\r
+    cld                         ; Block OUTs forward\r
+    out     DX, AL              ; set up correct register #\r
+\r
+    ; Load a block of DAC Registers\r
+\r
+    mov     DX, PEL_DATA_REG    ; Dac Data Register\r
+\r
+    ;rep     outsb               ; block set DAC registers\r
+\r
+    ;POPx    SI, DS, BP          ; Restore Registers\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    ret     10                  ; Exit & Clean Up Stack\r
+\r
+LOAD_DAC_REGISTERS  ENDP\r
+\r
+\r
+;====================================================\r
+;READ_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%)\r
+;====================================================\r
+;\r
+; Reads a Block of Vga Palette Registers\r
+;\r
+; ENTRY: PalData  = Far Pointer to block to store palette data\r
+;        StartReg = First Register # in range to read (0-255)\r
+;        EndReg   = Last Register # in Range to read (0-255)\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+; NOTES: PalData is a linear array of 3 byte Palette values\r
+;        in the order: Red  (0-63), Green (0-63), Blue (0-63)\r
+;\r
+\r
+RDR_STACK   STRUC\r
+                    DW  ?x1 ; BP, ES, DI\r
+                    DW  ?x1 ; BP, ES, DI\r
+                    DW  ?x1 ; BP, ES, DI\r
+                    DD  ?   ; Caller\r
+    RDR_EndReg      DB  ?,? ; Last Register #\r
+    RDR_StartReg    DB  ?,? ; First Register #\r
+    RDR_PalData     DD  ?   ; Far Ptr to Palette Data\r
+RDR_STACK   ENDS\r
+\r
+    PUBLIC  READ_DAC_REGISTERS\r
+\r
+READ_DAC_REGISTERS  PROC    FAR\r
+\r
+    ;PUSHx   BP, ES, DI          ; Save Registers\r
+    push       bp\r
+       push    es\r
+       push    di\r
+    mov     BP, SP              ; Set up Stack Frame\r
+\r
+    ; Determine register #'s, size to copy, etc\r
+\r
+    les     DI, [BP].RDR_PalData    ; ES:DI -> Palette Buffer\r
+    mov     DX, DAC_READ_ADDR       ; DAC register # selector\r
+\r
+    mov ax,0, BX                  ; Clear for byte loads\r
+    mov     AL, [BP].RDR_StartReg   ; Get Start Register\r
+    mov     BL, [BP].RDR_EndReg     ; Get End Register\r
+\r
+    sub     BX, AX              ; BX = # of DAC registers -1\r
+    inc     BX                  ; BX = # of DAC registers\r
+    mov     CX, BX              ; CX = # of DAC registers\r
+    add     CX, BX              ; CX =  "   " * 2\r
+    add     CX, BX              ; CX =  "   " * 3\r
+    cld                         ; Block INs forward\r
+\r
+    ; Read a block of DAC Registers\r
+\r
+    out     DX, AL              ; set up correct register #\r
+    mov     DX, PEL_DATA_REG    ; Dac Data Register\r
+\r
+    ;rep     insb                ; block read DAC registers\r
+\r
+    ;POPx    DI, ES, BP          ; Restore Registers\r
+    pop        di\r
+       pop     es\r
+       pop     bp\r
+    ret     8                   ; Exit & Clean Up Stack\r
+\r
+READ_DAC_REGISTERS  ENDP\r
+\r
+\r
+    ; ===== PAGE FLIPPING AND SCROLLING ROUTINES =====\r
+\r
+;=========================\r
+;SET_ACTIVE_PAGE (PageNo%)\r
+;=========================\r
+;\r
+; Sets the active display Page to be used for future drawing\r
+;\r
+; ENTRY: PageNo = Display Page to make active\r
+;        (values: 0 to Number of Pages - 1)\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+SAP_STACK   STRUC\r
+                DW  ?   ; BP\r
+                DD  ?   ; Caller\r
+    SAP_Page    DW  ?   ; Page # for Drawing\r
+SAP_STACK   ENDS\r
+\r
+    PUBLIC  SET_ACTIVE_PAGE\r
+\r
+SET_ACTIVE_PAGE PROC    FAR\r
+\r
+    PUSH    BP                  ; Preserve Registers\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    MOV     BX, [BP].SAP_Page   ; Get Desired Page #\r
+    CMP     BX, LAST_PAGE       ; Is Page # Valid?\r
+    JAE     @SAP_Exit           ; IF Not, Do Nothing\r
+\r
+    MOV     ACTIVE_PAGE, BX     ; Set Active Page #\r
+\r
+    SHL     BX, 1               ; Scale Page # to Word\r
+    MOV     AX, PAGE_ADDR[BX]   ; Get offset to Page\r
+\r
+    MOV     CURRENT_PAGE, AX    ; And set for future LES's\r
+\r
+@SAP_Exit:\r
+    POP     BP                  ; Restore Registers\r
+    RET     2                   ; Exit and Clean up Stack\r
+\r
+SET_ACTIVE_PAGE ENDP\r
+\r
+\r
+;================\r
+;GET_ACTIVE_PAGE%\r
+;================\r
+;\r
+; Returns the Video Page # currently used for Drawing\r
+;\r
+; ENTRY: No Parameters are passed\r
+;\r
+; EXIT:  AX = Current Video Page used for Drawing\r
+;\r
+\r
+    PUBLIC  GET_ACTIVE_PAGE\r
+\r
+GET_ACTIVE_PAGE PROC    FAR\r
+\r
+    MOV     AX, ACTIVE_PAGE     ; Get Active Page #\r
+    RET                         ; Exit and Clean up Stack\r
+\r
+GET_ACTIVE_PAGE ENDP\r
+\r
+\r
+;===============================\r
+;SET_DISPLAY_PAGE (DisplayPage%)\r
+;===============================\r
+;\r
+; Sets the currently visible display page.\r
+; When called this routine syncronizes the display\r
+; to the vertical blank.\r
+;\r
+; ENTRY: PageNo = Display Page to show on the screen\r
+;        (values: 0 to Number of Pages - 1)\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+SDP_STACK   STRUC\r
+                DW  ?       ; BP\r
+                DD  ?       ; Caller\r
+    SDP_Page    DW  ?       ; Page # to Display...\r
+SDP_STACK   ENDS\r
+\r
+    PUBLIC  SET_DISPLAY_PAGE\r
+\r
+SET_DISPLAY_PAGE    PROC    FAR\r
+\r
+    PUSH    BP                  ; Preserve Registers\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    MOV     BX, [BP].SDP_Page   ; Get Desired Page #\r
+    CMP     BX, LAST_PAGE       ; Is Page # Valid?\r
+    JAE     @SDP_Exit           ; IF Not, Do Nothing\r
+\r
+    MOV     DISPLAY_PAGE, BX    ; Set Display Page #\r
+\r
+    SHL     BX, 1               ; Scale Page # to Word\r
+    MOV     CX, PAGE_ADDR[BX]   ; Get offset in memory to Page\r
+    ADD     CX, CURRENT_MOFFSET ; Adjust for any scrolling\r
+\r
+    ; Wait if we are currently in a Vertical Retrace\r
+\r
+    MOV     DX, INPUT_1         ; Input Status #1 Register\r
+\r
+@DP_WAIT0:\r
+    IN      AL, DX              ; Get VGA status\r
+    AND     AL, VERT_RETRACE    ; In Display mode yet?\r
+    JNZ     @DP_WAIT0           ; If Not, wait for it\r
+\r
+    ; Set the Start Display Address to the new page\r
+\r
+    MOV     DX, CRTC_Index      ; We Change the VGA Sequencer\r
+\r
+    MOV     AL, START_DISP_LO   ; Display Start Low Register\r
+    MOV     AH, CL              ; Low 8 Bits of Start Addr\r
+    OUT     DX, AX              ; Set Display Addr Low\r
+\r
+    MOV     AL, START_DISP_HI   ; Display Start High Register\r
+    MOV     AH, CH              ; High 8 Bits of Start Addr\r
+    OUT     DX, AX              ; Set Display Addr High\r
+\r
+    ; Wait for a Vertical Retrace to smooth out things\r
+\r
+    MOV     DX, INPUT_1         ; Input Status #1 Register\r
+\r
+@DP_WAIT1:\r
+    IN      AL, DX              ; Get VGA status\r
+    AND     AL, VERT_RETRACE    ; Vertical Retrace Start?\r
+    JZ      @DP_WAIT1           ; If Not, wait for it\r
+\r
+    ; Now Set Display Starting Address\r
+\r
+\r
+@SDP_Exit:\r
+    POP     BP                  ; Restore Registers\r
+    RET     2                   ; Exit and Clean up Stack\r
+\r
+SET_DISPLAY_PAGE    ENDP\r
+\r
+\r
+;=================\r
+;GET_DISPLAY_PAGE%\r
+;=================\r
+;\r
+; Returns the Video Page # currently displayed\r
+;\r
+; ENTRY: No Parameters are passed\r
+;\r
+; EXIT:  AX = Current Video Page being displayed\r
+;\r
+\r
+    PUBLIC  GET_DISPLAY_PAGE\r
+\r
+GET_DISPLAY_PAGE    PROC    FAR\r
+\r
+    MOV     AX, DISPLAY_PAGE    ; Get Display Page #\r
+    RET                         ; Exit & Clean Up Stack\r
+\r
+GET_DISPLAY_PAGE    ENDP\r
+\r
+\r
+;=======================================\r
+;SET_WINDOW (DisplayPage%, Xpos%, Ypos%)\r
+;=======================================\r
+;\r
+; Since a Logical Screen can be larger than the Physical\r
+; Screen, Scrolling is possible.  This routine sets the\r
+; Upper Left Corner of the Screen to the specified Pixel.\r
+; Also Sets the Display page to simplify combined page\r
+; flipping and scrolling.  When called this routine\r
+; syncronizes the display to the vertical blank.\r
+;\r
+; ENTRY: DisplayPage = Display Page to show on the screen\r
+;        Xpos        = # of pixels to shift screen right\r
+;        Ypos        = # of lines to shift screen down\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+SW_STACK    STRUC\r
+                DW  ?   ; BP\r
+                DD  ?   ; Caller\r
+    SW_Ypos     DW  ?   ; Y pos of UL Screen Corner\r
+    SW_Xpos     DW  ?   ; X pos of UL Screen Corner\r
+    SW_Page     DW  ?   ; (new) Display Page\r
+SW_STACK    ENDS\r
+\r
+        PUBLIC SET_WINDOW\r
+\r
+SET_WINDOW  PROC    FAR\r
+\r
+    PUSH    BP                  ; Preserve Registers\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    ; Check if our Scroll Offsets are Valid\r
+\r
+    MOV     BX, [BP].SW_Page    ; Get Desired Page #\r
+    CMP     BX, LAST_PAGE       ; Is Page # Valid?\r
+    JAE     @SW_Exit            ; IF Not, Do Nothing\r
+\r
+    MOV     AX, [BP].SW_Ypos    ; Get Desired Y Offset\r
+    CMP     AX, MAX_YOFFSET     ; Is it Within Limits?\r
+    JA      @SW_Exit            ; if not, exit\r
+\r
+    MOV     CX, [BP].SW_Xpos    ; Get Desired X Offset\r
+    CMP     CX, MAX_XOFFSET     ; Is it Within Limits?\r
+    JA      @SW_Exit            ; if not, exit\r
+\r
+    ; Compute proper Display start address to use\r
+\r
+    MUL     SCREEN_WIDTH        ; AX = YOffset * Line Width\r
+    SHR     CX, 1               ; CX / 4 = Bytes into Line\r
+    SHR     CX, 1               ; CX / 4 = Bytes into Line\r
+    ADD     AX, CX              ; AX = Offset of Upper Left Pixel\r
+\r
+    MOV     CURRENT_MOFFSET, AX ; Save Offset Info\r
+\r
+    MOV     DISPLAY_PAGE, BX    ; Set Current Page #\r
+    SHL     BX, 1               ; Scale Page # to Word\r
+    ADD     AX, PAGE_ADDR[BX]   ; Get offset in VGA to Page\r
+    MOV     BX, AX              ; BX = Desired Display Start\r
+\r
+    MOV     DX, INPUT_1         ; Input Status #1 Register\r
+\r
+    ; Wait if we are currently in a Vertical Retrace\r
+\r
+@SW_WAIT0:\r
+    IN      AL, DX              ; Get VGA status\r
+    AND     AL, VERT_RETRACE    ; In Display mode yet?\r
+    JNZ     @SW_WAIT0           ; If Not, wait for it\r
+\r
+    ; Set the Start Display Address to the new window\r
+\r
+    MOV     DX, CRTC_Index      ; We Change the VGA Sequencer\r
+    MOV     AL, START_DISP_LO   ; Display Start Low Register\r
+    MOV     AH, BL              ; Low 8 Bits of Start Addr\r
+    OUT     DX, AX              ; Set Display Addr Low\r
+\r
+    MOV     AL, START_DISP_HI   ; Display Start High Register\r
+    MOV     AH, BH              ; High 8 Bits of Start Addr\r
+    OUT     DX, AX              ; Set Display Addr High\r
+\r
+    ; Wait for a Vertical Retrace to smooth out things\r
+\r
+    MOV     DX, INPUT_1         ; Input Status #1 Register\r
+\r
+@SW_WAIT1:\r
+    IN      AL, DX              ; Get VGA status\r
+    AND     AL, VERT_RETRACE    ; Vertical Retrace Start?\r
+    JZ      @SW_WAIT1           ; If Not, wait for it\r
+\r
+    ; Now Set the Horizontal Pixel Pan values\r
+\r
+    OUT_8   ATTRIB_Ctrl, PIXEL_PAN_REG  ; Select Pixel Pan Register\r
+\r
+    MOV     AX, [BP].SW_Xpos    ; Get Desired X Offset\r
+    AND     AL, 03              ; Get # of Pixels to Pan (0-3)\r
+    SHL     AL, 1               ; Shift for 256 Color Mode\r
+    OUT     DX, AL              ; Fine tune the display!\r
+\r
+@SW_Exit:\r
+    POP     BP                  ; Restore Saved Registers\r
+    RET     6                   ; Exit and Clean up Stack\r
+\r
+SET_WINDOW        ENDP\r
+\r
+\r
+;=============\r
+;GET_X_OFFSET%\r
+;=============\r
+;\r
+; Returns the X coordinate of the Pixel currently display\r
+; in the upper left corner of the display\r
+;\r
+; ENTRY: No Parameters are passed\r
+;\r
+; EXIT:  AX = Current Horizontal Scroll Offset\r
+;\r
+\r
+    PUBLIC  GET_X_OFFSET\r
+\r
+GET_X_OFFSET    PROC    FAR\r
+\r
+    MOV     AX, CURRENT_XOFFSET ; Get current horz offset\r
+    RET                         ; Exit & Clean Up Stack\r
+\r
+GET_X_OFFSET    ENDP\r
+\r
+\r
+;=============\r
+;GET_Y_OFFSET%\r
+;=============\r
+;\r
+; Returns the Y coordinate of the Pixel currently display\r
+; in the upper left corner of the display\r
+;\r
+; ENTRY: No Parameters are passed\r
+;\r
+; EXIT:  AX = Current Vertical Scroll Offset\r
+;\r
+\r
+    PUBLIC  GET_Y_OFFSET\r
+\r
+GET_Y_OFFSET    PROC    FAR\r
+\r
+    MOV     AX, CURRENT_YOFFSET ; Get current vertical offset\r
+    RET                         ; Exit & Clean Up Stack\r
+\r
+GET_Y_OFFSET    ENDP\r
+\r
+\r
+;============\r
+;SYNC_DISPLAY\r
+;============\r
+;\r
+; Pauses the computer until the next Vertical Retrace starts\r
+;\r
+; ENTRY: No Parameters are passed\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+    PUBLIC  SYNC_DISPLAY\r
+\r
+SYNC_DISPLAY    PROC    FAR\r
+\r
+    MOV     DX, INPUT_1         ; Input Status #1 Register\r
+\r
+    ; Wait for any current retrace to end\r
+\r
+@SD_WAIT0:\r
+    IN      AL, DX              ; Get VGA status\r
+    AND     AL, VERT_RETRACE    ; In Display mode yet?\r
+    JNZ     @SD_WAIT0           ; If Not, wait for it\r
+\r
+    ; Wait for the start of the next vertical retrace\r
+\r
+@SD_WAIT1:\r
+    IN      AL, DX              ; Get VGA status\r
+    AND     AL, VERT_RETRACE    ; Vertical Retrace Start?\r
+    JZ      @SD_WAIT1           ; If Not, wait for it\r
+\r
+    RET                         ; Exit & Clean Up Stack\r
+\r
+SYNC_DISPLAY    ENDP\r
+\r
+\r
+    ; ===== TEXT DISPLAY ROUTINES =====\r
+\r
+;==================================================\r
+;GPRINTC (CharNum%, Xpos%, Ypos%, ColorF%, ColorB%)\r
+;==================================================\r
+;\r
+; Draws an ASCII Text Character using the currently selected\r
+; 8x8 font on the active display page.  It would be a simple\r
+; exercise to make this routine process variable height fonts.\r
+;\r
+; ENTRY: CharNum = ASCII character # to draw\r
+;        Xpos    = X position to draw Character at\r
+;        Ypos    = Y position of to draw Character at\r
+;        ColorF  = Color to draw text character in\r
+;        ColorB  = Color to set background to\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+GPC_STACK   STRUC\r
+    GPC_Width   DW  ?   ; Screen Width-1\r
+    GPC_Lines   DB  ?,? ; Scan lines to Decode\r
+    GPC_T_SETS  DW  ?   ; Saved Charset Segment\r
+    GPC_T_SETO  DW  ?   ; Saved Charset Offset\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DD  ?   ; Caller\r
+    GPC_ColorB  DB  ?,? ; Background Color\r
+    GPC_ColorF  DB  ?,? ; Text Color\r
+    GPC_Ypos    DW  ?   ; Y Position to Print at\r
+    GPC_Xpos    DW  ?   ; X position to Print at\r
+    GPC_Char    DB  ?,? ; Character to Print\r
+GPC_STACK   ENDS\r
+\r
+        PUBLIC GPRINTC\r
+\r
+GPRINTC     PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+       push    di\r
+    SUB     SP, 8               ; Allocate WorkSpace on Stack\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+\r
+    MOV     AX, SCREEN_WIDTH    ; Get Logical Line Width\r
+    MOV     BX, AX              ; BX = Screen Width\r
+    DEC     BX                  ;    = Screen Width-1\r
+    MOV     [BP].GPC_Width, BX  ; Save for later use\r
+\r
+    MUL     [BP].GPC_Ypos       ; Start of Line = Ypos * Width\r
+    ADD     DI, AX              ; DI -> Start of Line Ypos\r
+\r
+    MOV     AX, [BP].GPC_Xpos   ; Get Xpos of Character\r
+    MOV     CX, AX              ; Save Copy of Xpos\r
+    SHR     AX, 1               ; Bytes into Line = Xpos/4\r
+    SHR     AX, 1               ; Bytes into Line = Xpos/4\r
+    ADD     DI, AX              ; DI -> (Xpos, Ypos)\r
+\r
+    ;Get Source ADDR of Character Bit Map  & Save\r
+\r
+    MOV     AL, [BP].GPC_Char   ; Get Character #\r
+    TEST    AL, 080h            ; Is Hi Bit Set?\r
+    JZ      @GPC_LowChar        ; Nope, use low char set ptr\r
+\r
+    AND     AL, 07Fh            ; Mask Out Hi Bit\r
+    MOV     BX, CHARSET_HI      ; BX = Char Set Ptr:Offset\r
+    MOV     DX, CHARSET_HI+2    ; DX = Char Set Ptr:Segment\r
+    JMP     s @GPC_Set_Char     ; Go Setup Character Ptr\r
+\r
+@GPC_LowChar:\r
+\r
+    MOV     BX, CHARSET_LOW     ; BX = Char Set Ptr:Offset\r
+    MOV     DX, CHARSET_LOW+2   ; DX = Char Set Ptr:Segment\r
+\r
+@GPC_Set_Char:\r
+    MOV     [BP].GPC_T_SETS, DX ; Save Segment on Stack\r
+\r
+    MOV     AH, 0               ; Valid #'s are 0..127\r
+    SHL     AX, 1               ; * 8 Bytes Per Bitmap\r
+    SHL     AX, 1               ; * 8 Bytes Per Bitmap\r
+    SHL     AX, 1               ; * 8 Bytes Per Bitmap\r
+    ADD     BX, AX              ; BX = Offset of Selected char\r
+    MOV     [BP].GPC_T_SETO, BX ; Save Offset on Stack\r
+\r
+    AND     CX, PLANE_BITS      ; Get Plane #\r
+    MOV     CH, ALL_PLANES      ; Get Initial Plane mask\r
+    SHL     CH, CL              ; And shift into position\r
+    AND     CH, ALL_PLANES      ; And mask to lower nibble\r
+\r
+    MOV     AL, 04              ; 4-Plane # = # of initial\r
+    SUB     AL, CL              ; shifts to align bit mask\r
+    MOV     CL, AL              ; Shift Count for SHL\r
+\r
+    ;Get segment of character map\r
+\r
+    OUT_8   SC_Index, MAP_MASK  ; Setup Plane selections\r
+    INC     DX                  ; DX -> SC_Data\r
+\r
+    MOV     AL, 08              ; 8 Lines to Process\r
+    MOV     [BP].GPC_Lines, AL  ; Save on Stack\r
+\r
+    MOV     DS, [BP].GPC_T_SETS ; Point to character set\r
+\r
+@GPC_DECODE_CHAR_BYTE:\r
+\r
+    MOV     SI, [BP].GPC_T_SETO ; Get DS:SI = String\r
+\r
+    MOV     BH, [SI]            ; Get Bit Map\r
+    INC     SI                  ; Point to Next Line\r
+    MOV     [BP].GPC_T_SETO, SI ; And save new Pointer...\r
+\r
+    mov ax,0                  ; Clear AX\r
+\r
+    ;mov bl,0                      ; Clear BL\r
+    mov bl,0\r
+    ROL     BX, CL                  ; BL holds left edge bits\r
+    MOV     SI, BX                  ; Use as Table Index\r
+    AND     SI, CHAR_BITS           ; Get Low Bits\r
+    MOV     AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+    JZ      @GPC_NO_LEFT1BITS       ; Skip if No Pixels to set\r
+\r
+    MOV     AH, [BP].GPC_ColorF ; Get Foreground Color\r
+    OUT     DX, AL              ; Set up Screen Mask\r
+    MOV     ES:[DI], AH         ; Write Foreground color\r
+\r
+@GPC_NO_LEFT1BITS:\r
+    XOR     AL, CH              ; Invert mask for Background\r
+    JZ      @GPC_NO_LEFT0BITS   ; Hey, no need for this\r
+\r
+    MOV     AH, [BP].GPC_ColorB ; Get background Color\r
+    OUT     DX, AL              ; Set up Screen Mask\r
+    MOV     ES:[DI], AH         ; Write Foreground color\r
+\r
+    ;Now Do Middle/Last Band\r
+\r
+@GPC_NO_LEFT0BITS:\r
+    INC     DI                  ; Point to next Byte\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+\r
+    MOV     SI, BX                  ; Make Lookup Pointer\r
+    AND     SI, CHAR_BITS           ; Get Low Bits\r
+    MOV     AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+    JZ      @GPC_NO_MIDDLE1BITS     ; Skip if no pixels to set\r
+\r
+    MOV     AH, [BP].GPC_ColorF ; Get Foreground Color\r
+    OUT     DX, AL              ; Set up Screen Mask\r
+    MOV     ES:[DI], AH         ; Write Foreground color\r
+\r
+@GPC_NO_MIDDLE1BITS:\r
+    XOR     AL, ALL_PLANES      ; Invert mask for Background\r
+    JZ      @GPC_NO_MIDDLE0BITS ; Hey, no need for this\r
+\r
+    MOV     AH, [BP].GPC_ColorB ; Get background Color\r
+    OUT     DX, AL              ; Set up Screen Mask\r
+    MOV     ES:[DI], AH         ; Write Foreground color\r
+\r
+@GPC_NO_MIDDLE0BITS:\r
+    XOR     CH, ALL_PLANES      ; Invert Clip Mask\r
+    CMP     CL, 4               ; Aligned by 4?\r
+    JZ      @GPC_NEXT_LINE      ; If so, Exit now..\r
+\r
+    INC     DI                  ; Point to next Byte\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+\r
+    MOV     SI, BX                  ; Make Lookup Pointer\r
+    AND     SI, CHAR_BITS           ; Get Low Bits\r
+    MOV     AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+    JZ      @GPC_NO_RIGHT1BITS      ; Skip if No Pixels to set\r
+\r
+    MOV     AH, [BP].GPC_ColorF ; Get Foreground Color\r
+    OUT     DX, AL              ; Set up Screen Mask\r
+    MOV     ES:[DI], AH         ; Write Foreground color\r
+\r
+@GPC_NO_RIGHT1BITS:\r
+\r
+    XOR     AL, CH              ; Invert mask for Background\r
+    JZ      @GPC_NO_RIGHT0BITS  ; Hey, no need for this\r
+\r
+    MOV     AH, [BP].GPC_ColorB ; Get background Color\r
+    OUT     DX, AL              ; Set up Screen Mask\r
+    MOV     ES:[DI], AH         ; Write Foreground color\r
+\r
+@GPC_NO_RIGHT0BITS:\r
+    DEC     DI                  ; Adjust for Next Line Advance\r
+\r
+@GPC_NEXT_LINE:\r
+    ADD     DI, [BP].GPC_Width  ; Point to Next Line\r
+    XOR     CH, CHAR_BITS       ; Flip the Clip mask back\r
+\r
+    DEC     [BP].GPC_Lines      ; Count Down Lines\r
+    JZ      @GPC_EXIT           ; Ok... Done!\r
+\r
+    JMP     @GPC_DECODE_CHAR_BYTE   ; Again! Hey!\r
+\r
+@GPC_EXIT:\r
+    ADD     SP, 08              ; Deallocate stack workspace\r
+    ;POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    RET     10                  ; Exit and Clean up Stack\r
+\r
+GPRINTC  ENDP\r
+\r
+\r
+;==========================================\r
+;TGPRINTC (CharNum%, Xpos%, Ypos%, ColorF%)\r
+;==========================================\r
+;\r
+; Transparently draws an ASCII Text Character using the\r
+; currently selected 8x8 font on the active display page.\r
+;\r
+; ENTRY: CharNum = ASCII character # to draw\r
+;        Xpos    = X position to draw Character at\r
+;        Ypos    = Y position of to draw Character at\r
+;        ColorF  = Color to draw text character in\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+TGP_STACK   STRUC\r
+    TGP_Width   DW  ?   ; Screen Width-1\r
+    TGP_Lines   DB  ?,? ; Scan lines to Decode\r
+    TGP_T_SETS  DW  ?   ; Saved Charset Segment\r
+    TGP_T_SETO  DW  ?   ; Saved Charset Offset\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DD  ?   ; Caller\r
+    TGP_ColorF  DB  ?,? ; Text Color\r
+    TGP_Ypos    DW  ?   ; Y Position to Print at\r
+    TGP_Xpos    DW  ?   ; X position to Print at\r
+    TGP_Char    DB  ?,? ; Character to Print\r
+TGP_STACK   ENDS\r
+\r
+        PUBLIC TGPRINTC\r
+\r
+TGPRINTC    PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+       push    di\r
+    SUB     SP, 8               ; Allocate WorkSpace on Stack\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+\r
+    MOV     AX, SCREEN_WIDTH    ; Get Logical Line Width\r
+    MOV     BX, AX              ; BX = Screen Width\r
+    DEC     BX                  ;    = Screen Width-1\r
+    MOV     [BP].TGP_Width, BX  ; Save for later use\r
+\r
+    MUL     [BP].TGP_Ypos       ; Start of Line = Ypos * Width\r
+    ADD     DI, AX              ; DI -> Start of Line Ypos\r
+\r
+    MOV     AX, [BP].TGP_Xpos   ; Get Xpos of Character\r
+    MOV     CX, AX              ; Save Copy of Xpos\r
+    SHR     AX, 1               ; Bytes into Line = Xpos/4\r
+    SHR     AX, 1               ; Bytes into Line = Xpos/4\r
+    ADD     DI, AX              ; DI -> (Xpos, Ypos)\r
+\r
+    ;Get Source ADDR of Character Bit Map  & Save\r
+\r
+    MOV     AL, [BP].TGP_Char   ; Get Character #\r
+    TEST    AL, 080h            ; Is Hi Bit Set?\r
+    JZ      @TGP_LowChar        ; Nope, use low char set ptr\r
+\r
+    AND     AL, 07Fh            ; Mask Out Hi Bit\r
+    MOV     BX, CHARSET_HI      ; BX = Char Set Ptr:Offset\r
+    MOV     DX, CHARSET_HI+2    ; DX = Char Set Ptr:Segment\r
+    JMP     s @TGP_Set_Char     ; Go Setup Character Ptr\r
+\r
+@TGP_LowChar:\r
+\r
+    MOV     BX, CHARSET_LOW     ; BX = Char Set Ptr:Offset\r
+    MOV     DX, CHARSET_LOW+2   ; DX = Char Set Ptr:Segment\r
+\r
+@TGP_Set_Char:\r
+    MOV     [BP].TGP_T_SETS, DX ; Save Segment on Stack\r
+\r
+    MOV     AH, 0               ; Valid #'s are 0..127\r
+    SHL     AX, 1               ; * 8 Bytes Per Bitmap\r
+    SHL     AX, 1               ; * 8 Bytes Per Bitmap\r
+    SHL     AX, 1               ; * 8 Bytes Per Bitmap\r
+    ADD     BX, AX              ; BX = Offset of Selected char\r
+    MOV     [BP].TGP_T_SETO, BX ; Save Offset on Stack\r
+\r
+    AND     CX, PLANE_BITS      ; Get Plane #\r
+    MOV     CH, ALL_PLANES      ; Get Initial Plane mask\r
+    SHL     CH, CL              ; And shift into position\r
+    AND     CH, ALL_PLANES      ; And mask to lower nibble\r
+\r
+    MOV     AL, 04              ; 4-Plane # = # of initial\r
+    SUB     AL, CL              ; shifts to align bit mask\r
+    MOV     CL, AL              ; Shift Count for SHL\r
+\r
+    ;Get segment of character map\r
+\r
+    OUT_8   SC_Index, MAP_MASK  ; Setup Plane selections\r
+    INC     DX                  ; DX -> SC_Data\r
+\r
+    MOV     AL, 08              ; 8 Lines to Process\r
+    MOV     [BP].TGP_Lines, AL  ; Save on Stack\r
+\r
+    MOV     DS, [BP].TGP_T_SETS ; Point to character set\r
+\r
+@TGP_DECODE_CHAR_BYTE:\r
+\r
+    MOV     SI, [BP].TGP_T_SETO ; Get DS:SI = String\r
+\r
+    MOV     BH, [SI]            ; Get Bit Map\r
+    INC     SI                  ; Point to Next Line\r
+    MOV     [BP].TGP_T_SETO, SI ; And save new Pointer...\r
+\r
+    MOV     AH, [BP].TGP_ColorF ; Get Foreground Color\r
+\r
+    mov bl,0                      ; Clear BL\r
+    ROL     BX, CL                  ; BL holds left edge bits\r
+    MOV     SI, BX                  ; Use as Table Index\r
+    AND     SI, CHAR_BITS           ; Get Low Bits\r
+    MOV     AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+    JZ      @TGP_NO_LEFT1BITS       ; Skip if No Pixels to set\r
+\r
+    OUT     DX, AL              ; Set up Screen Mask\r
+    MOV     ES:[DI], AH         ; Write Foreground color\r
+\r
+    ;Now Do Middle/Last Band\r
+\r
+@TGP_NO_LEFT1BITS:\r
+\r
+    INC     DI                  ; Point to next Byte\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+\r
+    MOV     SI, BX                  ; Make Lookup Pointer\r
+    AND     SI, CHAR_BITS           ; Get Low Bits\r
+    MOV     AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+    JZ      @TGP_NO_MIDDLE1BITS     ; Skip if no pixels to set\r
+\r
+    OUT     DX, AL              ; Set up Screen Mask\r
+    MOV     ES:[DI], AH         ; Write Foreground color\r
+\r
+@TGP_NO_MIDDLE1BITS:\r
+    XOR     CH, ALL_PLANES      ; Invert Clip Mask\r
+    CMP     CL, 4               ; Aligned by 4?\r
+    JZ      @TGP_NEXT_LINE      ; If so, Exit now..\r
+\r
+    INC     DI                  ; Point to next Byte\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+    ROL     BX, 1               ; Shift 4 bits\r
+\r
+    MOV     SI, BX                  ; Make Lookup Pointer\r
+    AND     SI, CHAR_BITS           ; Get Low Bits\r
+    MOV     AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+    JZ      @TGP_NO_RIGHT1BITS      ; Skip if No Pixels to set\r
+\r
+    OUT     DX, AL              ; Set up Screen Mask\r
+    MOV     ES:[DI], AH         ; Write Foreground color\r
+\r
+@TGP_NO_RIGHT1BITS:\r
+\r
+    DEC     DI                  ; Adjust for Next Line Advance\r
+\r
+@TGP_NEXT_LINE:\r
+    ADD     DI, [BP].TGP_Width  ; Point to Next Line\r
+    XOR     CH, CHAR_BITS       ; Flip the Clip mask back\r
+\r
+    DEC     [BP].TGP_Lines      ; Count Down Lines\r
+    JZ      @TGP_EXIT           ; Ok... Done!\r
+\r
+    JMP     @TGP_DECODE_CHAR_BYTE   ; Again! Hey!\r
+\r
+@TGP_EXIT:\r
+    ADD     SP, 08              ; Deallocate stack workspace\r
+    ;POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    RET     8                   ; Exit and Clean up Stack\r
+\r
+TGPRINTC    ENDP\r
+\r
+\r
+;===============================================================\r
+;PRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%)\r
+;===============================================================\r
+;\r
+; Routine to quickly Print a null terminated ASCII string on the\r
+; active display page up to a maximum length.\r
+;\r
+; ENTRY: String  = Far Pointer to ASCII string to print\r
+;        MaxLen  = # of characters to print if no null found\r
+;        Xpos    = X position to draw Text at\r
+;        Ypos    = Y position of to draw Text at\r
+;        ColorF  = Color to draw text in\r
+;        ColorB  = Color to set background to\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+PS_STACK    STRUC\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DD  ?   ; Caller\r
+    PS_ColorB   DW  ?   ; Background Color\r
+    PS_ColorF   DW  ?   ; Text Color\r
+    PS_Ypos     DW  ?   ; Y Position to Print at\r
+    PS_Xpos     DW  ?   ; X position to Print at\r
+    PS_Len      DW  ?   ; Maximum Length of string to print\r
+    PS_Text     DW  ?,? ; Far Ptr to Text String\r
+PS_STACK    ENDS\r
+\r
+        PUBLIC  PRINT_STR\r
+\r
+PRINT_STR   PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+       push    di\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+@PS_Print_It:\r
+\r
+    MOV     CX, [BP].PS_Len     ; Get Remaining text Length\r
+    JCXZ    @PS_Exit            ; Exit when out of text\r
+\r
+    LES     DI, d [BP].PS_Text  ; ES:DI -> Current Char in Text\r
+    MOV     AL, ES:[DI]         ; AL = Text Character\r
+    AND     AX, 00FFh           ; Clear High Word\r
+    JZ      @PS_Exit            ; Exit if null character\r
+\r
+    DEC     [BP].PS_Len         ; Remaining Text length--\r
+    INC     [BP].PS_Text        ; Point to Next text char\r
+\r
+    ; Set up Call to GPRINTC\r
+\r
+    PUSH    AX                  ; Set Character Parameter\r
+    MOV     BX, [BP].PS_Xpos    ; Get Xpos\r
+    PUSH    BX                  ; Set Xpos Parameter\r
+    ADD     BX, 8               ; Advance 1 Char to Right\r
+    MOV     [BP].PS_Xpos, BX    ; Save for next time through\r
+\r
+    MOV     BX, [BP].PS_Ypos    ; Get Ypos\r
+    PUSH    BX                  ; Set Ypos Parameter\r
+\r
+    MOV     BX, [BP].PS_ColorF  ; Get Text Color\r
+    PUSH    BX                  ; Set ColorF Parameter\r
+\r
+    MOV     BX, [BP].PS_ColorB  ; Get Background Color\r
+    PUSH    BX                  ; Set ColorB Parameter\r
+\r
+    CALL    f GPRINTC           ; Print Character!\r
+    JMP     s @PS_Print_It      ; Process next character\r
+\r
+@PS_Exit:\r
+    ;POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    RET     14                  ; Exit and Clean up Stack\r
+\r
+PRINT_STR  ENDP\r
+\r
+\r
+;================================================================\r
+;TPRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%)\r
+;================================================================\r
+;\r
+; Routine to quickly transparently Print a null terminated ASCII\r
+; string on the active display page up to a maximum length.\r
+;\r
+; ENTRY: String  = Far Pointer to ASCII string to print\r
+;        MaxLen  = # of characters to print if no null found\r
+;        Xpos    = X position to draw Text at\r
+;        Ypos    = Y position of to draw Text at\r
+;        ColorF  = Color to draw text in\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+TPS_STACK   STRUC\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DD  ?   ; Caller\r
+    TPS_ColorF  DW  ?   ; Text Color\r
+    TPS_Ypos    DW  ?   ; Y Position to Print at\r
+    TPS_Xpos    DW  ?   ; X position to Print at\r
+    TPS_Len     DW  ?   ; Maximum Length of string to print\r
+    TPS_Text    DW  ?,? ; Far Ptr to Text String\r
+TPS_STACK   ENDS\r
+\r
+        PUBLIC  TPRINT_STR\r
+\r
+TPRINT_STR  PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+       push    di\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+@TPS_Print_It:\r
+\r
+    MOV     CX, [BP].TPS_Len    ; Get Remaining text Length\r
+    JCXZ    @TPS_Exit           ; Exit when out of text\r
+\r
+    LES     DI, d [BP].TPS_Text ; ES:DI -> Current Char in Text\r
+    MOV     AL, ES:[DI]         ; AL = Text Character\r
+    AND     AX, 00FFh           ; Clear High Word\r
+    JZ      @TPS_Exit           ; Exit if null character\r
+\r
+    DEC     [BP].TPS_Len        ; Remaining Text length--\r
+    INC     [BP].TPS_Text       ; Point to Next text char\r
+\r
+    ; Set up Call to TGPRINTC\r
+\r
+    PUSH    AX                  ; Set Character Parameter\r
+    MOV     BX, [BP].TPS_Xpos   ; Get Xpos\r
+    PUSH    BX                  ; Set Xpos Parameter\r
+    ADD     BX, 8               ; Advance 1 Char to Right\r
+    MOV     [BP].TPS_Xpos, BX   ; Save for next time through\r
+\r
+    MOV     BX, [BP].TPS_Ypos   ; Get Ypos\r
+    PUSH    BX                  ; Set Ypos Parameter\r
+\r
+    MOV     BX, [BP].TPS_ColorF ; Get Text Color\r
+    PUSH    BX                  ; Set ColorF Parameter\r
+\r
+    CALL    f TGPRINTC          ; Print Character!\r
+    JMP     s @TPS_Print_It     ; Process next character\r
+\r
+@TPS_Exit:\r
+    ;POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    RET     12                  ; Exit and Clean up Stack\r
+\r
+TPRINT_STR  ENDP\r
+\r
+\r
+;===========================================\r
+;SET_DISPLAY_FONT(SEG FontData, FontNumber%)\r
+;===========================================\r
+;\r
+; Allows the user to specify their own font data for\r
+; wither the lower or upper 128 characters.\r
+;\r
+; ENTRY: FontData   = Far Pointer to Font Bitmaps\r
+;        FontNumber = Which half of set this is\r
+;                   = 0, Lower 128 characters\r
+;                   = 1, Upper 128 characters\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+SDF_STACK   STRUC\r
+                DW  ?   ; BP\r
+                DD  ?   ; Caller\r
+    SDF_Which   DW  ?   ; Hi Table/Low Table Flag\r
+    SDF_Font    DD  ?   ; Far Ptr to Font Table\r
+SDF_STACK   ENDS\r
+\r
+    PUBLIC  SET_DISPLAY_FONT\r
+\r
+SET_DISPLAY_FONT    PROC    FAR\r
+\r
+    PUSH    BP                  ; Preserve Registers\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    LES     DI, [BP].SDF_Font   ; Get Far Ptr to Font\r
+\r
+    MOV     SI, o CHARSET_LOW   ; Assume Lower 128 chars\r
+    TEST    [BP].SDF_Which, 1   ; Font #1 selected?\r
+    JZ      @SDF_Set_Font       ; If not, skip ahead\r
+\r
+    MOV     SI, o CHARSET_HI    ; Ah, really it's 128-255\r
+\r
+@SDF_Set_Font:\r
+    MOV     [SI], DI            ; Set Font Pointer Offset\r
+    MOV     [SI+2], ES          ; Set Font Pointer Segment\r
+\r
+    POP     BP                  ; Restore Registers\r
+    RET     6                   ; We are Done.. Outa here\r
+\r
+SET_DISPLAY_FONT    ENDP\r
+\r
+\r
+    ; ===== BITMAP (SPRITE) DISPLAY ROUTINES =====\r
+\r
+;======================================================\r
+;DRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%)\r
+;======================================================\r
+;\r
+; Draws a variable sized Graphics Bitmap such as a\r
+; picture or an Icon on the current Display Page in\r
+; Mode X.  The Bitmap is stored in a linear byte array\r
+; corresponding to (0,0) (1,0), (2,0) .. (Width, Height)\r
+; This is the same linear manner as mode 13h graphics.\r
+;\r
+; ENTRY: Image  = Far Pointer to Bitmap Data\r
+;        Xpos   = X position to Place Upper Left pixel at\r
+;        Ypos   = Y position to Place Upper Left pixel at\r
+;        Width  = Width of the Bitmap in Pixels\r
+;        Height = Height of the Bitmap in Pixels\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+DB_STACK    STRUC\r
+    DB_LineO    DW  ?   ; Offset to Next Line\r
+    DB_PixCount DW  ?   ; (Minimum) # of Pixels/Line\r
+    DB_Start    DW  ?   ; Addr of Upper Left Pixel\r
+    DB_PixSkew  DW  ?   ; # of bytes to Adjust EOL\r
+    DB_SkewFlag DW  ?   ; Extra Pix on Plane Flag\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DD  ?   ; Caller\r
+    DB_Height   DW  ?   ; Height of Bitmap in Pixels\r
+    DB_Width    DW  ?   ; Width of Bitmap in Pixels\r
+    DB_Ypos     DW  ?   ; Y position to Draw Bitmap at\r
+    DB_Xpos     DW  ?   ; X position to Draw Bitmap at\r
+    DB_Image    DD  ?   ; Far Pointer to Graphics Bitmap\r
+DB_STACK    ENDS\r
+\r
+        PUBLIC    DRAW_BITMAP\r
+\r
+DRAW_BITMAP PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+       push    di\r
+    SUB     SP, 10              ; Allocate workspace\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+    CLD                         ; Direction Flag = Forward\r
+\r
+    MOV     AX, [BP].DB_Ypos    ; Get UL Corner Ypos\r
+    MUL     SCREEN_WIDTH        ; AX = Offset to Line Ypos\r
+\r
+    MOV     BX, [BP].DB_Xpos    ; Get UL Corner Xpos\r
+    MOV     CL, BL              ; Save Plane # in CL\r
+    SHR     BX, 1               ; Xpos/4 = Offset Into Line\r
+    SHR     BX, 1               ; Xpos/4 = Offset Into Line\r
+\r
+    ADD     DI, AX              ; ES:DI -> Start of Line\r
+    ADD     DI, BX              ; ES:DI -> Upper Left Pixel\r
+    MOV     [BP].DB_Start, DI   ; Save Starting Addr\r
+\r
+    ; Compute line to line offset\r
+\r
+    MOV     BX, [BP].DB_Width   ; Get Width of Image\r
+    MOV     DX, BX              ; Save Copy in DX\r
+    SHR     BX, 1               ; /4 = width in bands\r
+    SHR     BX, 1               ; /4 = width in bands\r
+    MOV     AX, SCREEN_WIDTH    ; Get Screen Width\r
+    SUB     AX, BX              ; - (Bitmap Width/4)\r
+\r
+    MOV     [BP].DB_LineO, AX       ; Save Line Width offset\r
+    MOV     [BP].DB_PixCount, BX    ; Minimum # pix to copy\r
+\r
+    AND     DX, PLANE_BITS          ; Get "partial band" size (0-3)\r
+    MOV     [BP].DB_PixSkew, DX     ; Also End of Line Skew\r
+    MOV     [BP].DB_SkewFlag, DX    ; Save as Flag/Count\r
+\r
+    AND     CX, PLANE_BITS      ; CL = Starting Plane #\r
+    MOV     AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select\r
+    SHL     AH, CL              ; Select correct Plane\r
+    OUT_16  SC_Index, AX        ; Select Plane...\r
+    MOV     BH, AH              ; BH = Saved Plane Mask\r
+    MOV     BL, 4               ; BL = Planes to Copy\r
+\r
+@DB_COPY_PLANE:\r
+\r
+    LDS     SI, [BP].DB_Image   ; DS:SI-> Source Image\r
+    MOV     DX, [BP].DB_Height  ; # of Lines to Copy\r
+    MOV     DI, [BP].DB_Start   ; ES:DI-> Dest pos\r
+\r
+@DB_COPY_LINE:\r
+    MOV     CX, [BP].DB_PixCount    ; Min # to copy\r
+\r
+    TEST    CL, 0FCh            ; 16+PixWide?\r
+    JZ      @DB_COPY_REMAINDER  ; Nope...\r
+\r
+    ; Pixel Copy loop has been unrolled to x4\r
+\r
+@DB_COPY_LOOP:\r
+    MOVSB                       ; Copy Bitmap Pixel\r
+    ADD     SI, 3               ; Skip to Next Byte in same plane\r
+    MOVSB                       ; Copy Bitmap Pixel\r
+    ADD     SI, 3               ; Skip to Next Byte in same plane\r
+    MOVSB                       ; Copy Bitmap Pixel\r
+    ADD     SI, 3               ; Skip to Next Byte in same plane\r
+    MOVSB                       ; Copy Bitmap Pixel\r
+    ADD     SI, 3               ; Skip to Next Byte in same plane\r
+\r
+    SUB     CL, 4               ; Pixels to Copy=-4\r
+    TEST    CL, 0FCh            ; 4+ Pixels Left?\r
+    JNZ     @DB_COPY_LOOP       ; if so, do another block\r
+\r
+@DB_COPY_REMAINDER:\r
+    JCXZ    @DB_NEXT_LINE       ; Any Pixels left on line\r
+\r
+@DB_COPY2:\r
+    MOVSB                       ; Copy Bitmap Pixel\r
+    ADD     SI,3                ; Skip to Next Byte in same plane\r
+    LOOPx   CX, @DB_COPY2       ; Pixels to Copy--, Loop until done\r
+\r
+@DB_NEXT_LINE:\r
+\r
+    ; any Partial Pixels? (some planes only)\r
+\r
+    OR      CX, [BP].DB_SkewFlag    ; Get Skew Count\r
+    JZ      @DB_NEXT2               ; if no partial pixels\r
+\r
+    MOVSB                       ; Copy Bitmap Pixel\r
+    DEC     DI                  ; Back up to align\r
+    DEC     SI                  ; Back up to align\r
+\r
+@DB_NEXT2:\r
+    ADD     SI, [BP].DB_PixSkew ; Adjust Skew\r
+    ADD     DI, [BP].DB_LineO   ; Set to Next Display Line\r
+    LOOPx   DX, @DB_COPY_LINE   ; Lines to Copy--, Loop if more\r
+\r
+    ; Copy Next Plane....\r
+\r
+    DEC     BL                  ; Planes to Go--\r
+    JZ      @DB_Exit            ; Hey! We are done\r
+\r
+    ROL     BH, 1               ; Next Plane in line...\r
+    OUT_8   SC_Data, BH         ; Select Plane\r
+\r
+    CMP     AL, 12h             ; Carry Set if AL=11h\r
+    ADC     [BP].DB_Start, 0    ; Screen Addr =+Carry\r
+    INC     w [BP].DB_Image     ; Start @ Next Byte\r
+\r
+    SUB     [BP].DB_SkewFlag, 1 ; Reduce Planes to Skew\r
+    ADC     [BP].DB_SkewFlag, 0 ; Back to 0 if it was -1\r
+\r
+    JMP     s @DB_COPY_PLANE    ; Go Copy the Next Plane\r
+\r
+@DB_Exit:\r
+    ADD     SP, 10              ; Deallocate workspace\r
+    ;POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    RET     12                  ; Exit and Clean up Stack\r
+\r
+DRAW_BITMAP   ENDP\r
+\r
+\r
+;=======================================================\r
+;TDRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%)\r
+;=======================================================\r
+;\r
+; Transparently Draws a variable sized Graphics Bitmap\r
+; such as a picture or an Icon on the current Display Page\r
+; in Mode X.  Pixels with a value of 0 are not drawn,\r
+; leaving the previous "background" contents intact.\r
+;\r
+; The Bitmap format is the same as for the DRAW_BITMAP function.\r
+;\r
+; ENTRY: Image  = Far Pointer to Bitmap Data\r
+;        Xpos   = X position to Place Upper Left pixel at\r
+;        Ypos   = Y position to Place Upper Left pixel at\r
+;        Width  = Width of the Bitmap in Pixels\r
+;        Height = Height of the Bitmap in Pixels\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+TB_STACK    STRUC\r
+    TB_LineO    DW  ?   ; Offset to Next Line\r
+    TB_PixCount DW  ?   ; (Minimum) # of Pixels/Line\r
+    TB_Start    DW  ?   ; Addr of Upper Left Pixel\r
+    TB_PixSkew  DW  ?   ; # of bytes to Adjust EOL\r
+    TB_SkewFlag DW  ?   ; Extra Pix on Plane Flag\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DD  ?   ; Caller\r
+    TB_Height   DW  ?   ; Height of Bitmap in Pixels\r
+    TB_Width    DW  ?   ; Width of Bitmap in Pixels\r
+    TB_Ypos     DW  ?   ; Y position to Draw Bitmap at\r
+    TB_Xpos     DW  ?   ; X position to Draw Bitmap at\r
+    TB_Image    DD  ?   ; Far Pointer to Graphics Bitmap\r
+TB_STACK    ENDS\r
+\r
+        PUBLIC    TDRAW_BITMAP\r
+\r
+TDRAW_BITMAP    PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+       push    di\r
+    SUB     SP, 10              ; Allocate workspace\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+    CLD                         ; Direction Flag = Forward\r
+\r
+    MOV     AX, [BP].TB_Ypos    ; Get UL Corner Ypos\r
+    MUL     SCREEN_WIDTH        ; AX = Offset to Line Ypos\r
+\r
+    MOV     BX, [BP].TB_Xpos    ; Get UL Corner Xpos\r
+    MOV     CL, BL              ; Save Plane # in CL\r
+    SHR     BX, 1               ; Xpos/4 = Offset Into Line\r
+    SHR     BX, 1               ; Xpos/4 = Offset Into Line\r
+\r
+    ADD     DI, AX              ; ES:DI -> Start of Line\r
+    ADD     DI, BX              ; ES:DI -> Upper Left Pixel\r
+    MOV     [BP].TB_Start, DI   ; Save Starting Addr\r
+\r
+    ; Compute line to line offset\r
+\r
+    MOV     BX, [BP].TB_Width   ; Get Width of Image\r
+    MOV     DX, BX              ; Save Copy in DX\r
+    SHR     BX, 1               ; /4 = width in bands\r
+    SHR     BX, 1               ; /4 = width in bands\r
+    MOV     AX, SCREEN_WIDTH    ; Get Screen Width\r
+    SUB     AX, BX              ; - (Bitmap Width/4)\r
+\r
+    MOV     [BP].TB_LineO, AX       ; Save Line Width offset\r
+    MOV     [BP].TB_PixCount, BX    ; Minimum # pix to copy\r
+\r
+    AND     DX, PLANE_BITS          ; Get "partial band" size (0-3)\r
+    MOV     [BP].TB_PixSkew, DX     ; Also End of Line Skew\r
+    MOV     [BP].TB_SkewFlag, DX    ; Save as Flag/Count\r
+\r
+    AND     CX, PLANE_BITS      ; CL = Starting Plane #\r
+    MOV     AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select\r
+    SHL     AH, CL              ; Select correct Plane\r
+    OUT_16  SC_Index, AX        ; Select Plane...\r
+    MOV     BH, AH              ; BH = Saved Plane Mask\r
+    MOV     BL, 4               ; BL = Planes to Copy\r
+\r
+@TB_COPY_PLANE:\r
+\r
+    LDS     SI, [BP].TB_Image   ; DS:SI-> Source Image\r
+    MOV     DX, [BP].TB_Height  ; # of Lines to Copy\r
+    MOV     DI, [BP].TB_Start   ; ES:DI-> Dest pos\r
+\r
+    ; Here AH is set with the value to be considered\r
+    ; "Transparent".  It can be changed!\r
+\r
+    MOV     AH, 0               ; Value to Detect 0\r
+\r
+@TB_COPY_LINE:\r
+    MOV     CX, [BP].TB_PixCount    ; Min # to copy\r
+\r
+    TEST    CL, 0FCh            ; 16+PixWide?\r
+    JZ      @TB_COPY_REMAINDER  ; Nope...\r
+\r
+    ; Pixel Copy loop has been unrolled to x4\r
+\r
+@TB_COPY_LOOP:\r
+    LODSB                       ; Get Pixel Value in AL\r
+    ADD     SI, 3               ; Skip to Next Byte in same plane\r
+    CMP     AL, AH              ; It is "Transparent"?\r
+    JE      @TB_SKIP_01         ; Skip ahead if so\r
+    MOV     ES:[DI], AL         ; Copy Pixel to VGA screen\r
+\r
+@TB_SKIP_01:\r
+    LODSB                       ; Get Pixel Value in AL\r
+    ADD     SI, 3               ; Skip to Next Byte in same plane\r
+    CMP     AL, AH              ; It is "Transparent"?\r
+    JE      @TB_SKIP_02         ; Skip ahead if so\r
+    MOV     ES:[DI+1], AL       ; Copy Pixel to VGA screen\r
+\r
+@TB_SKIP_02:\r
+    LODSB                       ; Get Pixel Value in AL\r
+    ADD     SI, 3               ; Skip to Next Byte in same plane\r
+    CMP     AL, AH              ; It is "Transparent"?\r
+    JE      @TB_SKIP_03         ; Skip ahead if so\r
+    MOV     ES:[DI+2], AL       ; Copy Pixel to VGA screen\r
+\r
+@TB_SKIP_03:\r
+    LODSB                       ; Get Pixel Value in AL\r
+    ADD     SI, 3               ; Skip to Next Byte in same plane\r
+    CMP     AL, AH              ; It is "Transparent"?\r
+    JE      @TB_SKIP_04         ; Skip ahead if so\r
+    MOV     ES:[DI+3], AL       ; Copy Pixel to VGA screen\r
+\r
+@TB_SKIP_04:\r
+    ADD     DI, 4               ; Adjust Pixel Write Location\r
+    SUB     CL, 4               ; Pixels to Copy=-4\r
+    TEST    CL, 0FCh            ; 4+ Pixels Left?\r
+    JNZ     @TB_COPY_LOOP       ; if so, do another block\r
+\r
+@TB_COPY_REMAINDER:\r
+    JCXZ    @TB_NEXT_LINE       ; Any Pixels left on line\r
+\r
+@TB_COPY2:\r
+    LODSB                       ; Get Pixel Value in AL\r
+    ADD     SI, 3               ; Skip to Next Byte in same plane\r
+    CMP     AL, AH              ; It is "Transparent"?\r
+    JE      @TB_SKIP_05         ; Skip ahead if so\r
+    MOV     ES:[DI], AL         ; Copy Pixel to VGA screen\r
+\r
+@TB_SKIP_05:\r
+    INC     DI                  ; Advance Dest Addr\r
+    LOOPx   CX, @TB_COPY2       ; Pixels to Copy--, Loop until done\r
+\r
+@TB_NEXT_LINE:\r
+\r
+    ; any Partial Pixels? (some planes only)\r
+\r
+    OR      CX, [BP].TB_SkewFlag    ; Get Skew Count\r
+    JZ      @TB_NEXT2               ; if no partial pixels\r
+\r
+    LODSB                       ; Get Pixel Value in AL\r
+    DEC     SI                  ; Backup to Align\r
+    CMP     AL, AH              ; It is "Transparent"?\r
+    JE      @TB_NEXT2           ; Skip ahead if so\r
+    MOV     ES:[DI], AL         ; Copy Pixel to VGA screen\r
+\r
+@TB_NEXT2:\r
+    ADD     SI, [BP].TB_PixSkew ; Adjust Skew\r
+    ADD     DI, [BP].TB_LineO   ; Set to Next Display Line\r
+    LOOPx   DX, @TB_COPY_LINE   ; Lines to Copy--, Loop if More\r
+\r
+    ;Copy Next Plane....\r
+\r
+    DEC     BL                  ; Planes to Go--\r
+    JZ      @TB_Exit            ; Hey! We are done\r
+\r
+    ROL     BH, 1               ; Next Plane in line...\r
+    OUT_8   SC_Data, BH         ; Select Plane\r
+\r
+    CMP     AL, 12h             ; Carry Set if AL=11h\r
+    ADC     [BP].TB_Start, 0    ; Screen Addr =+Carry\r
+    INC     w [BP].TB_Image     ; Start @ Next Byte\r
+\r
+    SUB     [BP].TB_SkewFlag, 1 ; Reduce Planes to Skew\r
+    ADC     [BP].TB_SkewFlag, 0 ; Back to 0 if it was -1\r
+\r
+    JMP     @TB_COPY_PLANE      ; Go Copy the next Plane\r
+\r
+@TB_Exit:\r
+    ADD     SP, 10              ; Deallocate workspace\r
+    ;POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    RET     12                  ; Exit and Clean up Stack\r
+\r
+TDRAW_BITMAP    ENDP\r
+\r
+\r
+    ; ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====\r
+\r
+;==================================\r
+;COPY_PAGE (SourcePage%, DestPage%)\r
+;==================================\r
+;\r
+; Duplicate on display page onto another\r
+;\r
+; ENTRY: SourcePage = Display Page # to Duplicate\r
+;        DestPage   = Display Page # to hold copy\r
+;\r
+; EXIT:  No meaningful values returned\r
+;\r
+\r
+CP_STACK    STRUC\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DD  ?   ; Caller\r
+    CP_DestP    DW  ?   ; Page to hold copied image\r
+    CP_SourceP  DW  ?   ; Page to Make copy from\r
+CP_STACK    ENDS\r
+\r
+        PUBLIC    COPY_PAGE\r
+\r
+COPY_PAGE   PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+       push    di\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+    CLD                         ; Block Xfer Forwards\r
+\r
+    ; Make sure Page #'s are valid\r
+\r
+    MOV     AX, [BP].CP_SourceP ; Get Source Page #\r
+    CMP     AX, LAST_PAGE       ; is it > Max Page #?\r
+    JAE     @CP_Exit            ; if so, abort\r
+\r
+    MOV     BX, [BP].CP_DestP   ; Get Destination Page #\r
+    CMP     BX, LAST_PAGE       ; is it > Max Page #?\r
+    JAE     @CP_Exit            ; if so, abort\r
+\r
+    CMP     AX, BX              ; Pages #'s the same?\r
+    JE      @CP_Exit            ; if so, abort\r
+\r
+    ; Setup DS:SI and ES:DI to Video Pages\r
+\r
+    SHL     BX, 1               ; Scale index to Word\r
+    MOV     DI, PAGE_ADDR[BX]   ; Offset to Dest Page\r
+\r
+    MOV     BX, AX              ; Index to Source page\r
+    SHL     BX, 1               ; Scale index to Word\r
+    MOV     SI, PAGE_ADDR[BX]   ; Offset to Source Page\r
+\r
+    MOV     CX, PAGE_SIZE       ; Get size of Page\r
+    MOV     AX, CURRENT_SEGMENT ; Get Video Mem Segment\r
+    MOV     ES, AX              ; ES:DI -> Dest Page\r
+    MOV     DS, AX              ; DS:SI -> Source Page\r
+\r
+    ; Setup VGA registers for Mem to Mem copy\r
+\r
+    OUT_16  GC_Index, LATCHES_ON    ; Data from Latches = on\r
+    OUT_16  SC_Index, ALL_PLANES_ON ; Copy all Planes\r
+\r
+    ; Note.. Do *NOT* use MOVSW or MOVSD - they will\r
+    ; Screw with the latches which are 8 bits x 4\r
+\r
+    REP     MOVSB               ; Copy entire Page!\r
+\r
+    ; Reset VGA for normal memory access\r
+\r
+    OUT_16  GC_Index, LATCHES_OFF   ; Data from Latches = off\r
+\r
+@CP_Exit:\r
+    ;POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    RET     4                   ; Exit and Clean up Stack\r
+\r
+COPY_PAGE   ENDP\r
+\r
+\r
+;==========================================================================\r
+;COPY_BITMAP (SourcePage%, X1%, Y1%, X2%, Y2%, DestPage%, DestX1%, DestY1%)\r
+;==========================================================================\r
+;\r
+; Copies a Bitmap Image from one Display Page to Another\r
+; This Routine is Limited to copying Images with the same\r
+; Plane Alignment.  To Work: (X1 MOD 4) must = (DestX1 MOD 4)\r
+; Copying an Image to the Same Page is supported, but results\r
+; may be defined when the when the rectangular areas\r
+; (X1, Y1) - (X2, Y2) and (DestX1, DestY1) -\r
+; (DestX1+(X2-X1), DestY1+(Y2-Y1)) overlap...\r
+; No Paramter checking to done to insure that\r
+; X2 >= X1 and Y2 >= Y1.  Be Careful...\r
+;\r
+; ENTRY: SourcePage = Display Page # with Source Image\r
+;        X1         = Upper Left Xpos of Source Image\r
+;        Y1         = Upper Left Ypos of Source Image\r
+;        X2         = Lower Right Xpos of Source Image\r
+;        Y2         = Lower Right Ypos of Source Image\r
+;        DestPage   = Display Page # to copy Image to\r
+;        DestX1     = Xpos to Copy UL Corner of Image to\r
+;        DestY1     = Ypos to Copy UL Corner of Image to\r
+;\r
+; EXIT:  AX = Success Flag:   0 = Failure / -1= Success\r
+;\r
+\r
+CB_STACK    STRUC\r
+    CB_Height   DW  ?   ; Height of Image in Lines\r
+    CB_Width    DW  ?   ; Width of Image in "bands"\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DI, SI, DS, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DW  ?x1 ; DS, DI, SI, BP\r
+                DD  ?   ; Caller\r
+    CB_DestY1   DW  ?   ; Destination Ypos\r
+    CB_DestX1   DW  ?   ; Destination Xpos\r
+    CB_DestP    DW  ?   ; Page to Copy Bitmap To\r
+    CB_Y2       DW  ?   ; LR Ypos of Image\r
+    CB_X2       DW  ?   ; LR Xpos of Image\r
+    CB_Y1       DW  ?   ; UL Ypos of Image\r
+    CB_X1       DW  ?   ; UL Xpos of Image\r
+    CB_SourceP  DW  ?   ; Page containing Source Bitmap\r
+CB_STACK    ENDS\r
+\r
+        PUBLIC    COPY_BITMAP\r
+\r
+COPY_BITMAP PROC    FAR\r
+\r
+    ;PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+    push       bp\r
+       push    ds\r
+       push    si\r
+       push    di\r
+    SUB     SP, 4               ; Allocate WorkSpace on Stack\r
+    MOV     BP, SP              ; Set up Stack Frame\r
+\r
+    ; Prep Registers (and keep jumps short!)\r
+\r
+    MOV     ES, CURRENT_SEGMENT ; ES -> VGA Ram\r
+    CLD                         ; Block Xfer Forwards\r
+\r
+    ; Make sure Parameters are valid\r
+\r
+    MOV     BX, [BP].CB_SourceP ; Get Source Page #\r
+    CMP     BX, LAST_PAGE       ; is it > Max Page #?\r
+    JAE     @CB_Abort           ; if so, abort\r
+\r
+    MOV     CX, [BP].CB_DestP   ; Get Destination Page #\r
+    CMP     CX, LAST_PAGE       ; is it > Max Page #?\r
+    JAE     @CB_Abort           ; if so, abort\r
+\r
+    MOV     AX, [BP].CB_X1      ; Get Source X1\r
+    XOR     AX, [BP].CB_DestX1  ; Compare Bits 0-1\r
+    AND     AX, PLANE_BITS      ; Check Plane Bits\r
+    JNZ     @CB_Abort           ; They should cancel out\r
+\r
+    ; Setup for Copy processing\r
+\r
+    OUT_8   SC_INDEX, MAP_MASK      ; Set up for Plane Select\r
+    OUT_16  GC_Index, LATCHES_ON    ; Data from Latches = on\r
+\r
+    ; Compute Info About Images, Setup ES:SI & ES:DI\r
+\r
+    MOV     AX, [BP].CB_Y2      ; Height of Bitmap in lines\r
+    SUB     AX, [BP].CB_Y1      ; is Y2 - Y1 + 1\r
+    INC     AX                  ; (add 1 since were not 0 based)\r
+    MOV     [BP].CB_Height, AX  ; Save on Stack for later use\r
+\r
+    MOV     AX, [BP].CB_X2      ; Get # of "Bands" of 4 Pixels\r
+    MOV     DX, [BP].CB_X1      ; the Bitmap Occupies as X2-X1\r
+    SHR     AX, 1               ; Get X2 Band (X2 / 4)\r
+    SHR     DX, 1               ; Get X1 Band (X1 / 4)\r
+    SHR     AX, 1               ; Get X2 Band (X2 / 4)\r
+    SHR     DX, 1               ; Get X1 Band (X1 / 4)\r
+    SUB     AX, DX              ; AX = # of Bands - 1\r
+    INC     AX                  ; AX = # of Bands\r
+    MOV     [BP].CB_Width, AX   ; Save on Stack for later use\r
+\r
+    SHL     BX, 1               ; Scale Source Page to Word\r
+    MOV     SI, PAGE_ADDR[BX]   ; SI = Offset of Source Page\r
+    MOV     AX, [BP].CB_Y1      ; Get Source Y1 Line\r
+    MUL     SCREEN_WIDTH        ; AX = Offset to Line Y1\r
+    ADD     SI, AX              ; SI = Offset to Line Y1\r
+    MOV     AX, [BP].CB_X1      ; Get Source X1\r
+    SHR     AX, 1               ; X1 / 4 = Byte offset\r
+    SHR     AX, 1               ; X1 / 4 = Byte offset\r
+    ADD     SI, AX              ; SI = Byte Offset to (X1,Y1)\r
+\r
+    MOV     BX, CX              ; Dest Page Index to BX\r
+    SHL     BX, 1               ; Scale Source Page to Word\r
+    MOV     DI, PAGE_ADDR[BX]   ; DI = Offset of Dest Page\r
+    MOV     AX, [BP].CB_DestY1  ; Get Dest Y1 Line\r
+    MUL     SCREEN_WIDTH        ; AX = Offset to Line Y1\r
+    ADD     DI, AX              ; DI = Offset to Line Y1\r
+    MOV     AX, [BP].CB_DestX1  ; Get Dest X1\r
+    SHR     AX, 1              ; X1 / 4 = Byte offset\r
+    SHR     AX, 1               ; X1 / 4 = Byte offset\r
+    ADD     DI, AX              ; DI = Byte Offset to (D-X1,D-Y1)\r
+\r
+    MOV     CX, [BP].CB_Width   ; CX = Width of Image (Bands)\r
+    DEC     CX                  ; CX = 1?\r
+    JE      @CB_Only_One_Band   ; 0 Means Image Width of 1 Band\r
+\r
+    MOV     BX, [BP].CB_X1      ; Get Source X1\r
+    AND     BX, PLANE_BITS      ; Aligned? (bits 0-1 = 00?)\r
+    JZ      @CB_Check_Right     ; if so, check right alignment\r
+    JNZ     @CB_Left_Band       ; not aligned? well..\r
+\r
+@CB_Abort:\r
+    mov ax,0                  ; Return False (Failure)\r
+    JMP     @CB_Exit            ; and Finish Up\r
+\r
+    ; Copy when Left & Right Clip Masks overlap...\r
+\r
+@CB_Only_One_Band:\r
+    MOV     BX, [BP].CB_X1          ; Get Left Clip Mask\r
+    AND     BX, PLANE_BITS          ; Mask out Row #\r
+    MOV     AL, Left_Clip_Mask[BX]  ; Get Left Edge Mask\r
+    MOV     BX, [BP].CB_X2          ; Get Right Clip Mask\r
+    AND     BX, PLANE_BITS          ; Mask out Row #\r
+    AND     AL, Right_Clip_Mask[BX] ; Get Right Edge Mask byte\r
+\r
+    OUT_8   SC_Data, AL         ; Clip For Left & Right Masks\r
+\r
+    MOV     CX, [BP].CB_Height  ; CX = # of Lines to Copy\r
+    MOV     DX, SCREEN_WIDTH    ; DX = Width of Screen\r
+    mov bx,0                  ; BX = Offset into Image\r
+\r
+@CB_One_Loop:\r
+    MOV     AL, ES:[SI+BX]      ; Load Latches\r
+    MOV     ES:[DI+BX], AL      ; Unload Latches\r
+    ADD     BX, DX              ; Advance Offset to Next Line\r
+    LOOPjz  CX, @CB_One_Done    ; Exit Loop if Finished\r
+\r
+    MOV     AL, ES:[SI+BX]      ; Load Latches\r
+    MOV     ES:[DI+BX], AL      ; Unload Latches\r
+    ADD     BX, DX              ; Advance Offset to Next Line\r
+    LOOPx   CX, @CB_One_Loop    ; Loop until Finished\r
+\r
+@CB_One_Done:\r
+    JMP     @CB_Finish          ; Outa Here!\r
+\r
+    ; Copy Left Edge of Bitmap\r
+\r
+@CB_Left_Band:\r
+\r
+    OUT_8   SC_Data, Left_Clip_Mask[BX] ; Set Left Edge Plane Mask\r
+\r
+    MOV     CX, [BP].CB_Height  ; CX = # of Lines to Copy\r
+    MOV     DX, SCREEN_WIDTH    ; DX = Width of Screen\r
+    mov bx,0                  ; BX = Offset into Image\r
+\r
+@CB_Left_Loop:\r
+    MOV     AL, ES:[SI+BX]      ; Load Latches\r
+    MOV     ES:[DI+BX], AL      ; Unload Latches\r
+    ADD     BX, DX              ; Advance Offset to Next Line\r
+    LOOPjz  CX, @CB_Left_Done   ; Exit Loop if Finished\r
+\r
+    MOV     AL, ES:[SI+BX]      ; Load Latches\r
+    MOV     ES:[DI+BX], AL      ; Unload Latches\r
+    ADD     BX, DX              ; Advance Offset to Next Line\r
+    LOOPx   CX, @CB_Left_Loop   ; Loop until Finished\r
+\r
+@CB_Left_Done:\r
+    INC     DI                  ; Move Dest Over 1 band\r
+    INC     SI                  ; Move Source Over 1 band\r
+    DEC     [BP].CB_Width       ; Band Width--\r
+\r
+    ; Determine if Right Edge of Bitmap needs special copy\r
+\r
+@CB_Check_Right:\r
+    MOV     BX, [BP].CB_X2      ; Get Source X2\r
+    AND     BX, PLANE_BITS      ; Aligned? (bits 0-1 = 11?)\r
+    CMP     BL, 03h             ; Plane = 3?\r
+    JE      @CB_Copy_Middle     ; Copy the Middle then!\r
+\r
+    ; Copy Right Edge of Bitmap\r
+\r
+@CB_Right_Band:\r
+\r
+    OUT_8   SC_Data, Right_Clip_Mask[BX]    ; Set Right Edge Plane Mask\r
+\r
+    DEC     [BP].CB_Width       ; Band Width--\r
+    MOV     CX, [BP].CB_Height  ; CX = # of Lines to Copy\r
+    MOV     DX, SCREEN_WIDTH    ; DX = Width of Screen\r
+    MOV     BX, [BP].CB_Width   ; BX = Offset to Right Edge\r
+\r
+@CB_Right_Loop:\r
+    MOV     AL, ES:[SI+BX]      ; Load Latches\r
+    MOV     ES:[DI+BX], AL      ; Unload Latches\r
+    ADD     BX, DX              ; Advance Offset to Next Line\r
+    LOOPjz  CX, @CB_Right_Done  ; Exit Loop if Finished\r
+\r
+    MOV     AL, ES:[SI+BX]      ; Load Latches\r
+    MOV     ES:[DI+BX], AL      ; Unload Latches\r
+    ADD     BX, DX              ; Advance Offset to Next Line\r
+    LOOPx   CX, @CB_Right_Loop  ; Loop until Finished\r
+\r
+@CB_Right_Done:\r
+\r
+    ; Copy the Main Block of the Bitmap\r
+\r
+@CB_Copy_Middle:\r
+\r
+    MOV     CX, [BP].CB_Width   ; Get Width Remaining\r
+    JCXZ    @CB_Finish          ; Exit if Done\r
+\r
+    OUT_8   SC_Data, ALL_PLANES ; Copy all Planes\r
+\r
+    MOV     DX, SCREEN_WIDTH    ; Get Width of Screen minus\r
+    SUB     DX, CX              ; Image width (for Adjustment)\r
+    MOV     AX, [BP].CB_Height  ; AX = # of Lines to Copy\r
+    MOV     BX, CX              ; BX = Quick REP reload count\r
+    MOV     CX, ES              ; Move VGA Segment\r
+    MOV     DS, CX              ; Into DS\r
+\r
+    ; Actual Copy Loop.  REP MOVSB does the work\r
+\r
+@CB_Middle_Copy:\r
+    MOV     CX, BX              ; Recharge Rep Count\r
+    REP     MOVSB               ; Move Bands\r
+    LOOPjz  AX, @CB_Finish      ; Exit Loop if Finished\r
+\r
+    ADD     SI, DX              ; Adjust DS:SI to Next Line\r
+    ADD     DI, DX              ; Adjust ES:DI to Next Line\r
+\r
+    MOV     CX, BX              ; Recharge Rep Count\r
+    REP     MOVSB               ; Move Bands\r
+\r
+    ADD     SI, DX              ; Adjust DS:SI to Next Line\r
+    ADD     DI, DX              ; Adjust ES:DI to Next Line\r
+    LOOPx   AX, @CB_Middle_Copy ; Copy Lines until Done\r
+\r
+@CB_Finish:\r
+    OUT_16  GC_Index, LATCHES_OFF   ; Data from Latches = on\r
+\r
+@CB_Exit:\r
+    ADD     SP, 04              ; Deallocate stack workspace\r
+    ;POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+    pop        di\r
+       pop     si\r
+       pop     ds\r
+       pop     bp\r
+    RET     16                  ; Exit and Clean up Stack\r
+\r
+COPY_BITMAP ENDP\r
+\r
+    END                         ; End of Code Segment\r
diff --git a/src/lib/modex/modex.bi b/src/lib/modex/modex.bi
new file mode 100755 (executable)
index 0000000..6b1d7af
--- /dev/null
@@ -0,0 +1,63 @@
\r
+    ' ===== SCREEN RESOLUTIONS =====\r
\r
+CONST Mode320x200 = 0, Mode320x400 = 1\r
+CONST Mode360x200 = 2, Mode360x400 = 3\r
+CONST Mode320x240 = 4, Mode320x480 = 5\r
+CONST Mode360x240 = 6, Mode360x480 = 7\r
\r
+    ' ===== MODE X SETUP ROUTINES =====\r
\r
+DECLARE FUNCTION SET.VGA.MODEX% ALIAS "SET_VGA_MODEX" (BYVAL ModeType%, BYVAL MaxXpos%, BYVAL MaxYpos%, BYVAL Pages%)\r
+DECLARE FUNCTION SET.MODEX% ALIAS "SET_MODEX" (BYVAL Mode%)\r
\r
+    ' ===== BASIC GRAPHICS PRIMITIVES =====\r
\r
+DECLARE SUB CLEAR.VGA.SCREEN ALIAS "CLEAR_VGA_SCREEN" (BYVAL ColorNum%)\r
+DECLARE SUB SET.POINT ALIAS "SET_POINT" (BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorNum%)\r
+DECLARE FUNCTION READ.POINT% ALIAS "READ_POINT" (BYVAL Xpos%, BYVAL Ypos%)\r
+DECLARE SUB FILL.BLOCK ALIAS "FILL_BLOCK" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
+DECLARE SUB DRAW.LINE ALIAS "DRAW_LINE" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
\r
+    ' ===== DAC COLOR REGISTER ROUTINES =====\r
\r
+DECLARE SUB SET.DAC.REGISTER ALIAS "SET_DAC_REGISTER" (BYVAL RegNo%, BYVAL Red%, BYVAL Green%, BYVAL Blue%)\r
+DECLARE SUB GET.DAC.REGISTER ALIAS "GET_DAC_REGISTER" (BYVAL RegNo%, Red%, Green%, Blue%)\r
+DECLARE SUB LOAD.DAC.REGISTERS ALIAS "LOAD_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%, BYVAL VSync%)\r
+DECLARE SUB READ.DAC.REGISTERS ALIAS "READ_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%)\r
\r
\r
+    ' ===== PAGE FLIPPING AND SCROLLING ROUTINES =====\r
\r
+DECLARE SUB SET.ACTIVE.PAGE ALIAS "SET_ACTIVE_PAGE" (BYVAL PageNo%)\r
+DECLARE FUNCTION GET.ACTIVE.PAGE% ALIAS "GET_ACTIVE_PAGE"\r
+DECLARE SUB SET.DISPLAY.PAGE ALIAS "SET_DISPLAY_PAGE" (BYVAL PageNo%)\r
+DECLARE FUNCTION GET.DISPLAY.PAGE% ALIAS "GET_DISPLAY_PAGE"\r
+DECLARE SUB SET.WINDOW ALIAS "SET_WINDOW" (BYVAL DisplayPage%, BYVAL XOffset%, BYVAL YOffset%)\r
+DECLARE FUNCTION GET.X.OFFSET% ALIAS "GET_X_OFFSET" ()\r
+DECLARE FUNCTION GET.Y.OFFSET% ALIAS "GET_Y_OFFSET" ()\r
+DECLARE SUB SYNC.DISPLAY ALIAS "SYNC_DISPLAY"\r
\r
+    ' ===== TEXT DISPLAY ROUTINES =====\r
\r
+DECLARE SUB GPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
+DECLARE SUB TGPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
+DECLARE SUB PRINT.STR ALIAS "PRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
+DECLARE SUB TPRINT.STR ALIAS "TPRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
+DECLARE SUB SET.DISPLAY.FONT ALIAS "SET_DISPLAY_FONT" (SEG FontData AS ANY, BYVAL FontNumber%)\r
\r
+    ' ===== BITMAP (SPRITE) DISPLAY ROUTINES =====\r
\r
+DECLARE SUB DRAW.BITMAP ALIAS "DRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
+DECLARE SUB TDRAW.BITMAP ALIAS "TDRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
\r
+    ' ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====\r
\r
+DECLARE SUB COPY.PAGE ALIAS "COPY_PAGE" (BYVAL SourcePage%, BYVAL DestPage%)\r
+DECLARE SUB COPY.BITMAP ALIAS "COPY_BITMAP" (BYVAL SourcePage%, BYVAL X1%, BYVAL Y1%, BYVAL X2%, BYVAL Y2%, BYVAL DestPage%, BYVAL DestX1%, BYVAL DestY1%)\r
\r
\r
\r
\r
\r
\r
diff --git a/src/lib/modex/modex.h b/src/lib/modex/modex.h
new file mode 100755 (executable)
index 0000000..1381abb
--- /dev/null
@@ -0,0 +1,76 @@
+\r
+#ifndef __MODEX_H\r
+#define __MODEX_H\r
+\r
+    /* ===== SCREEN RESOLUTIONS ===== */\r
+\r
+#define Mode_320x200  0\r
+#define Mode_320x400  1\r
+#define Mode_360x200  2\r
+#define Mode_360x400  3\r
+#define Mode_320x240  4\r
+#define Mode_320x480  5\r
+#define Mode_360x240  6\r
+#define Mode_360x480  7\r
+\r
+    /* ===== MODE X SETUP ROUTINES ===== */\r
+\r
+int far pascal set_vga_modex (int Mode, int MaxXpos, int MaxYpos, int Pages);\r
+int far pascal set_modex (int Mode);\r
+\r
+    /* ===== BASIC GRAPHICS PRIMITIVES ===== */\r
+\r
+void far pascal clear_vga_screen (int Color);\r
+void far pascal set_point (int Xpos, int Ypos, int Color);\r
+int  far pascal read_point (int Xpos, int Ypos);\r
+void far pascal fill_block (int Xpos1, int Ypos1, int Xpos2, int Ypos2,\r
+                            int Color);\r
+void far pascal draw_line (int Xpos1, int Ypos1, int Xpos2, int Ypos2,\r
+                           int Color);\r
+\r
+    /* ===== DAC COLOR REGISTER ROUTINES ===== */\r
+\r
+void far pascal set_dac_register (int RegNo, int Red, int Green, int Blue);\r
+void far pascal get_dac_register (int RegNo, int* Red, int* Green, int* Blue);\r
+void far pascal load_dac_registers (char far *PalData, int StartReg,\r
+                                    int EndReg, int VSync);\r
+void far pascal readd_dac_registers (char far *PalData, int StartReg,\r
+                                    int EndReg);\r
+\r
+    /* ===== PAGE FLIPPING AND SCROLLING ROUTINES ===== */\r
+\r
+void far pascal set_active_page (int PageNo);\r
+int  far pascal get_active_page (void);\r
+void far pascal set_display_page (int PageNo);\r
+int  far pascal get_display_page (void);\r
+void far pascal set_window (int DisplayPage, int XOffset, int YOffset);\r
+int  far pascal get_x_offset (void);\r
+int  far pascal get_y_offset (void);\r
+void far pascal sync_display (void);\r
+\r
+    /* ===== TEXT DISPLAY ROUTINES ===== */\r
+\r
+void far pascal gprintc (int CharNum, int Xpos, int Ypos, int ColorF,\r
+                         int ColorB);\r
+void far pascal tgprintc (int CharNum, int Xpos, int Ypos, int ColorF);\r
+void far pascal print_str (char far *Text, int MaxLen, int Xpos, int Ypos,\r
+                           int ColorF, int ColorB);\r
+void far pascal tprint_str (char far *Text, int MaxLen, int Xpos, int Ypos,\r
+                            int ColorF);\r
+void far pascal set_display_font (char far *FontData, int FontNumber);\r
+\r
+    /* ===== BITMAP (SPRITE) DISPLAY ROUTINES ===== */\r
+\r
+void far pascal draw_bitmap (char far *Image, int Xpos, int Ypos,\r
+                             int Width, int Height);\r
+void far pascal tdraw_bitmap (char far *Image, int Xpos, int Ypos,\r
+                              int Width, int Height);\r
+\r
+    /* ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES ===== */\r
+\r
+void far pascal copy_page (int SourcePage, int DestPage);\r
+void far pascal copy_bitmap (int SourcePage, int X1, int Y1, int X2, int Y2,\r
+                             int DestPage, int DestX1, int DestY1);\r
+\r
+\r
+#endif\r
diff --git a/src/lib/modex/modex.lst b/src/lib/modex/modex.lst
new file mode 100755 (executable)
index 0000000..ce6d955
--- /dev/null
@@ -0,0 +1,4122 @@
+Microsoft (R) Macro Assembler Version 6.11                 07/02/14 15:18:33\r
+modex.asm                                                   Page 1 - 1\r
+\r
+\r
+                               ;========================================================\r
+                               ; MODEX.ASM - A Complete Mode X Library\r
+                               ;\r
+                               ; Version 1.04 Release, 3 May 1993, By Matt Pritchard\r
+                               ; With considerable input from Michael Abrash\r
+                               ;\r
+                               ; The following information is donated to the public domain in\r
+                               ; the hopes that save other programmers much frustration.\r
+                               ;\r
+                               ; If you do use this code in a product, it would be nice if\r
+                               ; you include a line like "Mode X routines by Matt Pritchard"\r
+                               ; in the credits.\r
+                               ;\r
+                               ; =========================================================\r
+                               ;\r
+                               ; All of this code is designed to be assembled with MASM 5.10a\r
+                               ; but TASM 3.0 could be used as well.\r
+                               ;\r
+                               ; The routines contained are designed for use in a MEDIUM model\r
+                               ; program.  All Routines are FAR, and is assumed that a DGROUP\r
+                               ; data segment exists and that DS will point to it on entry.\r
+                               ;\r
+                               ; For all routines, the AX, BX, CX, DX, ES and FLAGS registers\r
+                               ; will not be preserved, while the DS, BP, SI and DI registers\r
+                               ; will be preserved.\r
+                               ;\r
+                               ; Unless specifically noted, All Parameters are assumed to be\r
+                               ; "PASSED BY VALUE".  That is, the actual value is placed on\r
+                               ; the stack.  When a reference is passed it is assumed to be\r
+                               ; a near pointer to a variable in the DGROUP segment.\r
+                               ;\r
+                               ; Routines that return a single 16-Bit integer value will\r
+                               ; return that value in the AX register.\r
+                               ;\r
+                               ; This code will *NOT* run on an 8086/8088 because 80286+\r
+                               ; specific instructions are used.   If you have an 8088/86\r
+                               ; and VGA, you can buy an 80386-40 motherboard for about\r
+                               ; $160 and move into the 90's.\r
+                               ;\r
+                               ; This code is reasonably optimized: Most drawing loops have\r
+                               ; been unrolled once and memory references are minimized by\r
+                               ; keeping stuff in registers when possible.\r
+                               ;\r
+                               ; Error Trapping varies by Routine.  No Clipping is performed\r
+                               ; so the caller should verify that all coordinates are valid.\r
+                               ;\r
+                               ; Several Macros are used to simplify common 2 or 3 instruction\r
+                               ; sequences.  Several Single letter Text Constants also\r
+                               ; simplify common assembler expressions like "WORD PTR".\r
+                               ;\r
+                               ; ------------------ Mode X Variations ------------------\r
+                               ;\r
+                               ;  Mode #  Screen Size    Max Pages   Aspect Ratio (X:Y)\r
+                               ;\r
+                               ;    0      320 x 200      4 Pages         1.2:1\r
+                               ;    1      320 x 400      2 Pages         2.4:1\r
+                               ;    2      360 x 200      3 Pages        1.35:1\r
+                               ;    3      360 x 400      1 Page          2.7:1\r
+                               ;    4      320 x 240      3 Pages           1:1\r
+                               ;    5      320 x 480      1 Page            2:1\r
+                               ;    6      360 x 240      3 Pages       1.125:1\r
+                               ;    7      360 x 480      1 Page         2.25:1\r
+                               ;\r
+                               ; -------------------- The Legal Stuff ------------------\r
+                               ;\r
+                               ; No warranty, either written or implied, is made as to\r
+                               ; the accuracy and usability of this code product.  Use\r
+                               ; at your own risk.  Batteries not included.  Pepperoni\r
+                               ; and extra cheese available for an additional charge.\r
+                               ;\r
+                               ; ----------------------- The Author --------------------\r
+                               ;\r
+                               ; Matt Pritchard is a paid programmer who'd rather be\r
+                               ; writing games.  He can be reached at: P.O. Box 140264,\r
+                               ; Irving, TX  75014  USA.  Michael Abrash is a living\r
+                               ; god, who now works for Bill Gates (Microsoft).\r
+                               ;\r
+                               ; -------------------- Revision History -----------------\r
+                               ; 4-12-93: v1.02 - SET_POINT & READ_POINT now saves DI\r
+                               ;          SET_MODEX now saves SI\r
+                               ; 5-3-93:  v1.04 - added LOAD_DAC_REGISTERS and\r
+                               ;          READ_DAC_REGISTERS.  Expanded CLR Macro\r
+                               ;          to handle multiple registers\r
+                               ;\r
+                                \r
+                                   PAGE    255, 132\r
+                                \r
+                                   .MODEL Medium\r
+                                   .286\r
+                                \r
+                                   ; ===== MACROS =====\r
+                                \r
+                                   ; Macro to OUT a 16 bit value to an I/O port\r
+                                \r
+                               OUT_16 MACRO Register, Value\r
+                                   IFDIFI <Register>, <DX>         ; If DX not setup\r
+                                       MOV     DX, Register        ; then Select Register\r
+                                   ENDIF\r
+                                   IFDIFI <Value>, <AX>            ; If AX not setup\r
+                                       MOV     AX, Value           ; then Get Data Value\r
+                                   ENDIF\r
+                                       OUT     DX, AX              ; Set I/O Register(s)\r
+                               ENDM\r
+                                \r
+                                   ; Macro to OUT a 8 bit value to an I/O Port\r
+                                \r
+                               OUT_8 MACRO Register, Value\r
+                                   IFDIFI <Register>, <DX>         ; If DX not setup\r
+                                       MOV     DX, Register        ; then Select Register\r
+                                   ENDIF\r
+                                   IFDIFI <Value>, <AL>            ; If AL not Setup\r
+                                       MOV     AL, Value           ; then Get Data Value\r
+                                   ENDIF\r
+                                       OUT     DX, AL              ; Set I/O Register\r
+                               ENDM\r
+                                \r
+                                   ; macros to PUSH and POP multiple registers\r
+                                \r
+                               PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+                                   IFNB <R1>\r
+                                       PUSH    R1              ; Save R1\r
+                                       PUSHx   R2, R3, R4, R5, R6, R7, R8\r
+                                   ENDIF\r
+                               ENDM\r
+                                \r
+                               POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
+                                   IFNB <R1>\r
+                                       POP     R1              ; Restore R1\r
+                                       POPx    R2, R3, R4, R5, R6, R7, R8\r
+                                   ENDIF\r
+                               ENDM\r
+                                \r
+                                   ; Macro to Clear Registers to 0\r
+                                \r
+                               CLR MACRO Register, R2, R3, R4, R5, R6\r
+                                   IFNB <Register>\r
+                                       XOR     Register, Register      ; Set Register = 0\r
+                                       CLR R2, R3, R4, R5, R6\r
+                                   ENDIF\r
+                               ENDM\r
+                                \r
+                                   ; Macros to Decrement Counter & Jump on Condition\r
+                                \r
+                               LOOPx MACRO Register, Destination\r
+                                   DEC     Register                ; Counter--\r
+                                   JNZ     Destination             ; Jump if not 0\r
+                               ENDM\r
+                                \r
+                               LOOPjz MACRO Register, Destination\r
+                                   DEC     Register                ; Counter--\r
+                                   JZ      Destination             ; Jump if 0\r
+                               ENDM\r
+                                \r
+                                \r
+                                   ; ===== General Constants =====\r
+                                \r
+ = 0000                                    False   EQU 0\r
+ =-0001                                    True    EQU -1\r
+ = 0000                                    nil     EQU 0\r
+                                \r
+ = BYTE PTR                        b       EQU BYTE PTR\r
+ = WORD PTR                        w       EQU WORD PTR\r
+ = DWORD PTR                       d       EQU DWORD PTR\r
+ = OFFSET                          o       EQU OFFSET\r
+ = FAR PTR                         f       EQU FAR PTR\r
+ = SHORT                           s       EQU SHORT\r
+ = ?,?,?,?                         ?x4     EQU <?,?,?,?>\r
+ = ?,?,?                           ?x3     EQU <?,?,?>\r
+                                \r
+                                   ; ===== VGA Register Values =====\r
+                                \r
+ = A000                                    VGA_Segment     EQU 0A000h  ; Vga Memory Segment\r
+                                \r
+ = 03C0                                    ATTRIB_Ctrl     EQU 03C0h   ; VGA Attribute Controller\r
+ = 03CE                                    GC_Index        EQU 03CEh   ; VGA Graphics Controller\r
+ = 03C4                                    SC_Index        EQU 03C4h   ; VGA Sequencer Controller\r
+ = 03C5                                    SC_Data         EQU 03C5h   ; VGA Sequencer Data Port\r
+ = 03D4                                    CRTC_Index      EQU 03D4h   ; VGA CRT Controller\r
+ = 03D5                                    CRTC_Data       EQU 03D5h   ; VGA CRT Controller Data\r
+ = 03C2                                    MISC_OUTPUT     EQU 03C2h   ; VGA Misc Register\r
+ = 03DA                                    INPUT_1         EQU 03DAh   ; Input Status #1 Register\r
+                                \r
+ = 03C8                                    DAC_WRITE_ADDR  EQU 03C8h   ; VGA DAC Write Addr Register\r
+ = 03C7                                    DAC_READ_ADDR   EQU 03C7h   ; VGA DAC Read Addr Register\r
+ = 03C9                                    PEL_DATA_REG    EQU 03C9h   ; VGA DAC/PEL data Register R/W\r
+                                \r
+ = 0033                                    PIXEL_PAN_REG   EQU 033h    ; Attrib Index: Pixel Pan Reg\r
+ = 0002                                    MAP_MASK        EQU 002h    ; Sequ Index: Write Map Mask reg\r
+ = 0004                                    READ_MAP        EQU 004h    ; GC Index: Read Map Register\r
+ = 000C                                    START_DISP_HI   EQU 00Ch    ; CRTC Index: Display Start Hi\r
+ = 000D                                    START_DISP_LO   EQU 00Dh    ; CRTC Index: Display Start Lo\r
+                                \r
+ = 0102                                    MAP_MASK_PLANE1 EQU 00102h  ; Map Register + Plane 1\r
+ = 1102                                    MAP_MASK_PLANE2 EQU 01102h  ; Map Register + Plane 1\r
+ = 0F02                                    ALL_PLANES_ON   EQU 00F02h  ; Map Register + All Bit Planes\r
+                                \r
+ = 0604                                    CHAIN4_OFF      EQU 00604h  ; Chain 4 mode Off\r
+ = 0100                                    ASYNC_RESET     EQU 00100h  ; (A)synchronous Reset\r
+ = 0300                                    SEQU_RESTART    EQU 00300h  ; Sequencer Restart\r
+                                \r
+ = 0008                                    LATCHES_ON      EQU 00008h  ; Bit Mask + Data from Latches\r
+ = FF08                                    LATCHES_OFF     EQU 0FF08h  ; Bit Mask + Data from CPU\r
+                                \r
+ = 0008                                    VERT_RETRACE    EQU 08h     ; INPUT_1: Vertical Retrace Bit\r
+ = 0003                                    PLANE_BITS      EQU 03h     ; Bits 0-1 of Xpos = Plane #\r
+ = 000F                                    ALL_PLANES      EQU 0Fh     ; All Bit Planes Selected\r
+ = 000F                                    CHAR_BITS       EQU 0Fh     ; Bits 0-3 of Character Data\r
+                                \r
+ = 1130                                    GET_CHAR_PTR    EQU 01130h  ; VGA BIOS Func: Get Char Set\r
+ = 0003                                    ROM_8x8_Lo      EQU 03h     ; ROM 8x8 Char Set Lo Pointer\r
+ = 0004                                    ROM_8x8_Hi      EQU 04h     ; ROM 8x8 Char Set Hi Pointer\r
+                                \r
+                                   ; Constants Specific for these routines\r
+                                \r
+ = 0008                                    NUM_MODES       EQU 8       ; # of Mode X Variations\r
+                                \r
+                                   ; Specific Mode Data Table format...\r
+                                \r
+ 000C                          Mode_Data_Table STRUC\r
+ 0000  00                          M_MiscR         DB  ?       ; Value of MISC_OUTPUT register\r
+ 0001  00                          M_Pages         DB  ?       ; Maximum Possible # of pages\r
+ 0002  0000                        M_XSize         DW  ?       ; X Size Displayed on screen\r
+ 0004  0000                        M_YSize         DW  ?       ; Y Size Displayed on screen\r
+ 0006  0000                        M_XMax          DW  ?       ; Maximum Possible X Size\r
+ 0008  0000                        M_YMax          DW  ?       ; Maximum Possible Y Size\r
+ 000A  0000                        M_CRTC          DW  ?       ; Table of CRTC register values\r
+                               Mode_Data_Table ENDS\r
+                                \r
+                                   ; ===== DGROUP STORAGE NEEDED (42 BYTES) =====\r
+                                \r
+ 0000                              .DATA?\r
+                                \r
+ 0000 0000                     SCREEN_WIDTH    DW  0       ; Width of a line in Bytes\r
+ 0002 0000                     SCREEN_HEIGHT   DW  0       ; Vertical Height in Pixels\r
+                                \r
+ 0004 0000                     LAST_PAGE       DW  0       ; # of Display Pages\r
+ 0006  0004 [                  PAGE_ADDR       DW  4 DUP (0)   ; Offsets to start of each page\r
+        0000\r
+       ]\r
+                                \r
+ 000E 0000                     PAGE_SIZE       DW  0       ; Size of Page in Addr Bytes\r
+                                \r
+ 0010 0000                     DISPLAY_PAGE    DW  0       ; Page # currently displayed\r
+ 0012 0000                     ACTIVE_PAGE     DW  0       ; Page # currently active\r
+                                \r
+ 0014 0000                     CURRENT_PAGE    DW  0       ; Offset of current Page\r
+ 0016 0000                     CURRENT_SEGMENT DW  0       ; Segment of VGA memory\r
+                                \r
+ 0018 0000                     CURRENT_XOFFSET DW  0       ; Current Display X Offset\r
+ 001A 0000                     CURRENT_YOFFSET DW  0       ; Current Display Y Offset\r
+                                \r
+ 001C 0000                     CURRENT_MOFFSET DW  0       ; Current Start Offset\r
+                                \r
+ 001E 0000                     MAX_XOFFSET     DW  0       ; Current Display X Offset\r
+ 0020 0000                     MAX_YOFFSET     DW  0       ; Current Display Y Offset\r
+                                \r
+ 0022 0000 0000                        CHARSET_LOW     DW  0, 0    ; Far Ptr to Char Set: 0-127\r
+ 0026 0000 0000                        CHARSET_HI      DW  0, 0    ; Far Ptr to Char Set: 128-255\r
+                                \r
+ 0000                              .CODE\r
+                                \r
+                                   ; ===== DATA TABLES =====\r
+                                \r
+                                   ; Data Tables, Put in Code Segment for Easy Access\r
+                                   ; (Like when all the other Segment Registers are in\r
+                                   ; use!!) and reduced DGROUP requirements...\r
+                                \r
+                                   ; Bit Mask Tables for Left/Right/Character Masks\r
+                                \r
+ 0000 0F 0E 0C 08              Left_Clip_Mask      DB  0FH, 0EH, 0CH, 08H\r
+                                \r
+ 0004 01 03 07 0F              Right_Clip_Mask     DB  01H, 03H, 07H, 0FH\r
+                                \r
+                                   ; Bit Patterns for converting character fonts\r
+                                \r
+ 0008 00 08 04 0C 02 0A                Char_Plane_Data     DB  00H,08H,04H,0CH,02H,0AH,06H,0EH\r
+       06 0E\r
+ 0010  01 09 05 0D 03 0B                           DB  01H,09H,05H,0DH,03H,0BH,07H,0FH\r
+       07 0F\r
+                                \r
+                                       ; CRTC Register Values for Various Configurations\r
+                                \r
+ 0018                          MODE_Single_Line:       ; CRTC Setup Data for 400/480 Line modes\r
+ 0018  4009                            DW  04009H      ; Cell Height (1 Scan Line)\r
+ 001A  0014                            DW  00014H      ; Dword Mode off\r
+ 001C  E317                            DW  0E317H      ; turn on Byte Mode\r
+ 001E  0000                            DW  nil         ; End of CRTC Data for 400/480 Line Mode\r
+                                \r
+ 0020                          MODE_Double_Line:       ; CRTC Setup Data for 200/240 Line modes\r
+ 0020  4109                            DW  04109H      ; Cell Height (2 Scan Lines)\r
+ 0022  0014                            DW  00014H      ; Dword Mode off\r
+ 0024  E317                            DW  0E317H      ; turn on Byte Mode\r
+ 0026  0000                            DW  nil         ; End of CRTC Data for 200/240 Line Mode\r
+                                \r
+ 0028                          MODE_320_Wide:          ; CRTC Setup Data for 320 Horz Pixels\r
+ 0028  5F00                            DW  05F00H      ; Horz total\r
+ 002A  4F01                            DW  04F01H      ; Horz Displayed\r
+ 002C  5002                            DW  05002H      ; Start Horz Blanking\r
+ 002E  8203                            DW  08203H      ; End Horz Blanking\r
+ 0030  5404                            DW  05404H      ; Start H Sync\r
+ 0032  8005                            DW  08005H      ; End H Sync\r
+ 0034  0000                            DW  nil         ; End of CRTC Data for 320 Horz pixels\r
+                                \r
+ 0036                          MODE_360_Wide:          ; CRTC Setup Data for 360 Horz Pixels\r
+ 0036  6B00                            DW  06B00H      ; Horz total\r
+ 0038  5901                            DW  05901H      ; Horz Displayed\r
+ 003A  5A02                            DW  05A02H      ; Start Horz Blanking\r
+ 003C  8E03                            DW  08E03H      ; End Horz Blanking\r
+ 003E  5E04                            DW  05E04H      ; Start H Sync\r
+ 0040  8A05                            DW  08A05H      ; End H Sync\r
+ 0042  0000                            DW  nil         ; End of CRTC Data for 360 Horz pixels\r
+                                \r
+ 0044                          MODE_200_Tall:\r
+ 0044                          MODE_400_Tall:          ; CRTC Setup Data for 200/400 Line modes\r
+ 0044  BF06                            DW  0BF06H      ; Vertical Total\r
+ 0046  1F07                            DW  01F07H      ; Overflow\r
+ 0048  9C10                            DW  09C10H      ; V Sync Start\r
+ 004A  8E11                            DW  08E11H      ; V Sync End/Prot Cr0 Cr7\r
+ 004C  8F12                            DW  08F12H      ; Vertical Displayed\r
+ 004E  9615                            DW  09615H      ; V Blank Start\r
+ 0050  B916                            DW  0B916H      ; V Blank End\r
+ 0052  0000                            DW  nil         ; End of CRTC Data for 200/400 Lines\r
+                                \r
+ 0054                          MODE_240_Tall:\r
+ 0054                          MODE_480_Tall:          ; CRTC Setup Data for 240/480 Line modes\r
+ 0054  0D06                            DW  00D06H      ; Vertical Total\r
+ 0056  3E07                            DW  03E07H      ; Overflow\r
+ 0058  EA10                            DW  0EA10H      ; V Sync Start\r
+ 005A  8C11                            DW  08C11H      ; V Sync End/Prot Cr0 Cr7\r
+ 005C  DF12                            DW  0DF12H      ; Vertical Displayed\r
+ 005E  E715                            DW  0E715H      ; V Blank Start\r
+ 0060  0616                            DW  00616H      ; V Blank End\r
+ 0062  0000                            DW  nil         ; End of CRTC Data for 240/480 Lines\r
+                                \r
+                                       ; Table of Display Mode Tables\r
+                                \r
+ 0064                          MODE_TABLE:\r
+ 0064  0074 R 0086 R                   DW  o MODE_320x200, o MODE_320x400\r
+ 0068  00E0 R 00F2 R                   DW  o MODE_360x200, o MODE_360x400\r
+ 006C  00BC R 00CE R                   DW  o MODE_320x240, o MODE_320x480\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/02/14 15:18:33\r
+modex.asm                                                   Page 2 - 1\r
+\r
+\r
+ 0070  0098 R 00AA R                   DW  o MODE_360x240, o MODE_360x480\r
+                                \r
+                                       ; Table of Display Mode Components\r
+                                \r
+ 0074                          MODE_320x200:           ; Data for 320 by 200 Pixels\r
+                                \r
+ 0074  63                              DB  063h        ; 400 scan Lines & 25 Mhz Clock\r
+ 0075  04                              DB  4           ; Maximum of 4 Pages\r
+ 0076  0140 00C8                       DW  320, 200    ; Displayed Pixels (X,Y)\r
+ 007A  0516 0330                       DW  1302, 816   ; Max Possible X and Y Sizes\r
+                                \r
+ 007E  0028 R 0044 R                   DW  o MODE_320_Wide, o MODE_200_Tall\r
+ 0082  0020 R 0000                     DW  o MODE_Double_Line, nil\r
+                                \r
+ 0086                          MODE_320x400:           ; Data for 320 by 400 Pixels\r
+                                \r
+ 0086  63                              DB  063h        ; 400 scan Lines & 25 Mhz Clock\r
+ 0087  02                              DB  2           ; Maximum of 2 Pages\r
+ 0088  0140 0190                       DW  320, 400    ; Displayed Pixels X,Y\r
+ 008C  0288 0330                       DW  648, 816    ; Max Possible X and Y Sizes\r
+                                \r
+ 0090  0028 R 0044 R                   DW  o MODE_320_Wide, o MODE_400_Tall\r
+ 0094  0018 R 0000                     DW  o MODE_Single_Line, nil\r
+                                \r
+ 0098                          MODE_360x240:           ; Data for 360 by 240 Pixels\r
+                                \r
+ 0098  E7                              DB  0E7h        ; 480 scan Lines & 28 Mhz Clock\r
+ 0099  03                              DB  3           ; Maximum of 3 Pages\r
+ 009A  0168 00F0                       DW  360, 240    ; Displayed Pixels X,Y\r
+ 009E  0444 02D8                       DW  1092, 728   ; Max Possible X and Y Sizes\r
+                                \r
+ 00A2  0036 R 0054 R                   DW  o MODE_360_Wide, o MODE_240_Tall\r
+ 00A6  0020 R 0000                     DW  o MODE_Double_Line , nil\r
+                                \r
+ 00AA                          MODE_360x480:           ; Data for 360 by 480 Pixels\r
+                                \r
+ 00AA  E7                              DB  0E7h        ; 480 scan Lines & 28 Mhz Clock\r
+ 00AB  01                              DB  1           ; Only 1 Page Possible\r
+ 00AC  0168 01E0                       DW  360, 480    ; Displayed Pixels X,Y\r
+ 00B0  0220 02D8                       DW  544, 728    ; Max Possible X and Y Sizes\r
+                                \r
+ 00B4  0036 R 0054 R                   DW  o MODE_360_Wide, o MODE_480_Tall\r
+ 00B8  0018 R 0000                     DW  o MODE_Single_Line , nil\r
+                                \r
+ 00BC                          MODE_320x240:           ; Data for 320 by 240 Pixels\r
+                                \r
+ 00BC  E3                              DB  0E3h        ; 480 scan Lines & 25 Mhz Clock\r
+ 00BD  03                              DB  3           ; Maximum of 3 Pages\r
+ 00BE  0140 00F0                       DW  320, 240    ; Displayed Pixels X,Y\r
+ 00C2  0440 0332                       DW  1088, 818   ; Max Possible X and Y Sizes\r
+                                \r
+ 00C6  0028 R 0054 R                   DW  o MODE_320_Wide, o MODE_240_Tall\r
+ 00CA  0020 R 0000                     DW  o MODE_Double_Line, nil\r
+                                \r
+ 00CE                          MODE_320x480:           ; Data for 320 by 480 Pixels\r
+                                \r
+ 00CE  E3                              DB  0E3h        ; 480 scan Lines & 25 Mhz Clock\r
+ 00CF  01                              DB  1           ; Only 1 Page Possible\r
+ 00D0  0140 01E0                       DW  320, 480    ; Displayed Pixels X,Y\r
+ 00D4  021C 0332                       DW  540, 818    ; Max Possible X and Y Sizes\r
+                                \r
+ 00D8  0028 R 0054 R                   DW  o MODE_320_WIDE, o MODE_480_Tall\r
+ 00DC  0018 R 0000                     DW  o MODE_Single_Line, nil\r
+                                \r
+ 00E0                          MODE_360x200:           ; Data for 360 by 200 Pixels\r
+                                \r
+ 00E0  67                              DB  067h        ; 400 scan Lines & 28 Mhz Clock\r
+ 00E1  03                              DB  3           ; Maximum of 3 Pages\r
+ 00E2  0168 00C8                       DW  360, 200    ; Displayed Pixels (X,Y)\r
+ 00E6  0516 02D8                       DW  1302, 728   ; Max Possible X and Y Sizes\r
+                                \r
+ 00EA  0036 R 0044 R                   DW  o MODE_360_Wide, MODE_200_Tall\r
+ 00EE  0020 R 0000                     DW  o MODE_Double_Line, nil\r
+                                \r
+ 00F2                          MODE_360x400:           ; Data for 360 by 400 Pixels\r
+                                \r
+ 00F2  67                              DB  067h        ; 400 scan Lines & 28 Mhz Clock\r
+ 00F3  01                              DB  1           ; Maximum of 1 Pages\r
+ 00F4  0168 0190                       DW  360, 400    ; Displayed Pixels X,Y\r
+ 00F8  0288 0330                       DW  648, 816    ; Max Possible X and Y Sizes\r
+                                \r
+ 00FC  0036 R 0044 R                   DW  o MODE_360_Wide, MODE_400_Tall\r
+ 0100  0018 R 0000                     DW  o MODE_Single_Line, nil\r
+                                \r
+                                \r
+                                   ; ===== MODE X SETUP ROUTINES =====\r
+                                \r
+                               ;======================================================\r
+                               ;SET_VGA_MODEX% (ModeType%, MaxXPos%, MaxYpos%, Pages%)\r
+                               ;======================================================\r
+                               ;\r
+                               ; Sets Up the specified version of Mode X.  Allows for\r
+                               ; the setup of multiple video pages, and a virtual\r
+                               ; screen which can be larger than the displayed screen\r
+                               ; (which can then be scrolled a pixel at a time)\r
+                               ;\r
+                               ; ENTRY: ModeType = Desired Screen Resolution (0-7)\r
+                               ;\r
+                               ;     0 =  320 x 200, 4 Pages max,   1.2:1 Aspect Ratio\r
+                               ;     1 =  320 x 400, 2 Pages max,   2.4:1 Aspect Ratio\r
+                               ;     2 =  360 x 200, 3 Pages max,  1.35:1 Aspect Ratio\r
+                               ;     3 =  360 x 400, 1 Page  max,   2.7:1 Aspect Ratio\r
+                               ;     4 =  320 x 240, 3 Pages max,     1:1 Aspect Ratio\r
+                               ;     5 =  320 x 480, 1 Page  max,     2:1 Aspect Ratio\r
+                               ;     6 =  360 x 240, 3 Pages max, 1.125:1 Aspect Ratio\r
+                               ;     7 =  360 x 480, 1 Page  max,  2.25:1 Aspect Ratio\r
+                               ;\r
+                               ;        MaxXpos = The Desired Virtual Screen Width\r
+                               ;        MaxYpos = The Desired Virtual Screen Height\r
+                               ;        Pages   = The Desired # of Video Pages\r
+                               ;\r
+                               ; EXIT:  AX = Success Flag:   0 = Failure / -1= Success\r
+                               ;\r
+                                \r
+ 0016                          SVM_STACK   STRUC\r
+ 0000  0000                        SVM_Table   DW  ?   ; Offset of Mode Info Table\r
+ 0002  0000 0000 0000                          DW  ?x4 ; DI, SI, DS, BP\r
+       0000\r
+ 000A  00000000                                        DD  ?   ; Caller\r
+ 000E  0000                        SVM_Pages   DW  ?   ; # of Screen Pages desired\r
+ 0010  0000                        SVM_Ysize   DW  ?   ; Vertical Screen Size Desired\r
+ 0012  0000                        SVM_Xsize   DW  ?   ; Horizontal Screen Size Desired\r
+ 0014  0000                        SVM_Mode    DW  ?   ; Display Resolution Desired\r
+                               SVM_STACK   ENDS\r
+                                \r
+                                   PUBLIC  SET_VGA_MODEX\r
+                                \r
+ 0104                          SET_VGA_MODEX   PROC    FAR\r
+                                \r
+                                   PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+ 0104  55                   1          PUSH    BP              ; Save R1\r
+ 0105  1E                   2          PUSH    DS              ; Save R1\r
+ 0106  56                   3          PUSH    SI              ; Save R1\r
+ 0107  57                   4          PUSH    DI              ; Save R1\r
+ 0108  83 EC 02                            SUB     SP, 2               ; Allocate workspace\r
+ 010B  8B EC                       MOV     BP, SP              ; Set up Stack Frame\r
+                                \r
+                                   ; Check Legality of Mode Request....\r
+                                \r
+ 010D  8B 5E 14                            MOV     BX, [BP].SVM_Mode   ; Get Requested Mode #\r
+ 0110  83 FB 08                            CMP     BX, NUM_MODES       ; Is it 0..7?\r
+ 0113  73 47                       JAE     @SVM_BadModeSetup   ; If Not, Error out\r
+                                \r
+ 0115  D1 E3                       SHL     BX, 1                   ; Scale BX\r
+ 0117  2E: 8B B7 0064 R                    MOV     SI, w MODE_TABLE[BX]    ; CS:SI -> Mode Info\r
+ 011C  89 76 00                            MOV     [BP].SVM_Table, SI      ; Save ptr for later use\r
+                                \r
+                                   ; Check # of Requested Display Pages\r
+                                \r
+ 011F  8B 4E 0E                            MOV     CX, [BP].SVM_Pages  ; Get # of Requested Pages\r
+                                   CLR     CH                  ; Set Hi Word = 0!\r
+ 0122  32 ED                1          XOR     CH, CH      ; Set Register = 0\r
+ 0124  2E: 3A 4C 01                CMP     CL, CS:[SI].M_Pages ; Check # Pages for mode\r
+ 0128  77 32                       JA      @SVM_BadModeSetup   ; Report Error if too Many Pages\r
+ 012A  E3 30                       JCXZ    @SVM_BadModeSetup   ; Report Error if 0 Pages\r
+                                \r
+                                   ; Check Validity of X Size\r
+                                \r
+ 012C  83 66 12 F8                 AND     [BP].SVM_XSize, 0FFF8h  ; X size Mod 8 Must = 0\r
+                                \r
+ 0130  8B 46 12                            MOV     AX, [BP].SVM_XSize  ; Get Logical Screen Width\r
+ 0133  2E: 3B 44 02                CMP     AX, CS:[SI].M_XSize ; Check against Displayed X\r
+ 0137  72 23                       JB      @SVM_BadModeSetup   ; Report Error if too small\r
+ 0139  2E: 3B 44 06                CMP     AX, CS:[SI].M_XMax  ; Check against Max X\r
+ 013D  77 1D                       JA      @SVM_BadModeSetup   ; Report Error if too big\r
+                                \r
+                                   ; Check Validity of Y Size\r
+                                \r
+ 013F  8B 5E 10                            MOV     BX, [BP].SVM_YSize  ; Get Logical Screen Height\r
+ 0142  2E: 3B 5C 04                CMP     BX, CS:[SI].M_YSize ; Check against Displayed Y\r
+ 0146  72 14                       JB      @SVM_BadModeSetup   ; Report Error if too small\r
+ 0148  2E: 3B 5C 08                CMP     BX, CS:[SI].M_YMax  ; Check against Max Y\r
+ 014C  77 0E                       JA      @SVM_BadModeSetup   ; Report Error if too big\r
+                                \r
+                                   ; Enough memory to Fit it all?\r
+                                \r
+ 014E  C1 E8 02                            SHR     AX, 2               ; # of Bytes:Line = XSize/4\r
+ 0151  F7 E1                       MUL     CX                  ; AX = Bytes/Line * Pages\r
+ 0153  F7 E3                       MUL     BX                  ; DX:AX = Total VGA mem needed\r
+ 0155  71 0A                       JNO     @SVM_Continue       ; Exit if Total Size > 256K\r
+                                \r
+ 0157  4A                          DEC     DX                  ; Was it Exactly 256K???\r
+ 0158  0B D0                       OR      DX, AX              ; (DX = 1, AX = 0000)\r
+ 015A  74 05                       JZ      @SVM_Continue       ; if so, it's valid...\r
+                                \r
+ 015C                          @SVM_BadModeSetup:\r
+                                \r
+                                   CLR     AX                  ; Return Value = False\r
+ 015C  33 C0                1          XOR     AX, AX      ; Set Register = 0\r
+ 015E  E9 00E6                     JMP     @SVM_Exit           ; Normal Exit\r
+                                \r
+ 0161                          @SVM_Continue:\r
+                                \r
+ 0161  B8 0013                     MOV     AX, 13H             ; Start with Mode 13H\r
+ 0164  CD 10                       INT     10H                 ; Let BIOS Set Mode\r
+                                \r
+                                   OUT_16  SC_INDEX, CHAIN4_OFF            ; Disable Chain 4 Mode\r
+ 0166  BA 03C4              1          MOV     DX, SC_INDEX        ; then Select Register\r
+ 0169  B8 0604              1          MOV     AX, CHAIN4_OFF           ; then Get Data Value\r
+ 016C  EF                   1          OUT     DX, AX              ; Set I/O Register(s)\r
+                                   OUT_16  SC_INDEX, ASYNC_RESET           ; (A)synchronous Reset\r
+ 016D  BA 03C4              1          MOV     DX, SC_INDEX        ; then Select Register\r
+ 0170  B8 0100              1          MOV     AX, ASYNC_RESET           ; then Get Data Value\r
+ 0173  EF                   1          OUT     DX, AX              ; Set I/O Register(s)\r
+                                   OUT_8   MISC_OUTPUT, CS:[SI].M_MiscR    ; Set New Timing/Size\r
+ 0174  BA 03C2              1          MOV     DX, MISC_OUTPUT        ; then Select Register\r
+ 0177  2E: 8A 04            1          MOV     AL, CS:[SI].M_MiscR           ; then Get Data Value\r
+ 017A  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+                                   OUT_16  SC_INDEX, SEQU_RESTART          ; Restart Sequencer ...\r
+ 017B  BA 03C4              1          MOV     DX, SC_INDEX        ; then Select Register\r
+ 017E  B8 0300              1          MOV     AX, SEQU_RESTART           ; then Get Data Value\r
+ 0181  EF                   1          OUT     DX, AX              ; Set I/O Register(s)\r
+                                \r
+                                   OUT_8   CRTC_INDEX, 11H     ; Select Vert Retrace End Register\r
+ 0182  BA 03D4              1          MOV     DX, CRTC_INDEX        ; then Select Register\r
+ 0185  B0 11                1          MOV     AL, 11H           ; then Get Data Value\r
+ 0187  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+ 0188  42                          INC     DX                  ; Point to Data\r
+ 0189  EC                          IN      AL, DX              ; Get Value, Bit 7 = Protect\r
+ 018A  24 7F                       AND     AL, 7FH             ; Mask out Write Protect\r
+ 018C  EE                          OUT     DX, AL              ; And send it back\r
+                                \r
+ 018D  BA 03D4                     MOV     DX, CRTC_INDEX      ; Vga Crtc Registers\r
+ 0190  83 C6 0A                            ADD     SI, M_CRTC          ; SI -> CRTC Parameter Data\r
+                                \r
+                                   ; Load Tables of CRTC Parameters from List of Tables\r
+                                \r
+ 0193                          @SVM_Setup_Table:\r
+                                \r
+ 0193  2E: 8B 3C                   MOV     DI, CS:[SI]         ; Get Pointer to CRTC Data Tbl\r
+ 0196  83 C6 02                            ADD     SI, 2               ; Point to next Ptr Entry\r
+ 0199  0B FF                       OR      DI, DI              ; A nil Ptr means that we have\r
+ 019B  74 0D                       JZ      @SVM_Set_Data       ; finished CRTC programming\r
+                                \r
+ 019D                          @SVM_Setup_CRTC:\r
+ 019D  2E: 8B 05                   MOV     AX, CS:[DI]         ; Get CRTC Data from Table\r
+ 01A0  83 C7 02                            ADD     DI, 2               ; Advance Pointer\r
+ 01A3  0B C0                       OR      AX, AX              ; At End of Data Table?\r
+ 01A5  74 EC                       JZ      @SVM_Setup_Table    ; If so, Exit & get next Table\r
+                                \r
+ 01A7  EF                          OUT     DX, AX              ; Reprogram VGA CRTC reg\r
+ 01A8  EB F3                       JMP     s @SVM_Setup_CRTC   ; Process Next Table Entry\r
+                                \r
+                                   ; Initialize Page & Scroll info, DI = 0\r
+                                \r
+ 01AA                          @SVM_Set_Data:\r
+ 01AA  89 3E 0010 R                MOV     DISPLAY_PAGE, DI    ; Display Page = 0\r
+ 01AE  89 3E 0012 R                MOV     ACTIVE_PAGE, DI     ; Active Page = 0\r
+ 01B2  89 3E 0014 R                MOV     CURRENT_PAGE, DI    ; Current Page (Offset) = 0\r
+ 01B6  89 3E 0018 R                MOV     CURRENT_XOFFSET, DI ; Horz Scroll Index = 0\r
+ 01BA  89 3E 001A R                MOV     CURRENT_YOFFSET, DI ; Vert Scroll Index = 0\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/02/14 15:18:33\r
+modex.asm                                                   Page 3 - 1\r
+\r
+\r
+ 01BE  89 3E 001C R                MOV     CURRENT_MOFFSET, DI ; Memory Scroll Index = 0\r
+                                \r
+ 01C2  B8 A000                     MOV     AX, VGA_SEGMENT     ; Segment for VGA memory\r
+ 01C5  A3 0016 R                   MOV     CURRENT_SEGMENT, AX ; Save for Future LES's\r
+                                \r
+                                   ; Set Logical Screen Width, X Scroll and Our Data\r
+                                \r
+ 01C8  8B 76 00                            MOV     SI, [BP].SVM_Table  ; Get Saved Ptr to Mode Info\r
+ 01CB  8B 46 12                            MOV     AX, [BP].SVM_Xsize  ; Get Display Width\r
+                                \r
+ 01CE  8B C8                       MOV     CX, AX              ; CX = Logical Width\r
+ 01D0  2E: 2B 4C 02                SUB     CX, CS:[SI].M_XSize ; CX = Max X Scroll Value\r
+ 01D4  89 0E 001E R                MOV     MAX_XOFFSET, CX     ; Set Maximum X Scroll\r
+                                \r
+ 01D8  C1 E8 02                            SHR     AX, 2               ; Bytes = Pixels / 4\r
+ 01DB  A3 0000 R                   MOV     SCREEN_WIDTH, AX    ; Save Width in Pixels\r
+                                \r
+ 01DE  D1 E8                       SHR     AX, 1               ; Offset Value = Bytes / 2\r
+ 01E0  B4 13                       MOV     AH, 13h             ; CRTC Offset Register Index\r
+ 01E2  86 C4                       XCHG    AL, AH              ; Switch format for OUT\r
+ 01E4  EF                          OUT     DX, AX              ; Set VGA CRTC Offset Reg\r
+                                \r
+                                   ; Setup Data table, Y Scroll, Misc for Other Routines\r
+                                \r
+ 01E5  8B 46 10                            MOV     AX, [BP].SVM_Ysize  ; Get Logical Screen Height\r
+                                \r
+ 01E8  8B C8                       MOV     CX, AX              ; CX = Logical Height\r
+ 01EA  2E: 2B 5C 04                SUB     BX, CS:[SI].M_YSize ; CX = Max Y Scroll Value\r
+ 01EE  89 0E 0020 R                MOV     MAX_YOFFSET, CX     ; Set Maximum Y Scroll\r
+                                \r
+ 01F2  A3 0002 R                   MOV     SCREEN_HEIGHT, AX   ; Save Height in Pixels\r
+ 01F5  F7 26 0000 R                MUL     SCREEN_WIDTH        ; AX = Page Size in Bytes,\r
+ 01F9  A3 000E R                   MOV     PAGE_SIZE, AX       ; Save Page Size\r
+                                \r
+ 01FC  8B 4E 0E                            MOV     CX, [BP].SVM_Pages  ; Get # of Pages\r
+ 01FF  89 0E 0004 R                MOV     LAST_PAGE, CX       ; Save # of Pages\r
+                                \r
+                                   CLR     BX                  ; Page # = 0\r
+ 0203  33 DB                1          XOR     BX, BX      ; Set Register = 0\r
+ 0205  8B D3                       MOV     DX, BX              ; Page 0 Offset = 0\r
+                                \r
+ 0207                          @SVM_Set_Pages:\r
+                                \r
+ 0207  89 97 0006 R                MOV     PAGE_ADDR[BX], DX   ; Set Page #(BX) Offset\r
+ 020B  83 C3 02                            ADD     BX, 2               ; Page#++\r
+ 020E  03 D0                       ADD     DX, AX              ; Compute Addr of Next Page\r
+                                   LOOPx   CX, @SVM_Set_Pages  ; Loop until all Pages Set\r
+ 0210  49                   1      DEC     CX                ; Counter--\r
+ 0211  75 F4                1      JNZ     @SVM_Set_Pages             ; Jump if not 0\r
+                                \r
+                                   ; Clear VGA Memory\r
+                                \r
+                                   OUT_16  SC_INDEX, ALL_PLANES_ON ; Select All Planes\r
+ 0213  BA 03C4              1          MOV     DX, SC_INDEX        ; then Select Register\r
+ 0216  B8 0F02              1          MOV     AX, ALL_PLANES_ON           ; then Get Data Value\r
+ 0219  EF                   1          OUT     DX, AX              ; Set I/O Register(s)\r
+ 021A  C4 3E 0014 R                LES     DI, d CURRENT_PAGE      ; -> Start of VGA memory\r
+                                \r
+                                   CLR     AX                  ; AX = 0\r
+ 021E  33 C0                1          XOR     AX, AX      ; Set Register = 0\r
+ 0220  FC                          CLD                         ; Block Xfer Forwards\r
+ 0221  B9 8000                     MOV     CX, 8000H           ; 32K * 4 * 2 = 256K\r
+ 0224  F3/ AB                      REP     STOSW               ; Clear dat memory!\r
+                                \r
+                                   ; Setup Font Pointers\r
+                                \r
+ 0226  B7 03                       MOV     BH, ROM_8x8_Lo      ; Ask for 8x8 Font, 0-127\r
+ 0228  B8 1130                     MOV     AX, GET_CHAR_PTR    ; Service to Get Pointer\r
+ 022B  CD 10                       INT     10h                 ; Call VGA BIOS\r
+                                \r
+ 022D  89 2E 0022 R                MOV     CHARSET_LOW, BP     ; Save Char Set Offset\r
+ 0231  8C 06 0024 R                MOV     CHARSET_LOW+2, ES   ; Save Char Set Segment\r
+                                \r
+ 0235  B7 04                       MOV     BH, ROM_8x8_Hi      ; Ask for 8x8 Font, 128-255\r
+ 0237  B8 1130                     MOV     AX, GET_CHAR_PTR    ; Service to Get Pointer\r
+ 023A  CD 10                       INT     10h                 ; Call VGA BIOS\r
+                                \r
+ 023C  89 2E 0026 R                MOV     CHARSET_HI, BP      ; Save Char Set Offset\r
+ 0240  8C 06 0028 R                MOV     CHARSET_HI+2, ES    ; Save Char Set Segment\r
+                                \r
+ 0244  B8 FFFF                     MOV     AX, True            ; Return Success Code\r
+                                \r
+ 0247                          @SVM_EXIT:\r
+ 0247  83 C4 02                            ADD     SP, 2               ; Deallocate workspace\r
+                                   POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+ 024A  5F                   1          POP     DI              ; Restore R1\r
+ 024B  5E                   2          POP     SI              ; Restore R1\r
+ 024C  1F                   3          POP     DS              ; Restore R1\r
+ 024D  5D                   4          POP     BP              ; Restore R1\r
+ 024E  CA 0008                     RET     8                   ; Exit & Clean Up Stack\r
+                                \r
+ 0251                          SET_VGA_MODEX   ENDP\r
+                                \r
+                                \r
+                               ;==================\r
+                               ;SET_MODEX% (Mode%)\r
+                               ;==================\r
+                               ;\r
+                               ; Quickie Mode Set - Sets Up Mode X to Default Configuration\r
+                               ;\r
+                               ; ENTRY: ModeType = Desired Screen Resolution (0-7)\r
+                               ;        (See SET_VGA_MODEX for list)\r
+                               ;\r
+                               ; EXIT:  AX = Success Flag:   0 = Failure / -1= Success\r
+                               ;\r
+                                \r
+ 000A                          SM_STACK    STRUC\r
+ 0000  0000 0000                               DW  ?,? ; BP, SI\r
+ 0004  00000000                                        DD  ?   ; Caller\r
+ 0008  0000                        SM_Mode     DW  ?   ; Desired Screen Resolution\r
+                               SM_STACK    ENDS\r
+                                \r
+                                   PUBLIC  SET_MODEX\r
+                                \r
+ 0251                          SET_MODEX   PROC    FAR\r
+                                \r
+                                   PUSHx   BP, SI              ; Preserve Important registers\r
+ 0251  55                   1          PUSH    BP              ; Save R1\r
+ 0252  56                   2          PUSH    SI              ; Save R1\r
+ 0253  8B EC                       MOV     BP, SP              ; Set up Stack Frame\r
+                                \r
+                                   CLR     AX                  ; Assume Failure\r
+ 0255  33 C0                1          XOR     AX, AX      ; Set Register = 0\r
+ 0257  8B 5E 08                            MOV     BX, [BP].SM_Mode    ; Get Desired Mode #\r
+ 025A  83 FB 08                            CMP     BX, NUM_MODES       ; Is it a Valid Mode #?\r
+ 025D  73 1C                       JAE     @SMX_Exit           ; If Not, don't Bother\r
+                                \r
+ 025F  53                          PUSH    BX                  ; Push Mode Parameter\r
+                                \r
+ 0260  D1 E3                       SHL     BX, 1                   ; Scale BX to word Index\r
+ 0262  2E: 8B B7 0064 R                    MOV     SI, w MODE_TABLE[BX]    ; CS:SI -> Mode Info\r
+                                \r
+ 0267  2E: FF 74 02                PUSH    CS:[SI].M_XSize     ; Push Default X Size\r
+ 026B  2E: FF 74 04                PUSH    CS:[SI].M_Ysize     ; Push Default Y size\r
+ 026F  2E: 8A 44 01                MOV     AL, CS:[SI].M_Pages ; Get Default # of Pages\r
+                                   CLR     AH                  ; Hi Byte = 0\r
+ 0273  32 E4                1          XOR     AH, AH      ; Set Register = 0\r
+ 0275  50                          PUSH    AX                  ; Push # Pages\r
+                                \r
+ 0276  9A ---- 0104 R              CALL    f SET_VGA_MODEX     ; Set up Mode X!\r
+                                \r
+ 027B                          @SMX_Exit:\r
+                                   POPx    SI, BP              ; Restore Registers\r
+ 027B  5E                   1          POP     SI              ; Restore R1\r
+ 027C  5D                   2          POP     BP              ; Restore R1\r
+ 027D  CA 0002                     RET     2                   ; Exit & Clean Up Stack\r
+                                \r
+ 0280                          SET_MODEX   ENDP\r
+                                \r
+                                \r
+                                   ; ===== BASIC GRAPHICS PRIMITIVES =====\r
+                                \r
+                               ;============================\r
+                               ;CLEAR_VGA_SCREEN (ColorNum%)\r
+                               ;============================\r
+                               ;\r
+                               ; Clears the active display page\r
+                               ;\r
+                               ; ENTRY: ColorNum = Color Value to fill the page with\r
+                               ;\r
+                               ; EXIT:  No meaningful values returned\r
+                               ;\r
+                                \r
+ 000A                          CVS_STACK   STRUC\r
+ 0000  0000 0000                               DW  ?,? ; DI, BP\r
+ 0004  00000000                                        DD  ?   ; Caller\r
+ 0008  00 00                       CVS_COLOR   DB  ?,? ; Color to Set Screen to\r
+                               CVS_STACK   ENDS\r
+                                \r
+                                   PUBLIC  CLEAR_VGA_SCREEN\r
+                                \r
+ 0280                          CLEAR_VGA_SCREEN    PROC    FAR\r
+                                \r
+                                   PUSHx   BP, DI              ; Preserve Important Registers\r
+ 0280  55                   1          PUSH    BP              ; Save R1\r
+ 0281  57                   2          PUSH    DI              ; Save R1\r
+ 0282  8B EC                       MOV     BP, SP              ; Set up Stack Frame\r
+                                \r
+                                   OUT_16  SC_INDEX, ALL_PLANES_ON ; Select All Planes\r
+ 0284  BA 03C4              1          MOV     DX, SC_INDEX        ; then Select Register\r
+ 0287  B8 0F02              1          MOV     AX, ALL_PLANES_ON           ; then Get Data Value\r
+ 028A  EF                   1          OUT     DX, AX              ; Set I/O Register(s)\r
+ 028B  C4 3E 0014 R                LES     DI, d CURRENT_PAGE      ; Point to Active VGA Page\r
+                                \r
+ 028F  8A 46 08                            MOV     AL, [BP].CVS_COLOR  ; Get Color\r
+ 0292  8A E0                       MOV     AH, AL              ; Copy for Word Write\r
+ 0294  FC                          CLD                         ; Block fill Forwards\r
+                                \r
+ 0295  8B 0E 000E R                MOV     CX, PAGE_SIZE       ; Get Size of Page\r
+ 0299  D1 E9                       SHR     CX, 1               ; Divide by 2 for Words\r
+ 029B  F3/ AB                      REP     STOSW               ; Block Fill VGA memory\r
+                                \r
+                                   POPx    DI, BP              ; Restore Saved Registers\r
+ 029D  5F                   1          POP     DI              ; Restore R1\r
+ 029E  5D                   2          POP     BP              ; Restore R1\r
+ 029F  CA 0002                     RET     2                   ; Exit & Clean Up Stack\r
+                                \r
+ 02A2                          CLEAR_VGA_SCREEN    ENDP\r
+                                \r
+                                \r
+                               ;===================================\r
+                               ;SET_POINT (Xpos%, Ypos%, ColorNum%)\r
+                               ;===================================\r
+                               ;\r
+                               ; Plots a single Pixel on the active display page\r
+                               ;\r
+                               ; ENTRY: Xpos     = X position to plot pixel at\r
+                               ;        Ypos     = Y position to plot pixel at\r
+                               ;        ColorNum = Color to plot pixel with\r
+                               ;\r
+                               ; EXIT:  No meaningful values returned\r
+                               ;\r
+                                \r
+ 000E                          SP_STACK    STRUC\r
+ 0000  0000 0000                               DW  ?,? ; BP, DI\r
+ 0004  00000000                                        DD  ?   ; Caller\r
+ 0008  00 00                       SETP_Color  DB  ?,? ; Color of Point to Plot\r
+ 000A  0000                        SETP_Ypos   DW  ?   ; Y pos of Point to Plot\r
+ 000C  0000                        SETP_Xpos   DW  ?   ; X pos of Point to Plot\r
+                               SP_STACK    ENDS\r
+                                \r
+                                       PUBLIC SET_POINT\r
+                                \r
+ 02A2                          SET_POINT   PROC    FAR\r
+                                \r
+                                   PUSHx   BP, DI              ; Preserve Registers\r
+ 02A2  55                   1          PUSH    BP              ; Save R1\r
+ 02A3  57                   2          PUSH    DI              ; Save R1\r
+ 02A4  8B EC                       MOV     BP, SP              ; Set up Stack Frame\r
+                                \r
+ 02A6  C4 3E 0014 R                LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+                                \r
+ 02AA  8B 46 0A                            MOV     AX, [BP].SETP_Ypos  ; Get Line # of Pixel\r
+ 02AD  F7 26 0000 R                MUL     SCREEN_WIDTH        ; Get Offset to Start of Line\r
+                                \r
+ 02B1  8B 5E 0C                            MOV     BX, [BP].SETP_Xpos  ; Get Xpos\r
+ 02B4  8B CB                       MOV     CX, BX              ; Copy to extract Plane # from\r
+ 02B6  C1 EB 02                            SHR     BX, 2               ; X offset (Bytes) = Xpos/4\r
+ 02B9  03 D8                       ADD     BX, AX              ; Offset = Width*Ypos + Xpos/4\r
+                                \r
+ 02BB  B8 0102                     MOV     AX, MAP_MASK_PLANE1 ; Map Mask & Plane Select Register\r
+ 02BE  80 E1 03                            AND     CL, PLANE_BITS      ; Get Plane Bits\r
+ 02C1  D2 E4                       SHL     AH, CL              ; Get Plane Select Value\r
+                                   OUT_16  SC_Index, AX        ; Select Plane\r
+ 02C3  BA 03C4              1          MOV     DX, SC_Index        ; then Select Register\r
+ 02C6  EF                   1          OUT     DX, AX              ; Set I/O Register(s)\r
+                                \r
+ 02C7  8A 46 08                            MOV     AL,[BP].SETP_Color  ; Get Pixel Color\r
+ 02CA  26: 88 01                   MOV     ES:[DI+BX], AL      ; Draw Pixel\r
+                                \r
+                                   POPx    DI, BP              ; Restore Saved Registers\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/02/14 15:18:33\r
+modex.asm                                                   Page 4 - 1\r
+\r
+\r
+ 02CD  5F                   1          POP     DI              ; Restore R1\r
+ 02CE  5D                   2          POP     BP              ; Restore R1\r
+ 02CF  CA 0006                     RET     6                   ; Exit and Clean up Stack\r
+                                \r
+ 02D2                          SET_POINT        ENDP\r
+                                \r
+                                \r
+                               ;==========================\r
+                               ;READ_POINT% (Xpos%, Ypos%)\r
+                               ;==========================\r
+                               ;\r
+                               ; Read the color of a pixel from the Active Display Page\r
+                               ;\r
+                               ; ENTRY: Xpos = X position of pixel to read\r
+                               ;        Ypos = Y position of pixel to read\r
+                               ;\r
+                               ; EXIT:  AX   = Color of Pixel at (Xpos, Ypos)\r
+                               ;\r
+                                \r
+ 000C                          RP_STACK    STRUC\r
+ 0000  0000 0000                           DW  ?,? ; BP, DI\r
+ 0004  00000000                                    DD  ?   ; Caller\r
+ 0008  0000                        RP_Ypos DW  ?   ; Y pos of Point to Read\r
+ 000A  0000                        RP_Xpos DW  ?   ; X pos of Point to Read\r
+                               RP_STACK    ENDS\r
+                                \r
+                                       PUBLIC  READ_POINT\r
+                                \r
+ 02D2                          READ_POINT      PROC    FAR\r
+                                \r
+                                   PUSHx   BP, DI              ; Preserve Registers\r
+ 02D2  55                   1          PUSH    BP              ; Save R1\r
+ 02D3  57                   2          PUSH    DI              ; Save R1\r
+ 02D4  8B EC                       MOV     BP, SP              ; Set up Stack Frame\r
+                                \r
+ 02D6  C4 3E 0014 R                LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+                                \r
+ 02DA  8B 46 08                            MOV     AX, [BP].RP_Ypos    ; Get Line # of Pixel\r
+ 02DD  F7 26 0000 R                MUL     SCREEN_WIDTH        ; Get Offset to Start of Line\r
+                                \r
+ 02E1  8B 5E 0A                            MOV     BX, [BP].RP_Xpos    ; Get Xpos\r
+ 02E4  8B CB                       MOV     CX, BX\r
+ 02E6  C1 EB 02                            SHR     BX, 2               ; X offset (Bytes) = Xpos/4\r
+ 02E9  03 D8                       ADD     BX, AX              ; Offset = Width*Ypos + Xpos/4\r
+                                \r
+ 02EB  B0 04                       MOV     AL, READ_MAP        ; GC Read Mask Register\r
+ 02ED  8A E1                       MOV     AH, CL              ; Get Xpos\r
+ 02EF  80 E4 03                            AND     AH, PLANE_BITS      ; & mask out Plane #\r
+                                   OUT_16  GC_INDEX, AX        ; Select Plane to read in\r
+ 02F2  BA 03CE              1          MOV     DX, GC_INDEX        ; then Select Register\r
+ 02F5  EF                   1          OUT     DX, AX              ; Set I/O Register(s)\r
+                                \r
+                                   CLR     AH                  ; Clear Return Value Hi byte\r
+ 02F6  32 E4                1          XOR     AH, AH      ; Set Register = 0\r
+ 02F8  26: 8A 01                   MOV     AL, ES:[DI+BX]      ; Get Color of Pixel\r
+                                \r
+                                   POPx    DI, BP              ; Restore Saved Registers\r
+ 02FB  5F                   1          POP     DI              ; Restore R1\r
+ 02FC  5D                   2          POP     BP              ; Restore R1\r
+ 02FD  CA 0004                     RET     4                   ; Exit and Clean up Stack\r
+                                \r
+ 0300                          READ_POINT        ENDP\r
+                                \r
+                                \r
+                               ;======================================================\r
+                               ;FILL_BLOCK (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%)\r
+                               ;======================================================\r
+                               ;\r
+                               ; Fills a rectangular block on the active display Page\r
+                               ;\r
+                               ; ENTRY: Xpos1    = Left X position of area to fill\r
+                               ;        Ypos1    = Top Y position of area to fill\r
+                               ;        Xpos2    = Right X position of area to fill\r
+                               ;        Ypos2    = Bottom Y position of area to fill\r
+                               ;        ColorNum = Color to fill area with\r
+                               ;\r
+                               ; EXIT:  No meaningful values returned\r
+                               ;\r
+                                \r
+ 0016                          FB_STACK    STRUC\r
+ 0000  0000 0000 0000                          DW  ?x4 ; DS, DI, SI, BP\r
+       0000\r
+ 0008  00000000                                        DD  ?   ; Caller\r
+ 000C  00 00                       FB_Color    DB  ?,? ; Fill Color\r
+ 000E  0000                        FB_Ypos2    DW  ?   ; Y pos of Lower Right Pixel\r
+ 0010  0000                        FB_Xpos2    DW  ?   ; X pos of Lower Right Pixel\r
+ 0012  0000                        FB_Ypos1    DW  ?   ; Y pos of Upper Left Pixel\r
+ 0014  0000                        FB_Xpos1    DW  ?   ; X pos of Upper Left Pixel\r
+                               FB_STACK    ENDS\r
+                                \r
+                                       PUBLIC    FILL_BLOCK\r
+                                \r
+ 0300                          FILL_BLOCK  PROC    FAR\r
+                                \r
+                                   PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+ 0300  55                   1          PUSH    BP              ; Save R1\r
+ 0301  1E                   2          PUSH    DS              ; Save R1\r
+ 0302  56                   3          PUSH    SI              ; Save R1\r
+ 0303  57                   4          PUSH    DI              ; Save R1\r
+ 0304  8B EC                       MOV     BP, SP              ; Set up Stack Frame\r
+                                \r
+ 0306  C4 3E 0014 R                LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+ 030A  FC                          CLD                         ; Direction Flag = Forward\r
+                                \r
+                                   OUT_8   SC_INDEX, MAP_MASK  ; Set up for Plane Select\r
+ 030B  BA 03C4              1          MOV     DX, SC_INDEX        ; then Select Register\r
+ 030E  B0 02                1          MOV     AL, MAP_MASK           ; then Get Data Value\r
+ 0310  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+                                \r
+                                   ; Validate Pixel Coordinates\r
+                                   ; If necessary, Swap so X1 <= X2, Y1 <= Y2\r
+                                \r
+ 0311  8B 46 12                            MOV     AX, [BP].FB_Ypos1   ; AX = Y1   is Y1< Y2?\r
+ 0314  8B 5E 0E                            MOV     BX, [BP].FB_Ypos2   ; BX = Y2\r
+ 0317  3B C3                       CMP     AX, BX\r
+ 0319  7E 04                       JLE     @FB_NOSWAP1\r
+                                \r
+ 031B  89 5E 12                            MOV     [BP].FB_Ypos1, BX   ; Swap Y1 and Y2 and save Y1\r
+ 031E  93                          XCHG    AX, BX              ; on stack for future use\r
+                                \r
+ 031F                          @FB_NOSWAP1:\r
+ 031F  2B D8                       SUB     BX, AX              ; Get Y width\r
+ 0321  43                          INC     BX                  ; Add 1 to avoid 0 value\r
+ 0322  89 5E 0E                            MOV     [BP].FB_Ypos2, BX   ; Save in Ypos2\r
+                                \r
+ 0325  F7 26 0000 R                MUL     SCREEN_WIDTH        ; Mul Y1 by Bytes per Line\r
+ 0329  03 F8                       ADD     DI, AX              ; DI = Start of Line Y1\r
+                                \r
+ 032B  8B 46 14                            MOV     AX, [BP].FB_Xpos1   ; Check X1 <= X2\r
+ 032E  8B 5E 10                            MOV     BX, [BP].FB_Xpos2   ;\r
+ 0331  3B C3                       CMP     AX, BX\r
+ 0333  7E 04                       JLE     @FB_NOSWAP2         ; Skip Ahead if Ok\r
+                                \r
+ 0335  89 46 10                            MOV     [BP].FB_Xpos2, AX   ; Swap X1 AND X2 and save X2\r
+ 0338  93                          XCHG    AX, BX              ; on stack for future use\r
+                                \r
+                                   ; All our Input Values are in order, Now determine\r
+                                   ; How many full "bands" 4 pixels wide (aligned) there\r
+                                   ; are, and if there are partial bands (<4 pixels) on\r
+                                   ; the left and right edges.\r
+                                \r
+ 0339                          @FB_NOSWAP2:\r
+ 0339  8B D0                       MOV     DX, AX              ; DX = X1 (Pixel Position)\r
+ 033B  C1 EA 02                            SHR     DX, 2               ; DX/4 = Bytes into Line\r
+ 033E  03 FA                       ADD     DI, DX              ; DI = Addr of Upper-Left Corner\r
+                                \r
+ 0340  8B CB                       MOV     CX, BX              ; CX = X2 (Pixel Position)\r
+ 0342  C1 E9 02                            SHR     CX, 2               ; CX/4 = Bytes into Line\r
+                                \r
+ 0345  3B D1                       CMP     DX, CX              ; Start and end in same band?\r
+ 0347  75 03                       JNE     @FB_NORMAL          ; if not, check for l & r edges\r
+ 0349  E9 0086                     JMP     @FB_ONE_BAND_ONLY   ; if so, then special processing\r
+                                \r
+ 034C                          @FB_NORMAL:\r
+ 034C  2B CA                       SUB     CX, DX              ; CX = # bands -1\r
+ 034E  8B F0                       MOV     SI, AX              ; SI = PLANE#(X1)\r
+ 0350  83 E6 03                            AND     SI, PLANE_BITS      ; if Left edge is aligned then\r
+ 0353  74 27                       JZ      @FB_L_PLANE_FLUSH   ; no special processing..\r
+                                \r
+                                   ; Draw "Left Edge" vertical strip of 1-3 pixels...\r
+                                \r
+                                   OUT_8   SC_Data, Left_Clip_Mask[SI] ; Set Left Edge Plane Mask\r
+ 0355  BA 03C5              1          MOV     DX, SC_Data        ; then Select Register\r
+ 0358  2E: 8A 84 0000 R             1          MOV     AL, Left_Clip_Mask[SI]           ; then Get Data Value\r
+ 035D  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+                                \r
+ 035E  8B F7                       MOV     SI, DI              ; SI = Copy of Start Addr (UL)\r
+                                \r
+ 0360  8B 56 0E                            MOV     DX, [BP].FB_Ypos2   ; Get # of Lines to draw\r
+ 0363  8A 46 0C                            MOV     AL, [BP].FB_Color   ; Get Fill Color\r
+ 0366  8B 1E 0000 R                MOV     BX, SCREEN_WIDTH    ; Get Vertical increment Value\r
+                                \r
+ 036A                          @FB_LEFT_LOOP:\r
+ 036A  26: 88 04                   MOV     ES:[SI], AL         ; Fill in Left Edge Pixels\r
+ 036D  03 F3                       ADD     SI, BX              ; Point to Next Line (Below)\r
+                                   LOOPjz  DX, @FB_LEFT_CONT   ; Exit loop if all Lines Drawn\r
+ 036F  4A                   1      DEC     DX                ; Counter--\r
+ 0370  74 08                1      JZ      @FB_LEFT_CONT             ; Jump if 0\r
+                                \r
+ 0372  26: 88 04                   MOV     ES:[SI], AL         ; Fill in Left Edge Pixels\r
+ 0375  03 F3                       ADD     SI, BX              ; Point to Next Line (Below)\r
+                                   LOOPx   DX, @FB_LEFT_LOOP   ; loop until left strip is drawn\r
+ 0377  4A                   1      DEC     DX                ; Counter--\r
+ 0378  75 F0                1      JNZ     @FB_LEFT_LOOP             ; Jump if not 0\r
+                                \r
+ 037A                          @FB_LEFT_CONT:\r
+                                \r
+ 037A  47                          INC     DI                  ; Point to Middle (or Right) Block\r
+ 037B  49                          DEC     CX                  ; Reset CX instead of JMP @FB_RIGHT\r
+                                \r
+ 037C                          @FB_L_PLANE_FLUSH:\r
+ 037C  41                          INC     CX                  ; Add in Left band to middle block\r
+                                \r
+                                   ; DI = Addr of 1st middle Pixel (band) to fill\r
+                                   ; CX = # of Bands to fill -1\r
+                                \r
+ 037D                          @FB_RIGHT:\r
+ 037D  8B 76 10                            MOV     SI, [BP].FB_Xpos2   ; Get Xpos2\r
+ 0380  83 E6 03                            AND     SI, PLANE_BITS      ; Get Plane values\r
+ 0383  83 FE 03                            CMP     SI, 0003            ; Plane = 3?\r
+ 0386  74 2B                       JE      @FB_R_EDGE_FLUSH    ; Hey, add to middle\r
+                                \r
+                                   ; Draw "Right Edge" vertical strip of 1-3 pixels...\r
+                                \r
+                                   OUT_8   SC_Data, Right_Clip_Mask[SI]    ; Right Edge Plane Mask\r
+ 0388  BA 03C5              1          MOV     DX, SC_Data        ; then Select Register\r
+ 038B  2E: 8A 84 0004 R             1          MOV     AL, Right_Clip_Mask[SI]           ; then Get Data Value\r
+ 0390  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+                                \r
+ 0391  8B F7                       MOV     SI, DI              ; Get Addr of Left Edge\r
+ 0393  03 F1                       ADD     SI, CX              ; Add Width-1 (Bands)\r
+ 0395  4E                          DEC     SI                  ; To point to top of Right Edge\r
+                                \r
+ 0396  8B 56 0E                            MOV     DX, [BP].FB_Ypos2   ; Get # of Lines to draw\r
+ 0399  8A 46 0C                            MOV     AL, [BP].FB_Color   ; Get Fill Color\r
+ 039C  8B 1E 0000 R                MOV     BX, SCREEN_WIDTH    ; Get Vertical increment Value\r
+                                \r
+ 03A0                          @FB_RIGHT_LOOP:\r
+ 03A0  26: 88 04                   MOV     ES:[SI], AL         ; Fill in Right Edge Pixels\r
+ 03A3  03 F3                       ADD     SI, BX              ; Point to Next Line (Below)\r
+                                   LOOPjz  DX, @FB_RIGHT_CONT  ; Exit loop if all Lines Drawn\r
+ 03A5  4A                   1      DEC     DX                ; Counter--\r
+ 03A6  74 08                1      JZ      @FB_RIGHT_CONT             ; Jump if 0\r
+                                \r
+ 03A8  26: 88 04                   MOV     ES:[SI], AL         ; Fill in Right Edge Pixels\r
+ 03AB  03 F3                       ADD     SI, BX              ; Point to Next Line (Below)\r
+                                   LOOPx   DX, @FB_RIGHT_LOOP  ; loop until left strip is drawn\r
+ 03AD  4A                   1      DEC     DX                ; Counter--\r
+ 03AE  75 F0                1      JNZ     @FB_RIGHT_LOOP             ; Jump if not 0\r
+                                \r
+ 03B0                          @FB_RIGHT_CONT:\r
+                                \r
+ 03B0  49                          DEC     CX                  ; Minus 1 for Middle bands\r
+ 03B1  74 51                       JZ      @FB_EXIT            ; Uh.. no Middle bands...\r
+                                \r
+ 03B3                          @FB_R_EDGE_FLUSH:\r
+                                \r
+                                   ; DI = Addr of Upper Left block to fill\r
+                                   ; CX = # of Bands to fill in (width)\r
+                                \r
+                                   OUT_8   SC_Data, ALL_PLANES ; Write to All Planes\r
+ 03B3  BA 03C5              1          MOV     DX, SC_Data        ; then Select Register\r
+ 03B6  B0 0F                1          MOV     AL, ALL_PLANES           ; then Get Data Value\r
+ 03B8  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+                                \r
+ 03B9  8B 16 0000 R                MOV     DX, SCREEN_WIDTH    ; DX = DI Increment\r
+ 03BD  2B D1                       SUB     DX, CX              ;  = Screen_Width-# Planes Filled\r
+                                \r
+ 03BF  8B D9                       MOV     BX, CX              ; BX = Quick Refill for CX\r
+ 03C1  8B 76 0E                            MOV     SI, [BP].FB_Ypos2   ; SI = # of Line to Fill\r
+ 03C4  8A 46 0C                            MOV     AL, [BP].FB_Color   ; Get Fill Color\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/02/14 15:18:33\r
+modex.asm                                                   Page 5 - 1\r
+\r
+\r
+                                \r
+ 03C7                          @FB_MIDDLE_LOOP:\r
+ 03C7  F3/ AA                      REP     STOSB               ; Fill in entire line\r
+                                \r
+ 03C9  8B CB                       MOV     CX, BX              ; Recharge CX (Line Width)\r
+ 03CB  03 FA                       ADD     DI, DX              ; Point to start of Next Line\r
+                                   LOOPx   SI, @FB_MIDDLE_LOOP ; Loop until all lines drawn\r
+ 03CD  4E                   1      DEC     SI                ; Counter--\r
+ 03CE  75 F7                1      JNZ     @FB_MIDDLE_LOOP             ; Jump if not 0\r
+                                \r
+ 03D0  EB 32                       JMP     s @FB_EXIT          ; Outa here\r
+                                \r
+ 03D2                          @FB_ONE_BAND_ONLY:\r
+ 03D2  8B F0                       MOV     SI, AX                  ; Get Left Clip Mask, Save X1\r
+ 03D4  83 E6 03                            AND     SI, PLANE_BITS          ; Mask out Row #\r
+ 03D7  2E: 8A 84 0000 R                    MOV     AL, Left_Clip_Mask[SI]  ; Get Left Edge Mask\r
+ 03DC  8B F3                       MOV     SI, BX                  ; Get Right Clip Mask, Save X2\r
+ 03DE  83 E6 03                            AND     SI, PLANE_BITS          ; Mask out Row #\r
+ 03E1  2E: 22 84 0004 R                    AND     AL, Right_Clip_Mask[SI] ; Get Right Edge Mask byte\r
+                                \r
+                                   OUT_8   SC_Data, AL         ; Clip For Left & Right Masks\r
+ 03E6  BA 03C5              1          MOV     DX, SC_Data        ; then Select Register\r
+ 03E9  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+                                \r
+ 03EA  8B 4E 0E                            MOV     CX, [BP].FB_Ypos2   ; Get # of Lines to draw\r
+ 03ED  8A 46 0C                            MOV     AL, [BP].FB_Color   ; Get Fill Color\r
+ 03F0  8B 1E 0000 R                MOV     BX, SCREEN_WIDTH    ; Get Vertical increment Value\r
+                                \r
+ 03F4                          @FB_ONE_LOOP:\r
+ 03F4  26: 88 05                   MOV     ES:[DI], AL         ; Fill in Pixels\r
+ 03F7  03 FB                       ADD     DI, BX              ; Point to Next Line (Below)\r
+                                   LOOPjz  CX, @FB_EXIT        ; Exit loop if all Lines Drawn\r
+ 03F9  49                   1      DEC     CX                ; Counter--\r
+ 03FA  74 08                1      JZ      @FB_EXIT             ; Jump if 0\r
+                                \r
+ 03FC  26: 88 05                   MOV     ES:[DI], AL         ; Fill in Pixels\r
+ 03FF  03 FB                       ADD     DI, BX              ; Point to Next Line (Below)\r
+                                   LOOPx   CX, @FB_ONE_LOOP    ; loop until left strip is drawn\r
+ 0401  49                   1      DEC     CX                ; Counter--\r
+ 0402  75 F0                1      JNZ     @FB_ONE_LOOP             ; Jump if not 0\r
+                                \r
+ 0404                          @FB_EXIT:\r
+                                   POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+ 0404  5F                   1          POP     DI              ; Restore R1\r
+ 0405  5E                   2          POP     SI              ; Restore R1\r
+ 0406  1F                   3          POP     DS              ; Restore R1\r
+ 0407  5D                   4          POP     BP              ; Restore R1\r
+ 0408  CA 000A                     RET     10                  ; Exit and Clean up Stack\r
+                                \r
+ 040B                          FILL_BLOCK   ENDP\r
+                                \r
+                                \r
+                               ;=====================================================\r
+                               ;DRAW_LINE (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%)\r
+                               ;=====================================================\r
+                               ;\r
+                               ; Draws a Line on the active display page\r
+                               ;\r
+                               ; ENTRY: Xpos1    = X position of first point on line\r
+                               ;        Ypos1    = Y position of first point on line\r
+                               ;        Xpos2    = X position of last point on line\r
+                               ;        Ypos2    = Y position of last point on line\r
+                               ;        ColorNum = Color to draw line with\r
+                               ;\r
+                               ; EXIT:  No meaningful values returned\r
+                               ;\r
+                                \r
+ 0014                          DL_STACK    STRUC\r
+ 0000  0000 0000 0000                          DW  ?x3 ; DI, SI, BP\r
+ 0006  00000000                                        DD  ?   ; Caller\r
+ 000A  00 00                       DL_ColorF   DB  ?,? ; Line Draw Color\r
+ 000C  0000                        DL_Ypos2    DW  ?   ; Y pos of last point\r
+ 000E  0000                        DL_Xpos2    DW  ?   ; X pos of last point\r
+ 0010  0000                        DL_Ypos1    DW  ?   ; Y pos of first point\r
+ 0012  0000                        DL_Xpos1    DW  ?   ; X pos of first point\r
+                               DL_STACK    ENDS\r
+                                \r
+                                       PUBLIC DRAW_LINE\r
+                                \r
+ 040B                          DRAW_LINE   PROC    FAR\r
+                                \r
+                                   PUSHx   BP, SI, DI          ; Preserve Important Registers\r
+ 040B  55                   1          PUSH    BP              ; Save R1\r
+ 040C  56                   2          PUSH    SI              ; Save R1\r
+ 040D  57                   3          PUSH    DI              ; Save R1\r
+ 040E  8B EC                       MOV     BP, SP              ; Set up Stack Frame\r
+ 0410  FC                          CLD                         ; Direction Flag = Forward\r
+                                \r
+                                   OUT_8   SC_INDEX, MAP_MASK  ; Set up for Plane Select\r
+ 0411  BA 03C4              1          MOV     DX, SC_INDEX        ; then Select Register\r
+ 0414  B0 02                1          MOV     AL, MAP_MASK           ; then Get Data Value\r
+ 0416  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+ 0417  8A 6E 0A                            MOV     CH, [BP].DL_ColorF  ; Save Line Color in CH\r
+                                \r
+                                   ; Check Line Type\r
+                                \r
+ 041A  8B 76 12                            MOV     SI, [BP].DL_Xpos1   ; AX = X1   is X1< X2?\r
+ 041D  8B 7E 0E                            MOV     DI, [BP].DL_Xpos2   ; DX = X2\r
+ 0420  3B F7                       CMP     SI, DI              ; Is X1 < X2\r
+ 0422  74 5D                       JE      @DL_VLINE           ; If X1=X2, Draw Vertical Line\r
+ 0424  7C 02                       JL      @DL_NOSWAP1         ; If X1 < X2, don't swap\r
+                                \r
+ 0426  87 F7                       XCHG    SI, DI              ; X2 IS > X1, SO SWAP THEM\r
+                                \r
+ 0428                          @DL_NOSWAP1:\r
+                                \r
+                                   ; SI = X1, DI = X2\r
+                                \r
+ 0428  8B 46 10                            MOV     AX, [BP].DL_Ypos1   ; AX = Y1   is Y1 <> Y2?\r
+ 042B  3B 46 0C                            CMP     AX, [BP].DL_Ypos2   ; Y1 = Y2?\r
+ 042E  74 03                       JE      @DL_HORZ            ; If so, Draw a Horizontal Line\r
+                                \r
+ 0430  E9 0094                     JMP     @DL_BREZHAM         ; Diagonal line... go do it...\r
+                                \r
+                                   ; This Code draws a Horizontal Line in Mode X where:\r
+                                   ; SI = X1, DI = X2, and AX = Y1/Y2\r
+                                \r
+ 0433                          @DL_HORZ:\r
+                                \r
+ 0433  F7 26 0000 R                MUL     SCREEN_WIDTH        ; Offset = Ypos * Screen_Width\r
+ 0437  8B D0                       MOV     DX, AX              ; CX = Line offset into Page\r
+                                \r
+ 0439  8B C6                       MOV     AX, SI                  ; Get Left edge, Save X1\r
+ 043B  83 E6 03                            AND     SI, PLANE_BITS          ; Mask out Row #\r
+ 043E  2E: 8A 9C 0000 R                    MOV     BL, Left_Clip_Mask[SI]  ; Get Left Edge Mask\r
+ 0443  8B CF                       MOV     CX, DI                  ; Get Right edge, Save X2\r
+ 0445  83 E7 03                            AND     DI, PLANE_BITS          ; Mask out Row #\r
+ 0448  2E: 8A BD 0004 R                    MOV     BH, Right_Clip_Mask[DI] ; Get Right Edge Mask byte\r
+                                \r
+ 044D  C1 E8 02                            SHR     AX, 2               ; Get X1 Byte # (=X1/4)\r
+ 0450  C1 E9 02                            SHR     CX, 2               ; Get X2 Byte # (=X2/4)\r
+                                \r
+ 0453  C4 3E 0014 R                LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+ 0457  03 FA                       ADD     DI, DX              ; Point to Start of Line\r
+ 0459  03 F8                       ADD     DI, AX              ; Point to Pixel X1\r
+                                \r
+ 045B  2B C8                       SUB     CX, AX              ; CX = # Of Bands (-1) to set\r
+ 045D  75 02                       JNZ     @DL_LONGLN          ; jump if longer than one segment\r
+                                \r
+ 045F  22 DF                       AND     BL, BH              ; otherwise, merge clip masks\r
+                                \r
+ 0461                          @DL_LONGLN:\r
+                                \r
+                                   OUT_8   SC_Data, BL         ; Set the Left Clip Mask\r
+ 0461  BA 03C5              1          MOV     DX, SC_Data        ; then Select Register\r
+ 0464  8A C3                1          MOV     AL, BL           ; then Get Data Value\r
+ 0466  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+                                \r
+ 0467  8A 46 0A                            MOV     AL, [BP].DL_ColorF  ; Get Line Color\r
+ 046A  8A D8                       MOV     BL, AL              ; BL = Copy of Line Color\r
+ 046C  AA                          STOSB                       ; Set Left (1-4) Pixels\r
+                                \r
+ 046D  E3 55                       JCXZ    @DL_EXIT            ; Done if only one Line Segment\r
+                                \r
+ 046F  49                          DEC     CX                  ; CX = # of Middle Segments\r
+ 0470  74 07                       JZ      @DL_XRSEG           ; If no middle segments....\r
+                                \r
+                                   ; Draw Middle Segments\r
+                                \r
+                                   OUT_8   DX, ALL_PLANES      ; Write to ALL Planes\r
+ 0472  B0 0F                1          MOV     AL, ALL_PLANES           ; then Get Data Value\r
+ 0474  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+                                \r
+ 0475  8A C3                       MOV     AL, BL              ; Get Color from BL\r
+ 0477  F3/ AA                      REP     STOSB               ; Draw Middle (4 Pixel) Segments\r
+                                \r
+ 0479                          @DL_XRSEG:\r
+                                   OUT_8   DX, BH              ; Select Planes for Right Clip Mask\r
+ 0479  8A C7                1          MOV     AL, BH           ; then Get Data Value\r
+ 047B  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+ 047C  8A C3                       MOV     AL, BL              ; Get Color Value\r
+ 047E  AA                          STOSB                       ; Draw Right (1-4) Pixels\r
+                                \r
+ 047F  EB 43                       JMP     s @DL_EXIT          ; We Are Done...\r
+                                \r
+                                \r
+                                   ; This Code Draws A Vertical Line.  On entry:\r
+                                   ; CH = Line Color, SI & DI = X1\r
+                                \r
+ 0481                          @DL_VLINE:\r
+                                \r
+ 0481  8B 46 10                            MOV     AX, [BP].DL_Ypos1   ; AX = Y1\r
+ 0484  8B 76 0C                            MOV     SI, [BP].DL_Ypos2   ; SI = Y2\r
+ 0487  3B C6                       CMP     AX, SI              ; Is Y1 < Y2?\r
+ 0489  7E 01                       JLE     @DL_NOSWAP2         ; if so, Don't Swap them\r
+                                \r
+ 048B  96                          XCHG    AX, SI              ; Ok, NOW Y1 < Y2\r
+                                \r
+ 048C                          @DL_NOSWAP2:\r
+                                \r
+ 048C  2B F0                       SUB     SI, AX              ; SI = Line Height (Y2-Y1+1)\r
+ 048E  46                          INC     SI\r
+                                \r
+                                   ; AX = Y1, DI = X1, Get offset into Page into AX\r
+                                \r
+ 048F  F7 26 0000 R                MUL     SCREEN_WIDTH        ; Offset = Y1 (AX) * Screen Width\r
+ 0493  8B D7                       MOV     DX, DI              ; Copy Xpos into DX\r
+ 0495  C1 EF 02                            SHR     DI, 2               ; DI = Xpos/4\r
+ 0498  03 C7                       ADD     AX, DI              ; DI = Xpos/4 + ScreenWidth * Y1\r
+                                \r
+ 049A  C4 3E 0014 R                LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+ 049E  03 F8                       ADD     DI, AX              ; Point to Pixel X1, Y1\r
+                                \r
+                                   ;Select Plane\r
+                                \r
+ 04A0  8A CA                       MOV     CL, DL              ; CL = Save X1\r
+ 04A2  80 E1 03                            AND     CL, PLANE_BITS      ; Get X1 MOD 4 (Plane #)\r
+ 04A5  B8 0102                     MOV     AX, MAP_MASK_PLANE1 ; Code to set Plane #1\r
+ 04A8  D2 E4                       SHL     AH, CL              ; Change to Correct Plane #\r
+                                   OUT_16  SC_Index, AX        ; Select Plane\r
+ 04AA  BA 03C4              1          MOV     DX, SC_Index        ; then Select Register\r
+ 04AD  EF                   1          OUT     DX, AX              ; Set I/O Register(s)\r
+                                \r
+ 04AE  8A C5                       MOV     AL, CH              ; Get Saved Color\r
+ 04B0  8B 1E 0000 R                MOV     BX, SCREEN_WIDTH    ; Get Offset to Advance Line By\r
+                                \r
+ 04B4                          @DL_VLoop:\r
+ 04B4  26: 88 05                   MOV     ES:[DI], AL         ; Draw Single Pixel\r
+ 04B7  03 FB                       ADD     DI, BX              ; Point to Next Line\r
+                                   LOOPjz  SI, @DL_EXIT        ; Lines--, Exit if done\r
+ 04B9  4E                   1      DEC     SI                ; Counter--\r
+ 04BA  74 08                1      JZ      @DL_EXIT             ; Jump if 0\r
+                                \r
+ 04BC  26: 88 05                   MOV     ES:[DI], AL         ; Draw Single Pixel\r
+ 04BF  03 FB                       ADD     DI, BX              ; Point to Next Line\r
+                                   LOOPx   SI, @DL_VLoop       ; Lines--, Loop until Done\r
+ 04C1  4E                   1      DEC     SI                ; Counter--\r
+ 04C2  75 F0                1      JNZ     @DL_VLoop             ; Jump if not 0\r
+                                \r
+ 04C4                          @DL_EXIT:\r
+                                \r
+ 04C4  E9 0157                     JMP     @DL_EXIT2           ; Done!\r
+                                \r
+                                   ; This code Draws a diagonal line in Mode X\r
+                                \r
+ 04C7                          @DL_BREZHAM:\r
+ 04C7  C4 3E 0014 R                LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+                                \r
+ 04CB  8B 46 10                            MOV     AX, [BP].DL_Ypos1   ; get Y1 value\r
+ 04CE  8B 5E 0C                            MOV     BX, [BP].DL_Ypos2   ; get Y2 value\r
+ 04D1  8B 4E 12                            MOV     CX, [BP].DL_Xpos1   ; Get Starting Xpos\r
+                                \r
+ 04D4  3B D8                       CMP     BX, AX              ; Y2-Y1 is?\r
+ 04D6  73 04                       JNC     @DL_DeltaYOK        ; if Y2>=Y1 then goto...\r
+                                \r
+ 04D8  93                          XCHG    BX, AX              ; Swap em...\r
+ 04D9  8B 4E 0E                            MOV     CX, [BP].DL_Xpos2   ; Get New Starting Xpos\r
+                                \r
+ 04DC                          @DL_DeltaYOK:\r
+ 04DC  F7 26 0000 R                MUL     SCREEN_WIDTH        ; Offset = SCREEN_WIDTH * Y1\r
+                                \r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/02/14 15:18:33\r
+modex.asm                                                   Page 6 - 1\r
+\r
+\r
+ 04E0  03 F8                       ADD     DI, AX              ; DI -> Start of Line Y1 on Page\r
+ 04E2  8B C1                       MOV     AX, CX              ; AX = Xpos (X1)\r
+ 04E4  C1 E8 02                            SHR     AX, 2               ; /4 = Byte Offset into Line\r
+ 04E7  03 F8                       ADD     DI, AX              ; DI = Starting pos (X1,Y1)\r
+                                \r
+ 04E9  B0 11                       MOV     AL, 11h             ; Staring Mask\r
+ 04EB  80 E1 03                            AND     CL, PLANE_BITS      ; Get Plane #\r
+ 04EE  D2 E0                       SHL     AL, CL              ; and shift into place\r
+ 04F0  8A 66 0A                            MOV     AH, [BP].DL_ColorF  ; Color in Hi Bytes\r
+                                \r
+ 04F3  50                          PUSH    AX                  ; Save Mask,Color...\r
+                                \r
+ 04F4  8A E0                       MOV     AH, AL              ; Plane # in AH\r
+ 04F6  B0 02                       MOV     AL, MAP_MASK        ; Select Plane Register\r
+                                   OUT_16  SC_Index, AX        ; Select initial plane\r
+ 04F8  BA 03C4              1          MOV     DX, SC_Index        ; then Select Register\r
+ 04FB  EF                   1          OUT     DX, AX              ; Set I/O Register(s)\r
+                                \r
+ 04FC  8B 46 12                            MOV     AX, [BP].DL_Xpos1   ; get X1 value\r
+ 04FF  8B 5E 10                            MOV     BX, [BP].DL_Ypos1   ; get Y1 value\r
+ 0502  8B 4E 0E                            MOV     CX, [BP].DL_Xpos2   ; get X2 value\r
+ 0505  8B 56 0C                            MOV     DX, [BP].DL_Ypos2   ; get Y2 value\r
+                                \r
+ 0508  8B 2E 0000 R                MOV     BP, SCREEN_WIDTH    ; Use BP for Line width to\r
+                                                               ; to avoid extra memory access\r
+                                \r
+ 050C  2B D3                       SUB     DX, BX              ; figure Delta_Y\r
+ 050E  73 05                       JNC     @DL_DeltaYOK2       ; jump if Y2 >= Y1\r
+                                \r
+ 0510  03 DA                       ADD     BX, DX              ; put Y2 into Y1\r
+ 0512  F7 DA                       NEG     DX                  ; abs(Delta_Y)\r
+ 0514  91                          XCHG    AX, CX              ; and exchange X1 and X2\r
+                                \r
+ 0515                          @DL_DeltaYOK2:\r
+ 0515  BB 8000                     MOV     BX, 08000H          ; seed for fraction accumulator\r
+                                \r
+ 0518  2B C8                       SUB     CX, AX              ; figure Delta_X\r
+ 051A  72 03                       JC      @DL_DrawLeft        ; if negative, go left\r
+                                \r
+ 051C  E9 0084                     JMP     @DL_DrawRight       ; Draw Line that slopes right\r
+                                \r
+ 051F                          @DL_DrawLeft:\r
+                                \r
+ 051F  F7 D9                       NEG     CX                  ; abs(Delta_X)\r
+                                \r
+ 0521  3B CA                       CMP     CX, DX              ; is Delta_X < Delta_Y?\r
+ 0523  72 41                       JB      @DL_SteepLeft       ; yes, so go do steep line\r
+                                                               ; (Delta_Y iterations)\r
+                                \r
+                                   ; Draw a Shallow line to the left in Mode X\r
+                                \r
+ 0525                          @DL_ShallowLeft:\r
+                                   CLR     AX                  ; zero low word of Delta_Y * 10000h\r
+ 0525  33 C0                1          XOR     AX, AX      ; Set Register = 0\r
+ 0527  2B C2                       SUB     AX, DX              ; DX:AX <- DX * 0FFFFh\r
+ 0529  83 DA 00                            SBB     DX, 0               ; include carry\r
+ 052C  F7 F1                       DIV     CX                  ; divide by Delta_X\r
+                                \r
+ 052E  8B F3                       MOV     SI, BX              ; SI = Accumulator\r
+ 0530  8B D8                       MOV     BX, AX              ; BX = Add fraction\r
+ 0532  58                          POP     AX                  ; Get Color, Bit mask\r
+ 0533  BA 03C5                     MOV     DX, SC_Data         ; Sequence controller data register\r
+ 0536  41                          INC     CX                  ; Inc Delta_X so we can unroll loop\r
+                                \r
+                                   ; Loop (x2) to Draw Pixels, Move Left, and Maybe Down...\r
+                                \r
+ 0537                          @DL_SLLLoop:\r
+ 0537  26: 88 25                   MOV     ES:[DI], AH         ; set first pixel, plane data set up\r
+                                   LOOPjz  CX, @DL_SLLExit     ; Delta_X--, Exit if done\r
+ 053A  49                   1      DEC     CX                ; Counter--\r
+ 053B  74 26                1      JZ      @DL_SLLExit             ; Jump if 0\r
+                                \r
+ 053D  03 F3                       ADD     SI, BX              ; add numerator to accumulator\r
+ 053F  73 02                       JNC     @DL_SLLL2nc         ; move down on carry\r
+                                \r
+ 0541  03 FD                       ADD     DI, BP              ; Move Down one line...\r
+                                \r
+ 0543                          @DL_SLLL2nc:\r
+ 0543  4F                          DEC     DI                  ; Left one addr\r
+ 0544  D0 C8                       ROR     AL, 1               ; Move Left one plane, back on 0 1 2\r
+ 0546  3C 87                       CMP     AL, 87h             ; wrap?, if AL <88 then Carry set\r
+ 0548  83 D7 00                            ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+ 054B  EE                          OUT     DX, AL              ; Set up New Bit Plane mask\r
+                                \r
+ 054C  26: 88 25                   MOV     ES:[DI], AH         ; set pixel\r
+                                   LOOPjz  CX, @DL_SLLExit     ; Delta_X--, Exit if done\r
+ 054F  49                   1      DEC     CX                ; Counter--\r
+ 0550  74 11                1      JZ      @DL_SLLExit             ; Jump if 0\r
+                                \r
+ 0552  03 F3                       ADD     SI, BX              ; add numerator to accumulator,\r
+ 0554  73 02                       JNC     @DL_SLLL3nc         ; move down on carry\r
+                                \r
+ 0556  03 FD                       ADD     DI, BP              ; Move Down one line...\r
+                                \r
+ 0558                          @DL_SLLL3nc:                    ; Now move left a pixel...\r
+ 0558  4F                          DEC     DI                  ; Left one addr\r
+ 0559  D0 C8                       ROR     AL, 1               ; Move Left one plane, back on 0 1 2\r
+ 055B  3C 87                       CMP     AL, 87h             ; Wrap?, if AL <88 then Carry set\r
+ 055D  83 D7 00                            ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+ 0560  EE                          OUT     DX, AL              ; Set up New Bit Plane mask\r
+ 0561  EB D4                       JMP     s @DL_SLLLoop       ; loop until done\r
+                                \r
+ 0563                          @DL_SLLExit:\r
+ 0563  E9 00B8                     JMP     @DL_EXIT2           ; and exit\r
+                                \r
+                                   ; Draw a steep line to the left in Mode X\r
+                                \r
+ 0566                          @DL_SteepLeft:\r
+                                   CLR     AX                  ; zero low word of Delta_Y * 10000h\r
+ 0566  33 C0                1          XOR     AX, AX      ; Set Register = 0\r
+ 0568  87 D1                       XCHG    DX, CX              ; Delta_Y switched with Delta_X\r
+ 056A  F7 F1                       DIV     CX                  ; divide by Delta_Y\r
+                                \r
+ 056C  8B F3                       MOV     SI, BX              ; SI = Accumulator\r
+ 056E  8B D8                       MOV     BX, AX              ; BX = Add Fraction\r
+ 0570  58                          POP     AX                  ; Get Color, Bit mask\r
+ 0571  BA 03C5                     MOV     DX, SC_Data         ; Sequence controller data register\r
+ 0574  41                          INC     CX                  ; Inc Delta_Y so we can unroll loop\r
+                                \r
+                                   ; Loop (x2) to Draw Pixels, Move Down, and Maybe left\r
+                                \r
+ 0575                          @DL_STLLoop:\r
+                                \r
+ 0575  26: 88 25                   MOV     ES:[DI], AH         ; set first pixel\r
+                                   LOOPjz  CX, @DL_STLExit     ; Delta_Y--, Exit if done\r
+ 0578  49                   1      DEC     CX                ; Counter--\r
+ 0579  74 26                1      JZ      @DL_STLExit             ; Jump if 0\r
+                                \r
+ 057B  03 F3                       ADD     SI, BX              ; add numerator to accumulator\r
+ 057D  73 09                       JNC     @DL_STLnc2          ; No carry, just move down!\r
+                                \r
+ 057F  4F                          DEC     DI                  ; Move Left one addr\r
+ 0580  D0 C8                       ROR     AL, 1               ; Move Left one plane, back on 0 1 2\r
+ 0582  3C 87                       CMP     AL, 87h             ; Wrap?, if AL <88 then Carry set\r
+ 0584  83 D7 00                            ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+ 0587  EE                          OUT     DX, AL              ; Set up New Bit Plane mask\r
+                                \r
+ 0588                          @DL_STLnc2:\r
+ 0588  03 FD                       ADD     DI, BP              ; advance to next line.\r
+                                \r
+ 058A  26: 88 25                   MOV     ES:[DI], AH         ; set pixel\r
+                                   LOOPjz  CX, @DL_STLExit     ; Delta_Y--, Exit if done\r
+ 058D  49                   1      DEC     CX                ; Counter--\r
+ 058E  74 11                1      JZ      @DL_STLExit             ; Jump if 0\r
+                                \r
+ 0590  03 F3                       ADD     SI, BX              ; add numerator to accumulator\r
+ 0592  73 09                       JNC     @DL_STLnc3          ; No carry, just move down!\r
+                                \r
+ 0594  4F                          DEC     DI                  ; Move Left one addr\r
+ 0595  D0 C8                       ROR     AL, 1               ; Move Left one plane, back on 0 1 2\r
+ 0597  3C 87                       CMP     AL, 87h             ; Wrap?, if AL <88 then Carry set\r
+ 0599  83 D7 00                            ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+ 059C  EE                          OUT     DX, AL              ; Set up New Bit Plane mask\r
+                                \r
+ 059D                          @DL_STLnc3:\r
+ 059D  03 FD                       ADD     DI, BP              ; advance to next line.\r
+ 059F  EB D4                       JMP     s @DL_STLLoop       ; Loop until done\r
+                                \r
+ 05A1                          @DL_STLExit:\r
+ 05A1  EB 7B                       JMP     @DL_EXIT2           ; and exit\r
+                                \r
+                                   ; Draw a line that goes to the Right...\r
+                                \r
+ 05A3                          @DL_DrawRight:\r
+ 05A3  3B CA                       CMP     CX, DX              ; is Delta_X < Delta_Y?\r
+ 05A5  72 3E                       JB      @DL_SteepRight      ; yes, so go do steep line\r
+                                                               ; (Delta_Y iterations)\r
+                                \r
+                                   ; Draw a Shallow line to the Right in Mode X\r
+                                \r
+ 05A7                          @DL_ShallowRight:\r
+                                   CLR     AX                  ; zero low word of Delta_Y * 10000h\r
+ 05A7  33 C0                1          XOR     AX, AX      ; Set Register = 0\r
+ 05A9  2B C2                       SUB     AX, DX              ; DX:AX <- DX * 0FFFFh\r
+ 05AB  83 DA 00                            SBB     DX, 0               ; include carry\r
+ 05AE  F7 F1                       DIV     CX                  ; divide by Delta_X\r
+                                \r
+ 05B0  8B F3                       MOV     SI, BX              ; SI = Accumulator\r
+ 05B2  8B D8                       MOV     BX, AX              ; BX = Add Fraction\r
+ 05B4  58                          POP     AX                  ; Get Color, Bit mask\r
+ 05B5  BA 03C5                     MOV     DX, SC_Data         ; Sequence controller data register\r
+ 05B8  41                          INC     CX                  ; Inc Delta_X so we can unroll loop\r
+                                \r
+                                   ; Loop (x2) to Draw Pixels, Move Right, and Maybe Down...\r
+                                \r
+ 05B9                          @DL_SLRLoop:\r
+ 05B9  26: 88 25                   MOV     ES:[DI], AH         ; set first pixel, mask is set up\r
+                                   LOOPjz  CX, @DL_SLRExit     ; Delta_X--, Exit if done..\r
+ 05BC  49                   1      DEC     CX                ; Counter--\r
+ 05BD  74 24                1      JZ      @DL_SLRExit             ; Jump if 0\r
+                                \r
+ 05BF  03 F3                       ADD     SI, BX              ; add numerator to accumulator\r
+ 05C1  73 02                       JNC     @DL_SLR2nc          ; don't move down if carry not set\r
+                                \r
+ 05C3  03 FD                       ADD     DI, BP              ; Move Down one line...\r
+                                \r
+ 05C5                          @DL_SLR2nc:                     ; Now move right a pixel...\r
+ 05C5  D0 C0                       ROL     AL, 1               ; Move Right one addr if Plane = 0\r
+ 05C7  3C 12                       CMP     AL, 12h             ; Wrap? if AL >12 then Carry not set\r
+ 05C9  83 D7 00                            ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+ 05CC  EE                          OUT     DX, AL              ; Set up New Bit Plane mask\r
+                                \r
+ 05CD  26: 88 25                   MOV     ES:[DI], AH         ; set pixel\r
+                                   LOOPjz  CX, @DL_SLRExit     ; Delta_X--, Exit if done..\r
+ 05D0  49                   1      DEC     CX                ; Counter--\r
+ 05D1  74 10                1      JZ      @DL_SLRExit             ; Jump if 0\r
+                                \r
+ 05D3  03 F3                       ADD     SI, BX              ; add numerator to accumulator\r
+ 05D5  73 02                       JNC     @DL_SLR3nc          ; don't move down if carry not set\r
+                                \r
+ 05D7  03 FD                       ADD     DI, BP              ; Move Down one line...\r
+                                \r
+ 05D9                          @DL_SLR3nc:\r
+ 05D9  D0 C0                       ROL     AL, 1               ; Move Right one addr if Plane = 0\r
+ 05DB  3C 12                       CMP     AL, 12h             ; Wrap? if AL >12 then Carry not set\r
+ 05DD  83 D7 00                            ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+ 05E0  EE                          OUT     DX, AL              ; Set up New Bit Plane mask\r
+ 05E1  EB D6                       JMP     s @DL_SLRLoop       ; loop till done\r
+                                \r
+ 05E3                          @DL_SLRExit:\r
+ 05E3  EB 39                       JMP     @DL_EXIT2           ; and exit\r
+                                \r
+                                   ; Draw a Steep line to the Right in Mode X\r
+                                \r
+ 05E5                          @DL_SteepRight:\r
+                                   CLR     AX                  ; zero low word of Delta_Y * 10000h\r
+ 05E5  33 C0                1          XOR     AX, AX      ; Set Register = 0\r
+ 05E7  87 D1                       XCHG    DX, CX              ; Delta_Y switched with Delta_X\r
+ 05E9  F7 F1                       DIV     CX                  ; divide by Delta_Y\r
+                                \r
+ 05EB  8B F3                       MOV     SI, BX              ; SI = Accumulator\r
+ 05ED  8B D8                       MOV     BX, AX              ; BX = Add Fraction\r
+ 05EF  58                          POP     AX                  ; Get Color, Bit mask\r
+ 05F0  BA 03C5                     MOV     DX, SC_Data         ; Sequence controller data register\r
+ 05F3  41                          INC     CX                  ; Inc Delta_Y so we can unroll loop\r
+                                \r
+                                   ; Loop (x2) to Draw Pixels, Move Down, and Maybe Right\r
+                                \r
+ 05F4                          @STRLoop:\r
+ 05F4  26: 88 25                   MOV     ES:[DI], AH         ; set first pixel, mask is set up\r
+                                   LOOPjz  CX, @DL_EXIT2       ; Delta_Y--, Exit if Done\r
+ 05F7  49                   1      DEC     CX                ; Counter--\r
+ 05F8  74 24                1      JZ      @DL_EXIT2             ; Jump if 0\r
+                                \r
+ 05FA  03 F3                       ADD     SI, BX              ; add numerator to accumulator\r
+ 05FC  73 08                       JNC     @STRnc2             ; if no carry then just go down...\r
+                                \r
+ 05FE  D0 C0                       ROL     AL, 1               ; Move Right one addr if Plane = 0\r
+ 0600  3C 12                       CMP     AL, 12h             ; Wrap? if AL >12 then Carry not set\r
+ 0602  83 D7 00                            ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+ 0605  EE                          OUT     DX, AL              ; Set up New Bit Plane mask\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/02/14 15:18:33\r
+modex.asm                                                   Page 7 - 1\r
+\r
+\r
+                                \r
+ 0606                          @STRnc2:\r
+ 0606  03 FD                       ADD     DI, BP              ; advance to next line.\r
+                                \r
+ 0608  26: 88 25                   MOV     ES:[DI], AH         ; set pixel\r
+                                   LOOPjz  CX, @DL_EXIT2       ; Delta_Y--, Exit if Done\r
+ 060B  49                   1      DEC     CX                ; Counter--\r
+ 060C  74 10                1      JZ      @DL_EXIT2             ; Jump if 0\r
+                                \r
+ 060E  03 F3                       ADD     SI, BX              ; add numerator to accumulator\r
+ 0610  73 08                       JNC     @STRnc3             ; if no carry then just go down...\r
+                                \r
+ 0612  D0 C0                       ROL     AL, 1               ; Move Right one addr if Plane = 0\r
+ 0614  3C 12                       CMP     AL, 12h             ; Wrap? if AL >12 then Carry not set\r
+ 0616  83 D7 00                            ADC     DI, 0               ; Adjust Address: DI = DI + Carry\r
+ 0619  EE                          OUT     DX, AL              ; Set up New Bit Plane mask\r
+                                \r
+ 061A                          @STRnc3:\r
+ 061A  03 FD                       ADD     DI, BP              ; advance to next line.\r
+ 061C  EB D6                       JMP     s @STRLoop          ; loop till done\r
+                                \r
+ 061E                          @DL_EXIT2:\r
+                                   POPx    DI, SI, BP          ; Restore Saved Registers\r
+ 061E  5F                   1          POP     DI              ; Restore R1\r
+ 061F  5E                   2          POP     SI              ; Restore R1\r
+ 0620  5D                   3          POP     BP              ; Restore R1\r
+ 0621  CA 000A                     RET     10                  ; Exit and Clean up Stack\r
+                                \r
+ 0624                          DRAW_LINE        ENDP\r
+                                \r
+                                \r
+                                   ; ===== DAC COLOR REGISTER ROUTINES =====\r
+                                \r
+                               ;=================================================\r
+                               ;SET_DAC_REGISTER (Register%, Red%, Green%, Blue%)\r
+                               ;=================================================\r
+                               ;\r
+                               ; Sets a single (RGB) Vga Palette Register\r
+                               ;\r
+                               ; ENTRY: Register = The DAC # to modify (0-255)\r
+                               ;        Red      = The new Red Intensity (0-63)\r
+                               ;        Green    = The new Green Intensity (0-63)\r
+                               ;        Blue     = The new Blue Intensity (0-63)\r
+                               ;\r
+                               ; EXIT:  No meaningful values returned\r
+                               ;\r
+                                \r
+ 000E                          SDR_STACK   STRUC\r
+ 0000  0000                                        DW  ?   ; BP\r
+ 0002  00000000                                            DD  ?   ; Caller\r
+ 0006  00 00                       SDR_Blue        DB  ?,? ; Blue Data Value\r
+ 0008  00 00                       SDR_Green       DB  ?,? ; Green Data Value\r
+ 000A  00 00                       SDR_Red         DB  ?,? ; Red Data Value\r
+ 000C  00 00                       SDR_Register    DB  ?,? ; Palette Register #\r
+                               SDR_STACK   ENDS\r
+                                \r
+                                   PUBLIC  SET_DAC_REGISTER\r
+                                \r
+ 0624                          SET_DAC_REGISTER    PROC    FAR\r
+                                \r
+ 0624  55                          PUSH    BP                  ; Save BP\r
+ 0625  8B EC                       MOV     BP, SP              ; Set up Stack Frame\r
+                                \r
+                                   ; Select which DAC Register to modify\r
+                                \r
+                                   OUT_8   DAC_WRITE_ADDR, [BP].SDR_Register\r
+ 0627  BA 03C8              1          MOV     DX, DAC_WRITE_ADDR        ; then Select Register\r
+ 062A  8A 46 0C                     1          MOV     AL, [BP].SDR_Register           ; then Get Data Value\r
+ 062D  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+                                \r
+ 062E  BA 03C9                     MOV     DX, PEL_DATA_REG    ; Dac Data Register\r
+                                   OUT_8   DX, [BP].SDR_Red    ; Set Red Intensity\r
+ 0631  8A 46 0A                     1          MOV     AL, [BP].SDR_Red           ; then Get Data Value\r
+ 0634  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+                                   OUT_8   DX, [BP].SDR_Green  ; Set Green Intensity\r
+ 0635  8A 46 08                     1          MOV     AL, [BP].SDR_Green           ; then Get Data Value\r
+ 0638  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+                                   OUT_8   DX, [BP].SDR_Blue   ; Set Blue Intensity\r
+ 0639  8A 46 06                     1          MOV     AL, [BP].SDR_Blue           ; then Get Data Value\r
+ 063C  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+                                \r
+ 063D  5D                          POP     BP                  ; Restore Registers\r
+ 063E  CA 0008                     RET     8                   ; Exit & Clean Up Stack\r
+                                \r
+ 0641                          SET_DAC_REGISTER    ENDP\r
+                                \r
+                               ;====================================================\r
+                               ;GET_DAC_REGISTER (Register%, &Red%, &Green%, &Blue%)\r
+                               ;====================================================\r
+                               ;\r
+                               ; Reads the RGB Values of a single Vga Palette Register\r
+                               ;\r
+                               ; ENTRY: Register = The DAC # to read (0-255)\r
+                               ;        Red      = Offset to Red Variable in DS\r
+                               ;        Green    = Offset to Green Variable in DS\r
+                               ;        Blue     = Offset to Blue Variable in DS\r
+                               ;\r
+                               ; EXIT:  The values of the integer variables Red,\r
+                               ;        Green, and Blue are set to the values\r
+                               ;        taken from the specified DAC register.\r
+                               ;\r
+                                \r
+ 000E                          GDR_STACK   STRUC\r
+ 0000  0000                                        DW  ?   ; BP\r
+ 0002  00000000                                            DD  ?   ; Caller\r
+ 0006  0000                        GDR_Blue        DW  ?   ; Addr of Blue Data Value in DS\r
+ 0008  0000                        GDR_Green       DW  ?   ; Addr of Green Data Value in DS\r
+ 000A  0000                        GDR_Red         DW  ?   ; Addr of Red Data Value in DS\r
+ 000C  00 00                       GDR_Register    DB  ?,? ; Palette Register #\r
+                               GDR_STACK   ENDS\r
+                                \r
+                                   PUBLIC  GET_DAC_REGISTER\r
+                                \r
+ 0641                          GET_DAC_REGISTER    PROC    FAR\r
+                                \r
+ 0641  55                          PUSH    BP                  ; Save BP\r
+ 0642  8B EC                       MOV     BP, SP              ; Set up Stack Frame\r
+                                \r
+                                   ; Select which DAC Register to read in\r
+                                \r
+                                   OUT_8   DAC_READ_ADDR, [BP].GDR_Register\r
+ 0644  BA 03C7              1          MOV     DX, DAC_READ_ADDR        ; then Select Register\r
+ 0647  8A 46 0C                     1          MOV     AL, [BP].GDR_Register           ; then Get Data Value\r
+ 064A  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+                                \r
+ 064B  BA 03C9                     MOV     DX, PEL_DATA_REG    ; Dac Data Register\r
+                                   CLR     AX                  ; Clear AX\r
+ 064E  33 C0                1          XOR     AX, AX      ; Set Register = 0\r
+                                \r
+ 0650  EC                          IN      AL, DX              ; Read Red Value\r
+ 0651  8B 5E 0A                            MOV     BX, [BP].GDR_Red    ; Get Address of Red%\r
+ 0654  89 07                       MOV     [BX], AX            ; *Red% = AX\r
+                                \r
+ 0656  EC                          IN      AL, DX              ; Read Green Value\r
+ 0657  8B 5E 08                            MOV     BX, [BP].GDR_Green  ; Get Address of Green%\r
+ 065A  89 07                       MOV     [BX], AX            ; *Green% = AX\r
+                                \r
+ 065C  EC                          IN      AL, DX              ; Read Blue Value\r
+ 065D  8B 5E 06                            MOV     BX, [BP].GDR_Blue   ; Get Address of Blue%\r
+ 0660  89 07                       MOV     [BX], AX            ; *Blue% = AX\r
+                                \r
+ 0662  5D                          POP     BP                  ; Restore Registers\r
+ 0663  CA 0008                     RET     8                   ; Exit & Clean Up Stack\r
+                                \r
+ 0666                          GET_DAC_REGISTER    ENDP\r
+                                \r
+                                \r
+                               ;===========================================================\r
+                               ;LOAD_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%, Sync%)\r
+                               ;===========================================================\r
+                               ;\r
+                               ; Sets a Block of Vga Palette Registers\r
+                               ;\r
+                               ; ENTRY: PalData  = Far Pointer to Block of palette data\r
+                               ;        StartReg = First Register # in range to set (0-255)\r
+                               ;        EndReg   = Last Register # in Range to set (0-255)\r
+                               ;        Sync     = Wait for Vertical Retrace Flag (Boolean)\r
+                               ;\r
+                               ; EXIT:  No meaningful values returned\r
+                               ;\r
+                               ; NOTES: PalData is a linear array of 3 byte Palette values\r
+                               ;        in the order: Red  (0-63), Green (0-63), Blue (0-63)\r
+                               ;\r
+                                \r
+ 0014                          LDR_STACK   STRUC\r
+ 0000  0000 0000 0000                              DW  ?x3 ; BP, DS, SI\r
+ 0006  00000000                                            DD  ?   ; Caller\r
+ 000A  0000                        LDR_Sync        DW  ?   ; Vertical Sync Flag\r
+ 000C  00 00                       LDR_EndReg      DB  ?,? ; Last Register #\r
+ 000E  00 00                       LDR_StartReg    DB  ?,? ; First Register #\r
+ 0010  00000000                            LDR_PalData     DD  ?   ; Far Ptr to Palette Data\r
+                               LDR_STACK   ENDS\r
+                                \r
+                                   PUBLIC  LOAD_DAC_REGISTERS\r
+                                \r
+ 0666                          LOAD_DAC_REGISTERS  PROC    FAR\r
+                                \r
+                                   PUSHx   BP, DS, SI          ; Save Registers\r
+ 0666  55                   1          PUSH    BP              ; Save R1\r
+ 0667  1E                   2          PUSH    DS              ; Save R1\r
+ 0668  56                   3          PUSH    SI              ; Save R1\r
+ 0669  8B EC                       mov     BP, SP              ; Set up Stack Frame\r
+                                \r
+ 066B  8B 46 0A                            mov     AX, [BP].LDR_Sync   ; Get Vertical Sync Flag\r
+ 066E  0B C0                       or      AX, AX              ; is Sync Flag = 0?\r
+ 0670  74 05                       jz      @LDR_Load           ; if so, skip call\r
+                                \r
+ 0672  9A ---- 0795 R              call    f SYNC_DISPLAY      ; wait for vsync\r
+                                \r
+                                   ; Determine register #'s, size to copy, etc\r
+                                \r
+ 0677                          @LDR_Load:\r
+                                \r
+ 0677  C5 76 10                            lds     SI, [BP].LDR_PalData    ; DS:SI -> Palette Data\r
+ 067A  BA 03C8                     mov     DX, DAC_WRITE_ADDR      ; DAC register # selector\r
+                                \r
+                                   CLR     AX, BX                  ; Clear for byte loads\r
+ 067D  33 C0                1          XOR     AX, AX      ; Set Register = 0\r
+ 067F  33 DB                2          XOR     BX, BX      ; Set Register = 0\r
+ 0681  8A 46 0E                            mov     AL, [BP].LDR_StartReg   ; Get Start Register\r
+ 0684  8A 5E 0C                            mov     BL, [BP].LDR_EndReg     ; Get End Register\r
+                                \r
+ 0687  2B D8                       sub     BX, AX              ; BX = # of DAC registers -1\r
+ 0689  43                          inc     BX                  ; BX = # of DAC registers\r
+ 068A  8B CB                       mov     CX, BX              ; CX = # of DAC registers\r
+ 068C  03 CB                       add     CX, BX              ; CX =  "   " * 2\r
+ 068E  03 CB                       add     CX, BX              ; CX =  "   " * 3\r
+ 0690  FC                          cld                         ; Block OUTs forward\r
+ 0691  EE                          out     DX, AL              ; set up correct register #\r
+                                \r
+                                   ; Load a block of DAC Registers\r
+                                \r
+ 0692  BA 03C9                     mov     DX, PEL_DATA_REG    ; Dac Data Register\r
+                                \r
+ 0695  F3/ 6E                      rep     outsb               ; block set DAC registers\r
+                                \r
+                                   POPx    SI, DS, BP          ; Restore Registers\r
+ 0697  5E                   1          POP     SI              ; Restore R1\r
+ 0698  1F                   2          POP     DS              ; Restore R1\r
+ 0699  5D                   3          POP     BP              ; Restore R1\r
+ 069A  CA 000A                     ret     10                  ; Exit & Clean Up Stack\r
+                                \r
+ 069D                          LOAD_DAC_REGISTERS  ENDP\r
+                                \r
+                                \r
+                               ;====================================================\r
+                               ;READ_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%)\r
+                               ;====================================================\r
+                               ;\r
+                               ; Reads a Block of Vga Palette Registers\r
+                               ;\r
+                               ; ENTRY: PalData  = Far Pointer to block to store palette data\r
+                               ;        StartReg = First Register # in range to read (0-255)\r
+                               ;        EndReg   = Last Register # in Range to read (0-255)\r
+                               ;\r
+                               ; EXIT:  No meaningful values returned\r
+                               ;\r
+                               ; NOTES: PalData is a linear array of 3 byte Palette values\r
+                               ;        in the order: Red  (0-63), Green (0-63), Blue (0-63)\r
+                               ;\r
+                                \r
+ 0012                          RDR_STACK   STRUC\r
+ 0000  0000 0000 0000                              DW  ?x3 ; BP, ES, DI\r
+ 0006  00000000                                            DD  ?   ; Caller\r
+ 000A  00 00                       RDR_EndReg      DB  ?,? ; Last Register #\r
+ 000C  00 00                       RDR_StartReg    DB  ?,? ; First Register #\r
+ 000E  00000000                            RDR_PalData     DD  ?   ; Far Ptr to Palette Data\r
+                               RDR_STACK   ENDS\r
+                                \r
+                                   PUBLIC  READ_DAC_REGISTERS\r
+                                \r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/02/14 15:18:33\r
+modex.asm                                                   Page 8 - 1\r
+\r
+\r
+ 069D                          READ_DAC_REGISTERS  PROC    FAR\r
+                                \r
+                                   PUSHx   BP, ES, DI          ; Save Registers\r
+ 069D  55                   1          PUSH    BP              ; Save R1\r
+ 069E  06                   2          PUSH    ES              ; Save R1\r
+ 069F  57                   3          PUSH    DI              ; Save R1\r
+ 06A0  8B EC                       mov     BP, SP              ; Set up Stack Frame\r
+                                \r
+                                   ; Determine register #'s, size to copy, etc\r
+                                \r
+ 06A2  C4 7E 0E                            les     DI, [BP].RDR_PalData    ; ES:DI -> Palette Buffer\r
+ 06A5  BA 03C7                     mov     DX, DAC_READ_ADDR       ; DAC register # selector\r
+                                \r
+                                   CLR     AX, BX                  ; Clear for byte loads\r
+ 06A8  33 C0                1          XOR     AX, AX      ; Set Register = 0\r
+ 06AA  33 DB                2          XOR     BX, BX      ; Set Register = 0\r
+ 06AC  8A 46 0C                            mov     AL, [BP].RDR_StartReg   ; Get Start Register\r
+ 06AF  8A 5E 0A                            mov     BL, [BP].RDR_EndReg     ; Get End Register\r
+                                \r
+ 06B2  2B D8                       sub     BX, AX              ; BX = # of DAC registers -1\r
+ 06B4  43                          inc     BX                  ; BX = # of DAC registers\r
+ 06B5  8B CB                       mov     CX, BX              ; CX = # of DAC registers\r
+ 06B7  03 CB                       add     CX, BX              ; CX =  "   " * 2\r
+ 06B9  03 CB                       add     CX, BX              ; CX =  "   " * 3\r
+ 06BB  FC                          cld                         ; Block INs forward\r
+                                \r
+                                   ; Read a block of DAC Registers\r
+                                \r
+ 06BC  EE                          out     DX, AL              ; set up correct register #\r
+ 06BD  BA 03C9                     mov     DX, PEL_DATA_REG    ; Dac Data Register\r
+                                \r
+ 06C0  F3/ 6C                      rep     insb                ; block read DAC registers\r
+                                \r
+                                   POPx    DI, ES, BP          ; Restore Registers\r
+\r
+ 06C2  5F                   1          POP     DI              ; Restore R1\r
+ 06C3  07                   2          POP     ES              ; Restore R1\r
+ 06C4  5D                   3          POP     BP              ; Restore R1\r
+ 06C5  CA 0008                     ret     8                   ; Exit & Clean Up Stack\r
+                                \r
+ 06C8                          READ_DAC_REGISTERS  ENDP\r
+                                \r
+                                \r
+                                   ; ===== PAGE FLIPPING AND SCROLLING ROUTINES =====\r
+                                \r
+                               ;=========================\r
+                               ;SET_ACTIVE_PAGE (PageNo%)\r
+                               ;=========================\r
+                               ;\r
+                               ; Sets the active display Page to be used for future drawing\r
+                               ;\r
+                               ; ENTRY: PageNo = Display Page to make active\r
+                               ;        (values: 0 to Number of Pages - 1)\r
+                               ;\r
+                               ; EXIT:  No meaningful values returned\r
+                               ;\r
+                                \r
+ 0008                          SAP_STACK   STRUC\r
+ 0000  0000                                    DW  ?   ; BP\r
+ 0002  00000000                                        DD  ?   ; Caller\r
+ 0006  0000                        SAP_Page    DW  ?   ; Page # for Drawing\r
+                               SAP_STACK   ENDS\r
+                                \r
+                                   PUBLIC  SET_ACTIVE_PAGE\r
+                                \r
+ 06C8                          SET_ACTIVE_PAGE PROC    FAR\r
+                                \r
+ 06C8  55                          PUSH    BP                  ; Preserve Registers\r
+ 06C9  8B EC                       MOV     BP, SP              ; Set up Stack Frame\r
+                                \r
+ 06CB  8B 5E 06                            MOV     BX, [BP].SAP_Page   ; Get Desired Page #\r
+ 06CE  3B 1E 0004 R                CMP     BX, LAST_PAGE       ; Is Page # Valid?\r
+ 06D2  73 0D                       JAE     @SAP_Exit           ; IF Not, Do Nothing\r
+                                \r
+ 06D4  89 1E 0012 R                MOV     ACTIVE_PAGE, BX     ; Set Active Page #\r
+                                \r
+ 06D8  D1 E3                       SHL     BX, 1               ; Scale Page # to Word\r
+ 06DA  8B 87 0006 R                MOV     AX, PAGE_ADDR[BX]   ; Get offset to Page\r
+                                \r
+ 06DE  A3 0014 R                   MOV     CURRENT_PAGE, AX    ; And set for future LES's\r
+                                \r
+ 06E1                          @SAP_Exit:\r
+ 06E1  5D                          POP     BP                  ; Restore Registers\r
+ 06E2  CA 0002                     RET     2                   ; Exit and Clean up Stack\r
+                                \r
+ 06E5                          SET_ACTIVE_PAGE ENDP\r
+                                \r
+                                \r
+                               ;================\r
+                               ;GET_ACTIVE_PAGE%\r
+                               ;================\r
+                               ;\r
+                               ; Returns the Video Page # currently used for Drawing\r
+                               ;\r
+                               ; ENTRY: No Parameters are passed\r
+                               ;\r
+                               ; EXIT:  AX = Current Video Page used for Drawing\r
+                               ;\r
+                                \r
+                                   PUBLIC  GET_ACTIVE_PAGE\r
+                                \r
+ 06E5                          GET_ACTIVE_PAGE PROC    FAR\r
+                                \r
+ 06E5  A1 0012 R                   MOV     AX, ACTIVE_PAGE     ; Get Active Page #\r
+ 06E8  CB                          RET                         ; Exit and Clean up Stack\r
+                                \r
+ 06E9                          GET_ACTIVE_PAGE ENDP\r
+                                \r
+                                \r
+                               ;===============================\r
+                               ;SET_DISPLAY_PAGE (DisplayPage%)\r
+                               ;===============================\r
+                               ;\r
+                               ; Sets the currently visible display page.\r
+                               ; When called this routine syncronizes the display\r
+                               ; to the vertical blank.\r
+                               ;\r
+                               ; ENTRY: PageNo = Display Page to show on the screen\r
+                               ;        (values: 0 to Number of Pages - 1)\r
+                               ;\r
+                               ; EXIT:  No meaningful values returned\r
+                               ;\r
+                                \r
+ 0008                          SDP_STACK   STRUC\r
+ 0000  0000                                    DW  ?       ; BP\r
+ 0002  00000000                                        DD  ?       ; Caller\r
+ 0006  0000                        SDP_Page    DW  ?       ; Page # to Display...\r
+                               SDP_STACK   ENDS\r
+                                \r
+                                   PUBLIC  SET_DISPLAY_PAGE\r
+                                \r
+ 06E9                          SET_DISPLAY_PAGE    PROC    FAR\r
+                                \r
+ 06E9  55                          PUSH    BP                  ; Preserve Registers\r
+ 06EA  8B EC                       MOV     BP, SP              ; Set up Stack Frame\r
+                                \r
+ 06EC  8B 5E 06                            MOV     BX, [BP].SDP_Page   ; Get Desired Page #\r
+ 06EF  3B 1E 0004 R                CMP     BX, LAST_PAGE       ; Is Page # Valid?\r
+ 06F3  73 2B                       JAE     @SDP_Exit           ; IF Not, Do Nothing\r
+                                \r
+ 06F5  89 1E 0010 R                MOV     DISPLAY_PAGE, BX    ; Set Display Page #\r
+                                \r
+ 06F9  D1 E3                       SHL     BX, 1               ; Scale Page # to Word\r
+ 06FB  8B 8F 0006 R                MOV     CX, PAGE_ADDR[BX]   ; Get offset in memory to Page\r
+ 06FF  03 0E 001C R                ADD     CX, CURRENT_MOFFSET ; Adjust for any scrolling\r
+                                \r
+                                   ; Wait if we are currently in a Vertical Retrace\r
+                                \r
+ 0703  BA 03DA                     MOV     DX, INPUT_1         ; Input Status #1 Register\r
+                                \r
+ 0706                          @DP_WAIT0:\r
+ 0706  EC                          IN      AL, DX              ; Get VGA status\r
+ 0707  24 08                       AND     AL, VERT_RETRACE    ; In Display mode yet?\r
+ 0709  75 FB                       JNZ     @DP_WAIT0           ; If Not, wait for it\r
+                                \r
+                                   ; Set the Start Display Address to the new page\r
+                                \r
+ 070B  BA 03D4                     MOV     DX, CRTC_Index      ; We Change the VGA Sequencer\r
+                                \r
+ 070E  B0 0D                       MOV     AL, START_DISP_LO   ; Display Start Low Register\r
+ 0710  8A E1                       MOV     AH, CL              ; Low 8 Bits of Start Addr\r
+ 0712  EF                          OUT     DX, AX              ; Set Display Addr Low\r
+                                \r
+ 0713  B0 0C                       MOV     AL, START_DISP_HI   ; Display Start High Register\r
+ 0715  8A E5                       MOV     AH, CH              ; High 8 Bits of Start Addr\r
+ 0717  EF                          OUT     DX, AX              ; Set Display Addr High\r
+                                \r
+                                   ; Wait for a Vertical Retrace to smooth out things\r
+                                \r
+ 0718  BA 03DA                     MOV     DX, INPUT_1         ; Input Status #1 Register\r
+                                \r
+ 071B                          @DP_WAIT1:\r
+ 071B  EC                          IN      AL, DX              ; Get VGA status\r
+ 071C  24 08                       AND     AL, VERT_RETRACE    ; Vertical Retrace Start?\r
+ 071E  74 FB                       JZ      @DP_WAIT1           ; If Not, wait for it\r
+                                \r
+                                   ; Now Set Display Starting Address\r
+                                \r
+                                \r
+ 0720                          @SDP_Exit:\r
+ 0720  5D                          POP     BP                  ; Restore Registers\r
+ 0721  CA 0002                     RET     2                   ; Exit and Clean up Stack\r
+                                \r
+ 0724                          SET_DISPLAY_PAGE    ENDP\r
+                                \r
+                                \r
+                               ;=================\r
+                               ;GET_DISPLAY_PAGE%\r
+                               ;=================\r
+                               ;\r
+                               ; Returns the Video Page # currently displayed\r
+                               ;\r
+                               ; ENTRY: No Parameters are passed\r
+                               ;\r
+                               ; EXIT:  AX = Current Video Page being displayed\r
+                               ;\r
+                                \r
+                                   PUBLIC  GET_DISPLAY_PAGE\r
+                                \r
+ 0724                          GET_DISPLAY_PAGE    PROC    FAR\r
+                                \r
+ 0724  A1 0010 R                   MOV     AX, DISPLAY_PAGE    ; Get Display Page #\r
+ 0727  CB                          RET                         ; Exit & Clean Up Stack\r
+                                \r
+ 0728                          GET_DISPLAY_PAGE    ENDP\r
+                                \r
+                                \r
+                               ;=======================================\r
+                               ;SET_WINDOW (DisplayPage%, Xpos%, Ypos%)\r
+                               ;=======================================\r
+                               ;\r
+                               ; Since a Logical Screen can be larger than the Physical\r
+                               ; Screen, Scrolling is possible.  This routine sets the\r
+                               ; Upper Left Corner of the Screen to the specified Pixel.\r
+                               ; Also Sets the Display page to simplify combined page\r
+                               ; flipping and scrolling.  When called this routine\r
+                               ; syncronizes the display to the vertical blank.\r
+                               ;\r
+                               ; ENTRY: DisplayPage = Display Page to show on the screen\r
+                               ;        Xpos        = # of pixels to shift screen right\r
+                               ;        Ypos        = # of lines to shift screen down\r
+                               ;\r
+                               ; EXIT:  No meaningful values returned\r
+                               ;\r
+                                \r
+ 000C                          SW_STACK    STRUC\r
+ 0000  0000                                    DW  ?   ; BP\r
+ 0002  00000000                                        DD  ?   ; Caller\r
+ 0006  0000                        SW_Ypos     DW  ?   ; Y pos of UL Screen Corner\r
+ 0008  0000                        SW_Xpos     DW  ?   ; X pos of UL Screen Corner\r
+ 000A  0000                        SW_Page     DW  ?   ; (new) Display Page\r
+                               SW_STACK    ENDS\r
+                                \r
+                                       PUBLIC SET_WINDOW\r
+                                \r
+ 0728                          SET_WINDOW  PROC    FAR\r
+                                \r
+ 0728  55                          PUSH    BP                  ; Preserve Registers\r
+ 0729  8B EC                       MOV     BP, SP              ; Set up Stack Frame\r
+                                \r
+                                   ; Check if our Scroll Offsets are Valid\r
+                                \r
+ 072B  8B 5E 0A                            MOV     BX, [BP].SW_Page    ; Get Desired Page #\r
+ 072E  3B 1E 0004 R                CMP     BX, LAST_PAGE       ; Is Page # Valid?\r
+ 0732  73 55                       JAE     @SW_Exit            ; IF Not, Do Nothing\r
+                                \r
+ 0734  8B 46 06                            MOV     AX, [BP].SW_Ypos    ; Get Desired Y Offset\r
+ 0737  3B 06 0020 R                CMP     AX, MAX_YOFFSET     ; Is it Within Limits?\r
+ 073B  77 4C                       JA      @SW_Exit            ; if not, exit\r
+                                \r
+ 073D  8B 4E 08                            MOV     CX, [BP].SW_Xpos    ; Get Desired X Offset\r
+ 0740  3B 0E 001E R                CMP     CX, MAX_XOFFSET     ; Is it Within Limits?\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/02/14 15:18:33\r
+modex.asm                                                   Page 9 - 1\r
+\r
+\r
+ 0744  77 43                       JA      @SW_Exit            ; if not, exit\r
+                                \r
+                                   ; Compute proper Display start address to use\r
+                                \r
+ 0746  F7 26 0000 R                MUL     SCREEN_WIDTH        ; AX = YOffset * Line Width\r
+ 074A  C1 E9 02                            SHR     CX, 2               ; CX / 4 = Bytes into Line\r
+ 074D  03 C1                       ADD     AX, CX              ; AX = Offset of Upper Left Pixel\r
+                                \r
+ 074F  A3 001C R                   MOV     CURRENT_MOFFSET, AX ; Save Offset Info\r
+                                \r
+ 0752  89 1E 0010 R                MOV     DISPLAY_PAGE, BX    ; Set Current Page #\r
+ 0756  D1 E3                       SHL     BX, 1               ; Scale Page # to Word\r
+ 0758  03 87 0006 R                ADD     AX, PAGE_ADDR[BX]   ; Get offset in VGA to Page\r
+ 075C  8B D8                       MOV     BX, AX              ; BX = Desired Display Start\r
+                                \r
+ 075E  BA 03DA                     MOV     DX, INPUT_1         ; Input Status #1 Register\r
+                                \r
+                                   ; Wait if we are currently in a Vertical Retrace\r
+                                \r
+ 0761                          @SW_WAIT0:\r
+ 0761  EC                          IN      AL, DX              ; Get VGA status\r
+ 0762  24 08                       AND     AL, VERT_RETRACE    ; In Display mode yet?\r
+ 0764  75 FB                       JNZ     @SW_WAIT0           ; If Not, wait for it\r
+                                \r
+                                   ; Set the Start Display Address to the new window\r
+                                \r
+ 0766  BA 03D4                     MOV     DX, CRTC_Index      ; We Change the VGA Sequencer\r
+ 0769  B0 0D                       MOV     AL, START_DISP_LO   ; Display Start Low Register\r
+ 076B  8A E3                       MOV     AH, BL              ; Low 8 Bits of Start Addr\r
+ 076D  EF                          OUT     DX, AX              ; Set Display Addr Low\r
+                                \r
+ 076E  B0 0C                       MOV     AL, START_DISP_HI   ; Display Start High Register\r
+ 0770  8A E7                       MOV     AH, BH              ; High 8 Bits of Start Addr\r
+ 0772  EF                          OUT     DX, AX              ; Set Display Addr High\r
+                                \r
+                                   ; Wait for a Vertical Retrace to smooth out things\r
+                                \r
+ 0773  BA 03DA                     MOV     DX, INPUT_1         ; Input Status #1 Register\r
+                                \r
+ 0776                          @SW_WAIT1:\r
+ 0776  EC                          IN      AL, DX              ; Get VGA status\r
+ 0777  24 08                       AND     AL, VERT_RETRACE    ; Vertical Retrace Start?\r
+ 0779  74 FB                       JZ      @SW_WAIT1           ; If Not, wait for it\r
+                                \r
+                                   ; Now Set the Horizontal Pixel Pan values\r
+                                \r
+                                   OUT_8   ATTRIB_Ctrl, PIXEL_PAN_REG  ; Select Pixel Pan Register\r
+ 077B  BA 03C0              1          MOV     DX, ATTRIB_Ctrl        ; then Select Register\r
+ 077E  B0 33                1          MOV     AL, PIXEL_PAN_REG           ; then Get Data Value\r
+ 0780  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+                                \r
+ 0781  8B 46 08                            MOV     AX, [BP].SW_Xpos    ; Get Desired X Offset\r
+ 0784  24 03                       AND     AL, 03              ; Get # of Pixels to Pan (0-3)\r
+ 0786  D0 E0                       SHL     AL, 1               ; Shift for 256 Color Mode\r
+ 0788  EE                          OUT     DX, AL              ; Fine tune the display!\r
+                                \r
+ 0789                          @SW_Exit:\r
+ 0789  5D                          POP     BP                  ; Restore Saved Registers\r
+ 078A  CA 0006                     RET     6                   ; Exit and Clean up Stack\r
+                                \r
+ 078D                          SET_WINDOW        ENDP\r
+                                \r
+                                \r
+                               ;=============\r
+                               ;GET_X_OFFSET%\r
+                               ;=============\r
+                               ;\r
+                               ; Returns the X coordinate of the Pixel currently display\r
+                               ; in the upper left corner of the display\r
+                               ;\r
+                               ; ENTRY: No Parameters are passed\r
+                               ;\r
+                               ; EXIT:  AX = Current Horizontal Scroll Offset\r
+                               ;\r
+                                \r
+                                   PUBLIC  GET_X_OFFSET\r
+                                \r
+ 078D                          GET_X_OFFSET    PROC    FAR\r
+                                \r
+ 078D  A1 0018 R                   MOV     AX, CURRENT_XOFFSET ; Get current horz offset\r
+ 0790  CB                          RET                         ; Exit & Clean Up Stack\r
+                                \r
+ 0791                          GET_X_OFFSET    ENDP\r
+                                \r
+                                \r
+                               ;=============\r
+                               ;GET_Y_OFFSET%\r
+                               ;=============\r
+                               ;\r
+                               ; Returns the Y coordinate of the Pixel currently display\r
+                               ; in the upper left corner of the display\r
+                               ;\r
+                               ; ENTRY: No Parameters are passed\r
+                               ;\r
+                               ; EXIT:  AX = Current Vertical Scroll Offset\r
+                               ;\r
+                                \r
+                                   PUBLIC  GET_Y_OFFSET\r
+                                \r
+ 0791                          GET_Y_OFFSET    PROC    FAR\r
+                                \r
+ 0791  A1 001A R                   MOV     AX, CURRENT_YOFFSET ; Get current vertical offset\r
+ 0794  CB                          RET                         ; Exit & Clean Up Stack\r
+                                \r
+ 0795                          GET_Y_OFFSET    ENDP\r
+                                \r
+                                \r
+                               ;============\r
+                               ;SYNC_DISPLAY\r
+                               ;============\r
+                               ;\r
+                               ; Pauses the computer until the next Vertical Retrace starts\r
+                               ;\r
+                               ; ENTRY: No Parameters are passed\r
+                               ;\r
+                               ; EXIT:  No meaningful values returned\r
+                               ;\r
+                                \r
+                                   PUBLIC  SYNC_DISPLAY\r
+                                \r
+ 0795                          SYNC_DISPLAY    PROC    FAR\r
+                                \r
+ 0795  BA 03DA                     MOV     DX, INPUT_1         ; Input Status #1 Register\r
+                                \r
+                                   ; Wait for any current retrace to end\r
+                                \r
+ 0798                          @SD_WAIT0:\r
+ 0798  EC                          IN      AL, DX              ; Get VGA status\r
+ 0799  24 08                       AND     AL, VERT_RETRACE    ; In Display mode yet?\r
+ 079B  75 FB                       JNZ     @SD_WAIT0           ; If Not, wait for it\r
+                                \r
+                                   ; Wait for the start of the next vertical retrace\r
+                                \r
+ 079D                          @SD_WAIT1:\r
+ 079D  EC                          IN      AL, DX              ; Get VGA status\r
+ 079E  24 08                       AND     AL, VERT_RETRACE    ; Vertical Retrace Start?\r
+ 07A0  74 FB                       JZ      @SD_WAIT1           ; If Not, wait for it\r
+                                \r
+ 07A2  CB                          RET                         ; Exit & Clean Up Stack\r
+                                \r
+ 07A3                          SYNC_DISPLAY    ENDP\r
+                                \r
+                                \r
+                                   ; ===== TEXT DISPLAY ROUTINES =====\r
+                                \r
+                               ;==================================================\r
+                               ;GPRINTC (CharNum%, Xpos%, Ypos%, ColorF%, ColorB%)\r
+                               ;==================================================\r
+                               ;\r
+                               ; Draws an ASCII Text Character using the currently selected\r
+                               ; 8x8 font on the active display page.  It would be a simple\r
+                               ; exercise to make this routine process variable height fonts.\r
+                               ;\r
+                               ; ENTRY: CharNum = ASCII character # to draw\r
+                               ;        Xpos    = X position to draw Character at\r
+                               ;        Ypos    = Y position of to draw Character at\r
+                               ;        ColorF  = Color to draw text character in\r
+                               ;        ColorB  = Color to set background to\r
+                               ;\r
+                               ; EXIT:  No meaningful values returned\r
+                               ;\r
+                                \r
+ 001E                          GPC_STACK   STRUC\r
+ 0000  0000                        GPC_Width   DW  ?   ; Screen Width-1\r
+ 0002  00 00                       GPC_Lines   DB  ?,? ; Scan lines to Decode\r
+ 0004  0000                        GPC_T_SETS  DW  ?   ; Saved Charset Segment\r
+ 0006  0000                        GPC_T_SETO  DW  ?   ; Saved Charset Offset\r
+ 0008  0000 0000 0000                          DW  ?x4 ; DI, SI, DS, BP\r
+       0000\r
+ 0010  00000000                                        DD  ?   ; Caller\r
+ 0014  00 00                       GPC_ColorB  DB  ?,? ; Background Color\r
+ 0016  00 00                       GPC_ColorF  DB  ?,? ; Text Color\r
+ 0018  0000                        GPC_Ypos    DW  ?   ; Y Position to Print at\r
+ 001A  0000                        GPC_Xpos    DW  ?   ; X position to Print at\r
+ 001C  00 00                       GPC_Char    DB  ?,? ; Character to Print\r
+                               GPC_STACK   ENDS\r
+                                \r
+                                       PUBLIC GPRINTC\r
+                                \r
+ 07A3                          GPRINTC     PROC    FAR\r
+                                \r
+                                   PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+ 07A3  55                   1          PUSH    BP              ; Save R1\r
+ 07A4  1E                   2          PUSH    DS              ; Save R1\r
+ 07A5  56                   3          PUSH    SI              ; Save R1\r
+ 07A6  57                   4          PUSH    DI              ; Save R1\r
+ 07A7  83 EC 08                            SUB     SP, 8               ; Allocate WorkSpace on Stack\r
+ 07AA  8B EC                       MOV     BP, SP              ; Set up Stack Frame\r
+                                \r
+ 07AC  C4 3E 0014 R                LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+                                \r
+ 07B0  A1 0000 R                   MOV     AX, SCREEN_WIDTH    ; Get Logical Line Width\r
+ 07B3  8B D8                       MOV     BX, AX              ; BX = Screen Width\r
+ 07B5  4B                          DEC     BX                  ;    = Screen Width-1\r
+ 07B6  89 5E 00                            MOV     [BP].GPC_Width, BX  ; Save for later use\r
+                                \r
+ 07B9  F7 66 18                            MUL     [BP].GPC_Ypos       ; Start of Line = Ypos * Width\r
+ 07BC  03 F8                       ADD     DI, AX              ; DI -> Start of Line Ypos\r
+                                \r
+ 07BE  8B 46 1A                            MOV     AX, [BP].GPC_Xpos   ; Get Xpos of Character\r
+ 07C1  8B C8                       MOV     CX, AX              ; Save Copy of Xpos\r
+ 07C3  C1 E8 02                            SHR     AX, 2               ; Bytes into Line = Xpos/4\r
+ 07C6  03 F8                       ADD     DI, AX              ; DI -> (Xpos, Ypos)\r
+                                \r
+                                   ;Get Source ADDR of Character Bit Map  & Save\r
+                                \r
+ 07C8  8A 46 1C                            MOV     AL, [BP].GPC_Char   ; Get Character #\r
+ 07CB  A8 80                       TEST    AL, 080h            ; Is Hi Bit Set?\r
+ 07CD  74 0C                       JZ      @GPC_LowChar        ; Nope, use low char set ptr\r
+                                \r
+ 07CF  24 7F                       AND     AL, 07Fh            ; Mask Out Hi Bit\r
+ 07D1  8B 1E 0026 R                MOV     BX, CHARSET_HI      ; BX = Char Set Ptr:Offset\r
+ 07D5  8B 16 0028 R                MOV     DX, CHARSET_HI+2    ; DX = Char Set Ptr:Segment\r
+ 07D9  EB 08                       JMP     s @GPC_Set_Char     ; Go Setup Character Ptr\r
+                                \r
+ 07DB                          @GPC_LowChar:\r
+                                \r
+ 07DB  8B 1E 0022 R                MOV     BX, CHARSET_LOW     ; BX = Char Set Ptr:Offset\r
+ 07DF  8B 16 0024 R                MOV     DX, CHARSET_LOW+2   ; DX = Char Set Ptr:Segment\r
+                                \r
+ 07E3                          @GPC_Set_Char:\r
+ 07E3  89 56 04                            MOV     [BP].GPC_T_SETS, DX ; Save Segment on Stack\r
+                                \r
+ 07E6  B4 00                       MOV     AH, 0               ; Valid #'s are 0..127\r
+ 07E8  C1 E0 03                            SHL     AX, 3               ; * 8 Bytes Per Bitmap\r
+ 07EB  03 D8                       ADD     BX, AX              ; BX = Offset of Selected char\r
+ 07ED  89 5E 06                            MOV     [BP].GPC_T_SETO, BX ; Save Offset on Stack\r
+                                \r
+ 07F0  83 E1 03                            AND     CX, PLANE_BITS      ; Get Plane #\r
+ 07F3  B5 0F                       MOV     CH, ALL_PLANES      ; Get Initial Plane mask\r
+ 07F5  D2 E5                       SHL     CH, CL              ; And shift into position\r
+ 07F7  80 E5 0F                            AND     CH, ALL_PLANES      ; And mask to lower nibble\r
+                                \r
+ 07FA  B0 04                       MOV     AL, 04              ; 4-Plane # = # of initial\r
+ 07FC  2A C1                       SUB     AL, CL              ; shifts to align bit mask\r
+ 07FE  8A C8                       MOV     CL, AL              ; Shift Count for SHL\r
+                                \r
+                                   ;Get segment of character map\r
+                                \r
+                                   OUT_8   SC_Index, MAP_MASK  ; Setup Plane selections\r
+ 0800  BA 03C4              1          MOV     DX, SC_Index        ; then Select Register\r
+ 0803  B0 02                1          MOV     AL, MAP_MASK           ; then Get Data Value\r
+ 0805  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+ 0806  42                          INC     DX                  ; DX -> SC_Data\r
+                                \r
+ 0807  B0 08                       MOV     AL, 08              ; 8 Lines to Process\r
+ 0809  88 46 02                            MOV     [BP].GPC_Lines, AL  ; Save on Stack\r
+                                \r
+ 080C  8E 5E 04                            MOV     DS, [BP].GPC_T_SETS ; Point to character set\r
+                                \r
+ 080F                          @GPC_DECODE_CHAR_BYTE:\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/02/14 15:18:33\r
+modex.asm                                                   Page 10 - 1\r
+\r
+\r
+                                \r
+ 080F  8B 76 06                            MOV     SI, [BP].GPC_T_SETO ; Get DS:SI = String\r
+                                \r
+ 0812  8A 3C                       MOV     BH, [SI]            ; Get Bit Map\r
+ 0814  46                          INC     SI                  ; Point to Next Line\r
+ 0815  89 76 06                            MOV     [BP].GPC_T_SETO, SI ; And save new Pointer...\r
+                                \r
+                                   CLR     AX                  ; Clear AX\r
+ 0818  33 C0                1          XOR     AX, AX      ; Set Register = 0\r
+                                \r
+                                   CLR     BL                      ; Clear BL\r
+ 081A  32 DB                1          XOR     BL, BL      ; Set Register = 0\r
+ 081C  D3 C3                       ROL     BX, CL                  ; BL holds left edge bits\r
+ 081E  8B F3                       MOV     SI, BX                  ; Use as Table Index\r
+ 0820  83 E6 0F                            AND     SI, CHAR_BITS           ; Get Low Bits\r
+ 0823  2E: 8A 84 0008 R                    MOV     AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ 0828  74 07                       JZ      @GPC_NO_LEFT1BITS       ; Skip if No Pixels to set\r
+                                \r
+ 082A  8A 66 16                            MOV     AH, [BP].GPC_ColorF ; Get Foreground Color\r
+ 082D  EE                          OUT     DX, AL              ; Set up Screen Mask\r
+ 082E  26: 88 25                   MOV     ES:[DI], AH         ; Write Foreground color\r
+                                \r
+ 0831                          @GPC_NO_LEFT1BITS:\r
+ 0831  32 C5                       XOR     AL, CH              ; Invert mask for Background\r
+ 0833  74 07                       JZ      @GPC_NO_LEFT0BITS   ; Hey, no need for this\r
+                                \r
+ 0835  8A 66 14                            MOV     AH, [BP].GPC_ColorB ; Get background Color\r
+ 0838  EE                          OUT     DX, AL              ; Set up Screen Mask\r
+ 0839  26: 88 25                   MOV     ES:[DI], AH         ; Write Foreground color\r
+                                \r
+                                   ;Now Do Middle/Last Band\r
+                                \r
+ 083C                          @GPC_NO_LEFT0BITS:\r
+ 083C  47                          INC     DI                  ; Point to next Byte\r
+ 083D  C1 C3 04                            ROL     BX, 4               ; Shift 4 bits\r
+                                \r
+ 0840  8B F3                       MOV     SI, BX                  ; Make Lookup Pointer\r
+ 0842  83 E6 0F                            AND     SI, CHAR_BITS           ; Get Low Bits\r
+ 0845  2E: 8A 84 0008 R                    MOV     AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ 084A  74 07                       JZ      @GPC_NO_MIDDLE1BITS     ; Skip if no pixels to set\r
+                                \r
+ 084C  8A 66 16                            MOV     AH, [BP].GPC_ColorF ; Get Foreground Color\r
+ 084F  EE                          OUT     DX, AL              ; Set up Screen Mask\r
+ 0850  26: 88 25                   MOV     ES:[DI], AH         ; Write Foreground color\r
+                                \r
+ 0853                          @GPC_NO_MIDDLE1BITS:\r
+ 0853  34 0F                       XOR     AL, ALL_PLANES      ; Invert mask for Background\r
+ 0855  74 07                       JZ      @GPC_NO_MIDDLE0BITS ; Hey, no need for this\r
+                                \r
+ 0857  8A 66 14                            MOV     AH, [BP].GPC_ColorB ; Get background Color\r
+ 085A  EE                          OUT     DX, AL              ; Set up Screen Mask\r
+ 085B  26: 88 25                   MOV     ES:[DI], AH         ; Write Foreground color\r
+                                \r
+ 085E                          @GPC_NO_MIDDLE0BITS:\r
+ 085E  80 F5 0F                            XOR     CH, ALL_PLANES      ; Invert Clip Mask\r
+ 0861  80 F9 04                            CMP     CL, 4               ; Aligned by 4?\r
+ 0864  74 23                       JZ      @GPC_NEXT_LINE      ; If so, Exit now..\r
+                                \r
+ 0866  47                          INC     DI                  ; Point to next Byte\r
+ 0867  C1 C3 04                            ROL     BX, 4               ; Shift 4 bits\r
+                                \r
+ 086A  8B F3                       MOV     SI, BX                  ; Make Lookup Pointer\r
+ 086C  83 E6 0F                            AND     SI, CHAR_BITS           ; Get Low Bits\r
+ 086F  2E: 8A 84 0008 R                    MOV     AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ 0874  74 07                       JZ      @GPC_NO_RIGHT1BITS      ; Skip if No Pixels to set\r
+                                \r
+ 0876  8A 66 16                            MOV     AH, [BP].GPC_ColorF ; Get Foreground Color\r
+ 0879  EE                          OUT     DX, AL              ; Set up Screen Mask\r
+ 087A  26: 88 25                   MOV     ES:[DI], AH         ; Write Foreground color\r
+                                \r
+ 087D                          @GPC_NO_RIGHT1BITS:\r
+                                \r
+ 087D  32 C5                       XOR     AL, CH              ; Invert mask for Background\r
+ 087F  74 07                       JZ      @GPC_NO_RIGHT0BITS  ; Hey, no need for this\r
+                                \r
+ 0881  8A 66 14                            MOV     AH, [BP].GPC_ColorB ; Get background Color\r
+ 0884  EE                          OUT     DX, AL              ; Set up Screen Mask\r
+ 0885  26: 88 25                   MOV     ES:[DI], AH         ; Write Foreground color\r
+                                \r
+ 0888                          @GPC_NO_RIGHT0BITS:\r
+ 0888  4F                          DEC     DI                  ; Adjust for Next Line Advance\r
+                                \r
+ 0889                          @GPC_NEXT_LINE:\r
+ 0889  03 7E 00                            ADD     DI, [BP].GPC_Width  ; Point to Next Line\r
+ 088C  80 F5 0F                            XOR     CH, CHAR_BITS       ; Flip the Clip mask back\r
+                                \r
+ 088F  FE 4E 02                            DEC     [BP].GPC_Lines      ; Count Down Lines\r
+ 0892  74 03                       JZ      @GPC_EXIT           ; Ok... Done!\r
+                                \r
+ 0894  E9 FF78                     JMP     @GPC_DECODE_CHAR_BYTE   ; Again! Hey!\r
+                                \r
+ 0897                          @GPC_EXIT:\r
+ 0897  83 C4 08                            ADD     SP, 08              ; Deallocate stack workspace\r
+                                   POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+ 089A  5F                   1          POP     DI              ; Restore R1\r
+ 089B  5E                   2          POP     SI              ; Restore R1\r
+ 089C  1F                   3          POP     DS              ; Restore R1\r
+ 089D  5D                   4          POP     BP              ; Restore R1\r
+ 089E  CA 000A                     RET     10                  ; Exit and Clean up Stack\r
+                                \r
+ 08A1                          GPRINTC  ENDP\r
+                                \r
+                                \r
+                               ;==========================================\r
+                               ;TGPRINTC (CharNum%, Xpos%, Ypos%, ColorF%)\r
+                               ;==========================================\r
+                               ;\r
+                               ; Transparently draws an ASCII Text Character using the\r
+                               ; currently selected 8x8 font on the active display page.\r
+                               ;\r
+                               ; ENTRY: CharNum = ASCII character # to draw\r
+                               ;        Xpos    = X position to draw Character at\r
+                               ;        Ypos    = Y position of to draw Character at\r
+                               ;        ColorF  = Color to draw text character in\r
+                               ;\r
+                               ; EXIT:  No meaningful values returned\r
+                               ;\r
+                                \r
+ 001C                          TGP_STACK   STRUC\r
+ 0000  0000                        TGP_Width   DW  ?   ; Screen Width-1\r
+ 0002  00 00                       TGP_Lines   DB  ?,? ; Scan lines to Decode\r
+ 0004  0000                        TGP_T_SETS  DW  ?   ; Saved Charset Segment\r
+ 0006  0000                        TGP_T_SETO  DW  ?   ; Saved Charset Offset\r
+ 0008  0000 0000 0000                          DW  ?x4 ; DI, SI, DS, BP\r
+       0000\r
+ 0010  00000000                                        DD  ?   ; Caller\r
+ 0014  00 00                       TGP_ColorF  DB  ?,? ; Text Color\r
+ 0016  0000                        TGP_Ypos    DW  ?   ; Y Position to Print at\r
+ 0018  0000                        TGP_Xpos    DW  ?   ; X position to Print at\r
+ 001A  00 00                       TGP_Char    DB  ?,? ; Character to Print\r
+                               TGP_STACK   ENDS\r
+                                \r
+                                       PUBLIC TGPRINTC\r
+                                \r
+ 08A1                          TGPRINTC    PROC    FAR\r
+                                \r
+                                   PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+ 08A1  55                   1          PUSH    BP              ; Save R1\r
+ 08A2  1E                   2          PUSH    DS              ; Save R1\r
+ 08A3  56                   3          PUSH    SI              ; Save R1\r
+ 08A4  57                   4          PUSH    DI              ; Save R1\r
+ 08A5  83 EC 08                            SUB     SP, 8               ; Allocate WorkSpace on Stack\r
+ 08A8  8B EC                       MOV     BP, SP              ; Set up Stack Frame\r
+                                \r
+ 08AA  C4 3E 0014 R                LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+                                \r
+ 08AE  A1 0000 R                   MOV     AX, SCREEN_WIDTH    ; Get Logical Line Width\r
+ 08B1  8B D8                       MOV     BX, AX              ; BX = Screen Width\r
+ 08B3  4B                          DEC     BX                  ;    = Screen Width-1\r
+ 08B4  89 5E 00                            MOV     [BP].TGP_Width, BX  ; Save for later use\r
+                                \r
+ 08B7  F7 66 16                            MUL     [BP].TGP_Ypos       ; Start of Line = Ypos * Width\r
+ 08BA  03 F8                       ADD     DI, AX              ; DI -> Start of Line Ypos\r
+                                \r
+ 08BC  8B 46 18                            MOV     AX, [BP].TGP_Xpos   ; Get Xpos of Character\r
+ 08BF  8B C8                       MOV     CX, AX              ; Save Copy of Xpos\r
+ 08C1  C1 E8 02                            SHR     AX, 2               ; Bytes into Line = Xpos/4\r
+ 08C4  03 F8                       ADD     DI, AX              ; DI -> (Xpos, Ypos)\r
+                                \r
+                                   ;Get Source ADDR of Character Bit Map  & Save\r
+                                \r
+ 08C6  8A 46 1A                            MOV     AL, [BP].TGP_Char   ; Get Character #\r
+ 08C9  A8 80                       TEST    AL, 080h            ; Is Hi Bit Set?\r
+ 08CB  74 0C                       JZ      @TGP_LowChar        ; Nope, use low char set ptr\r
+                                \r
+ 08CD  24 7F                       AND     AL, 07Fh            ; Mask Out Hi Bit\r
+ 08CF  8B 1E 0026 R                MOV     BX, CHARSET_HI      ; BX = Char Set Ptr:Offset\r
+ 08D3  8B 16 0028 R                MOV     DX, CHARSET_HI+2    ; DX = Char Set Ptr:Segment\r
+ 08D7  EB 08                       JMP     s @TGP_Set_Char     ; Go Setup Character Ptr\r
+                                \r
+ 08D9                          @TGP_LowChar:\r
+                                \r
+ 08D9  8B 1E 0022 R                MOV     BX, CHARSET_LOW     ; BX = Char Set Ptr:Offset\r
+ 08DD  8B 16 0024 R                MOV     DX, CHARSET_LOW+2   ; DX = Char Set Ptr:Segment\r
+                                \r
+ 08E1                          @TGP_Set_Char:\r
+ 08E1  89 56 04                            MOV     [BP].TGP_T_SETS, DX ; Save Segment on Stack\r
+                                \r
+ 08E4  B4 00                       MOV     AH, 0               ; Valid #'s are 0..127\r
+ 08E6  C1 E0 03                            SHL     AX, 3               ; * 8 Bytes Per Bitmap\r
+ 08E9  03 D8                       ADD     BX, AX              ; BX = Offset of Selected char\r
+ 08EB  89 5E 06                            MOV     [BP].TGP_T_SETO, BX ; Save Offset on Stack\r
+                                \r
+ 08EE  83 E1 03                            AND     CX, PLANE_BITS      ; Get Plane #\r
+ 08F1  B5 0F                       MOV     CH, ALL_PLANES      ; Get Initial Plane mask\r
+ 08F3  D2 E5                       SHL     CH, CL              ; And shift into position\r
+ 08F5  80 E5 0F                            AND     CH, ALL_PLANES      ; And mask to lower nibble\r
+                                \r
+ 08F8  B0 04                       MOV     AL, 04              ; 4-Plane # = # of initial\r
+ 08FA  2A C1                       SUB     AL, CL              ; shifts to align bit mask\r
+ 08FC  8A C8                       MOV     CL, AL              ; Shift Count for SHL\r
+                                \r
+                                   ;Get segment of character map\r
+                                \r
+                                   OUT_8   SC_Index, MAP_MASK  ; Setup Plane selections\r
+ 08FE  BA 03C4              1          MOV     DX, SC_Index        ; then Select Register\r
+ 0901  B0 02                1          MOV     AL, MAP_MASK           ; then Get Data Value\r
+ 0903  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+ 0904  42                          INC     DX                  ; DX -> SC_Data\r
+                                \r
+ 0905  B0 08                       MOV     AL, 08              ; 8 Lines to Process\r
+ 0907  88 46 02                            MOV     [BP].TGP_Lines, AL  ; Save on Stack\r
+                                \r
+ 090A  8E 5E 04                            MOV     DS, [BP].TGP_T_SETS ; Point to character set\r
+                                \r
+ 090D                          @TGP_DECODE_CHAR_BYTE:\r
+                                \r
+ 090D  8B 76 06                            MOV     SI, [BP].TGP_T_SETO ; Get DS:SI = String\r
+                                \r
+ 0910  8A 3C                       MOV     BH, [SI]            ; Get Bit Map\r
+ 0912  46                          INC     SI                  ; Point to Next Line\r
+ 0913  89 76 06                            MOV     [BP].TGP_T_SETO, SI ; And save new Pointer...\r
+                                \r
+ 0916  8A 66 14                            MOV     AH, [BP].TGP_ColorF ; Get Foreground Color\r
+                                \r
+                                   CLR     BL                      ; Clear BL\r
+ 0919  32 DB                1          XOR     BL, BL      ; Set Register = 0\r
+ 091B  D3 C3                       ROL     BX, CL                  ; BL holds left edge bits\r
+ 091D  8B F3                       MOV     SI, BX                  ; Use as Table Index\r
+ 091F  83 E6 0F                            AND     SI, CHAR_BITS           ; Get Low Bits\r
+ 0922  2E: 8A 84 0008 R                    MOV     AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ 0927  74 04                       JZ      @TGP_NO_LEFT1BITS       ; Skip if No Pixels to set\r
+                                \r
+ 0929  EE                          OUT     DX, AL              ; Set up Screen Mask\r
+ 092A  26: 88 25                   MOV     ES:[DI], AH         ; Write Foreground color\r
+                                \r
+                                   ;Now Do Middle/Last Band\r
+                                \r
+ 092D                          @TGP_NO_LEFT1BITS:\r
+                                \r
+ 092D  47                          INC     DI                  ; Point to next Byte\r
+ 092E  C1 C3 04                            ROL     BX, 4               ; Shift 4 bits\r
+                                \r
+ 0931  8B F3                       MOV     SI, BX                  ; Make Lookup Pointer\r
+ 0933  83 E6 0F                            AND     SI, CHAR_BITS           ; Get Low Bits\r
+ 0936  2E: 8A 84 0008 R                    MOV     AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ 093B  74 04                       JZ      @TGP_NO_MIDDLE1BITS     ; Skip if no pixels to set\r
+                                \r
+ 093D  EE                          OUT     DX, AL              ; Set up Screen Mask\r
+ 093E  26: 88 25                   MOV     ES:[DI], AH         ; Write Foreground color\r
+                                \r
+ 0941                          @TGP_NO_MIDDLE1BITS:\r
+ 0941  80 F5 0F                            XOR     CH, ALL_PLANES      ; Invert Clip Mask\r
+ 0944  80 F9 04                            CMP     CL, 4               ; Aligned by 4?\r
+ 0947  74 15                       JZ      @TGP_NEXT_LINE      ; If so, Exit now..\r
+                                \r
+ 0949  47                          INC     DI                  ; Point to next Byte\r
+ 094A  C1 C3 04                            ROL     BX, 4               ; Shift 4 bits\r
+                                \r
+ 094D  8B F3                       MOV     SI, BX                  ; Make Lookup Pointer\r
+ 094F  83 E6 0F                            AND     SI, CHAR_BITS           ; Get Low Bits\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/02/14 15:18:33\r
+modex.asm                                                   Page 11 - 1\r
+\r
+\r
+ 0952  2E: 8A 84 0008 R                    MOV     AL, Char_Plane_Data[SI] ; Get Mask in AL\r
+ 0957  74 04                       JZ      @TGP_NO_RIGHT1BITS      ; Skip if No Pixels to set\r
+                                \r
+ 0959  EE                          OUT     DX, AL              ; Set up Screen Mask\r
+ 095A  26: 88 25                   MOV     ES:[DI], AH         ; Write Foreground color\r
+                                \r
+ 095D                          @TGP_NO_RIGHT1BITS:\r
+                                \r
+ 095D  4F                          DEC     DI                  ; Adjust for Next Line Advance\r
+                                \r
+ 095E                          @TGP_NEXT_LINE:\r
+ 095E  03 7E 00                            ADD     DI, [BP].TGP_Width  ; Point to Next Line\r
+ 0961  80 F5 0F                            XOR     CH, CHAR_BITS       ; Flip the Clip mask back\r
+                                \r
+ 0964  FE 4E 02                            DEC     [BP].TGP_Lines      ; Count Down Lines\r
+ 0967  74 02                       JZ      @TGP_EXIT           ; Ok... Done!\r
+                                \r
+ 0969  EB A2                       JMP     @TGP_DECODE_CHAR_BYTE   ; Again! Hey!\r
+                                \r
+ 096B                          @TGP_EXIT:\r
+ 096B  83 C4 08                            ADD     SP, 08              ; Deallocate stack workspace\r
+                                   POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+ 096E  5F                   1          POP     DI              ; Restore R1\r
+ 096F  5E                   2          POP     SI              ; Restore R1\r
+ 0970  1F                   3          POP     DS              ; Restore R1\r
+ 0971  5D                   4          POP     BP              ; Restore R1\r
+ 0972  CA 0008                     RET     8                   ; Exit and Clean up Stack\r
+                                \r
+ 0975                          TGPRINTC    ENDP\r
+                                \r
+                                \r
+                               ;===============================================================\r
+                               ;PRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%)\r
+                               ;===============================================================\r
+                               ;\r
+                               ; Routine to quickly Print a null terminated ASCII string on the\r
+                               ; active display page up to a maximum length.\r
+                               ;\r
+                               ; ENTRY: String  = Far Pointer to ASCII string to print\r
+                               ;        MaxLen  = # of characters to print if no null found\r
+                               ;        Xpos    = X position to draw Text at\r
+                               ;        Ypos    = Y position of to draw Text at\r
+                               ;        ColorF  = Color to draw text in\r
+                               ;        ColorB  = Color to set background to\r
+                               ;\r
+                               ; EXIT:  No meaningful values returned\r
+                               ;\r
+                                \r
+ 001A                          PS_STACK    STRUC\r
+ 0000  0000 0000 0000                          DW  ?x4 ; DI, SI, DS, BP\r
+       0000\r
+ 0008  00000000                                        DD  ?   ; Caller\r
+ 000C  0000                        PS_ColorB   DW  ?   ; Background Color\r
+ 000E  0000                        PS_ColorF   DW  ?   ; Text Color\r
+ 0010  0000                        PS_Ypos     DW  ?   ; Y Position to Print at\r
+ 0012  0000                        PS_Xpos     DW  ?   ; X position to Print at\r
+ 0014  0000                        PS_Len      DW  ?   ; Maximum Length of string to print\r
+ 0016  0000 0000                   PS_Text     DW  ?,? ; Far Ptr to Text String\r
+                               PS_STACK    ENDS\r
+                                \r
+                                       PUBLIC  PRINT_STR\r
+                                \r
+ 0975                          PRINT_STR   PROC    FAR\r
+                                \r
+                                   PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+ 0975  55                   1          PUSH    BP              ; Save R1\r
+ 0976  1E                   2          PUSH    DS              ; Save R1\r
+ 0977  56                   3          PUSH    SI              ; Save R1\r
+ 0978  57                   4          PUSH    DI              ; Save R1\r
+ 0979  8B EC                       MOV     BP, SP              ; Set up Stack Frame\r
+                                \r
+ 097B                          @PS_Print_It:\r
+                                \r
+ 097B  8B 4E 14                            MOV     CX, [BP].PS_Len     ; Get Remaining text Length\r
+ 097E  E3 2F                       JCXZ    @PS_Exit            ; Exit when out of text\r
+                                \r
+ 0980  C4 7E 16                            LES     DI, d [BP].PS_Text  ; ES:DI -> Current Char in Text\r
+ 0983  26: 8A 05                   MOV     AL, ES:[DI]         ; AL = Text Character\r
+ 0986  25 00FF                     AND     AX, 00FFh           ; Clear High Word\r
+ 0989  74 24                       JZ      @PS_Exit            ; Exit if null character\r
+                                \r
+ 098B  FF 4E 14                            DEC     [BP].PS_Len         ; Remaining Text length--\r
+ 098E  FF 46 16                            INC     [BP].PS_Text        ; Point to Next text char\r
+                                \r
+                                   ; Set up Call to GPRINTC\r
+                                \r
+ 0991  50                          PUSH    AX                  ; Set Character Parameter\r
+ 0992  8B 5E 12                            MOV     BX, [BP].PS_Xpos    ; Get Xpos\r
+ 0995  53                          PUSH    BX                  ; Set Xpos Parameter\r
+ 0996  83 C3 08                            ADD     BX, 8               ; Advance 1 Char to Right\r
+ 0999  89 5E 12                            MOV     [BP].PS_Xpos, BX    ; Save for next time through\r
+                                \r
+ 099C  8B 5E 10                            MOV     BX, [BP].PS_Ypos    ; Get Ypos\r
+ 099F  53                          PUSH    BX                  ; Set Ypos Parameter\r
+                                \r
+ 09A0  8B 5E 0E                            MOV     BX, [BP].PS_ColorF  ; Get Text Color\r
+ 09A3  53                          PUSH    BX                  ; Set ColorF Parameter\r
+                                \r
+ 09A4  8B 5E 0C                            MOV     BX, [BP].PS_ColorB  ; Get Background Color\r
+ 09A7  53                          PUSH    BX                  ; Set ColorB Parameter\r
+                                \r
+ 09A8  9A ---- 07A3 R              CALL    f GPRINTC           ; Print Character!\r
+ 09AD  EB CC                       JMP     s @PS_Print_It      ; Process next character\r
+                                \r
+ 09AF                          @PS_Exit:\r
+                                   POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+ 09AF  5F                   1          POP     DI              ; Restore R1\r
+ 09B0  5E                   2          POP     SI              ; Restore R1\r
+ 09B1  1F                   3          POP     DS              ; Restore R1\r
+ 09B2  5D                   4          POP     BP              ; Restore R1\r
+ 09B3  CA 000E                     RET     14                  ; Exit and Clean up Stack\r
+                                \r
+ 09B6                          PRINT_STR  ENDP\r
+                                \r
+                                \r
+                               ;================================================================\r
+                               ;TPRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%)\r
+                               ;================================================================\r
+                               ;\r
+                               ; Routine to quickly transparently Print a null terminated ASCII\r
+                               ; string on the active display page up to a maximum length.\r
+                               ;\r
+                               ; ENTRY: String  = Far Pointer to ASCII string to print\r
+                               ;        MaxLen  = # of characters to print if no null found\r
+                               ;        Xpos    = X position to draw Text at\r
+                               ;        Ypos    = Y position of to draw Text at\r
+                               ;        ColorF  = Color to draw text in\r
+                               ;\r
+                               ; EXIT:  No meaningful values returned\r
+                               ;\r
+                                \r
+ 0018                          TPS_STACK   STRUC\r
+ 0000  0000 0000 0000                          DW  ?x4 ; DI, SI, DS, BP\r
+       0000\r
+ 0008  00000000                                        DD  ?   ; Caller\r
+ 000C  0000                        TPS_ColorF  DW  ?   ; Text Color\r
+ 000E  0000                        TPS_Ypos    DW  ?   ; Y Position to Print at\r
+ 0010  0000                        TPS_Xpos    DW  ?   ; X position to Print at\r
+ 0012  0000                        TPS_Len     DW  ?   ; Maximum Length of string to print\r
+ 0014  0000 0000                   TPS_Text    DW  ?,? ; Far Ptr to Text String\r
+                               TPS_STACK   ENDS\r
+                                \r
+                                       PUBLIC  TPRINT_STR\r
+                                \r
+ 09B6                          TPRINT_STR  PROC    FAR\r
+                                \r
+                                   PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+ 09B6  55                   1          PUSH    BP              ; Save R1\r
+ 09B7  1E                   2          PUSH    DS              ; Save R1\r
+ 09B8  56                   3          PUSH    SI              ; Save R1\r
+ 09B9  57                   4          PUSH    DI              ; Save R1\r
+ 09BA  8B EC                       MOV     BP, SP              ; Set up Stack Frame\r
+                                \r
+ 09BC                          @TPS_Print_It:\r
+                                \r
+ 09BC  8B 4E 12                            MOV     CX, [BP].TPS_Len    ; Get Remaining text Length\r
+ 09BF  E3 2B                       JCXZ    @TPS_Exit           ; Exit when out of text\r
+                                \r
+ 09C1  C4 7E 14                            LES     DI, d [BP].TPS_Text ; ES:DI -> Current Char in Text\r
+ 09C4  26: 8A 05                   MOV     AL, ES:[DI]         ; AL = Text Character\r
+ 09C7  25 00FF                     AND     AX, 00FFh           ; Clear High Word\r
+ 09CA  74 20                       JZ      @TPS_Exit           ; Exit if null character\r
+                                \r
+ 09CC  FF 4E 12                            DEC     [BP].TPS_Len        ; Remaining Text length--\r
+ 09CF  FF 46 14                            INC     [BP].TPS_Text       ; Point to Next text char\r
+                                \r
+                                   ; Set up Call to TGPRINTC\r
+                                \r
+ 09D2  50                          PUSH    AX                  ; Set Character Parameter\r
+ 09D3  8B 5E 10                            MOV     BX, [BP].TPS_Xpos   ; Get Xpos\r
+ 09D6  53                          PUSH    BX                  ; Set Xpos Parameter\r
+ 09D7  83 C3 08                            ADD     BX, 8               ; Advance 1 Char to Right\r
+ 09DA  89 5E 10                            MOV     [BP].TPS_Xpos, BX   ; Save for next time through\r
+                                \r
+ 09DD  8B 5E 0E                            MOV     BX, [BP].TPS_Ypos   ; Get Ypos\r
+ 09E0  53                          PUSH    BX                  ; Set Ypos Parameter\r
+                                \r
+ 09E1  8B 5E 0C                            MOV     BX, [BP].TPS_ColorF ; Get Text Color\r
+ 09E4  53                          PUSH    BX                  ; Set ColorF Parameter\r
+                                \r
+ 09E5  9A ---- 08A1 R              CALL    f TGPRINTC          ; Print Character!\r
+ 09EA  EB D0                       JMP     s @TPS_Print_It     ; Process next character\r
+                                \r
+ 09EC                          @TPS_Exit:\r
+                                   POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+ 09EC  5F                   1          POP     DI              ; Restore R1\r
+ 09ED  5E                   2          POP     SI              ; Restore R1\r
+ 09EE  1F                   3          POP     DS              ; Restore R1\r
+ 09EF  5D                   4          POP     BP              ; Restore R1\r
+ 09F0  CA 000C                     RET     12                  ; Exit and Clean up Stack\r
+                                \r
+ 09F3                          TPRINT_STR  ENDP\r
+                                \r
+                                \r
+                               ;===========================================\r
+                               ;SET_DISPLAY_FONT(SEG FontData, FontNumber%)\r
+                               ;===========================================\r
+                               ;\r
+                               ; Allows the user to specify their own font data for\r
+                               ; wither the lower or upper 128 characters.\r
+                               ;\r
+                               ; ENTRY: FontData   = Far Pointer to Font Bitmaps\r
+                               ;        FontNumber = Which half of set this is\r
+                               ;                   = 0, Lower 128 characters\r
+                               ;                   = 1, Upper 128 characters\r
+                               ;\r
+                               ; EXIT:  No meaningful values returned\r
+                               ;\r
+                                \r
+ 000C                          SDF_STACK   STRUC\r
+ 0000  0000                                    DW  ?   ; BP\r
+ 0002  00000000                                        DD  ?   ; Caller\r
+ 0006  0000                        SDF_Which   DW  ?   ; Hi Table/Low Table Flag\r
+ 0008  00000000                            SDF_Font    DD  ?   ; Far Ptr to Font Table\r
+                               SDF_STACK   ENDS\r
+                                \r
+                                   PUBLIC  SET_DISPLAY_FONT\r
+                                \r
+ 09F3                          SET_DISPLAY_FONT    PROC    FAR\r
+                                \r
+ 09F3  55                          PUSH    BP                  ; Preserve Registers\r
+ 09F4  8B EC                       MOV     BP, SP              ; Set up Stack Frame\r
+                                \r
+ 09F6  C4 7E 08                            LES     DI, [BP].SDF_Font   ; Get Far Ptr to Font\r
+                                \r
+ 09F9  BE 0022 R                   MOV     SI, o CHARSET_LOW   ; Assume Lower 128 chars\r
+ 09FC  F7 46 06 0001               TEST    [BP].SDF_Which, 1   ; Font #1 selected?\r
+ 0A01  74 03                       JZ      @SDF_Set_Font       ; If not, skip ahead\r
+                                \r
+ 0A03  BE 0026 R                   MOV     SI, o CHARSET_HI    ; Ah, really it's 128-255\r
+                                \r
+ 0A06                          @SDF_Set_Font:\r
+ 0A06  89 3C                       MOV     [SI], DI            ; Set Font Pointer Offset\r
+ 0A08  8C 44 02                            MOV     [SI+2], ES          ; Set Font Pointer Segment\r
+                                \r
+ 0A0B  5D                          POP     BP                  ; Restore Registers\r
+ 0A0C  CA 0006                     RET     6                   ; We are Done.. Outa here\r
+                                \r
+ 0A0F                          SET_DISPLAY_FONT    ENDP\r
+                                \r
+                                \r
+                                   ; ===== BITMAP (SPRITE) DISPLAY ROUTINES =====\r
+                                \r
+                               ;======================================================\r
+                               ;DRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%)\r
+                               ;======================================================\r
+                               ;\r
+                               ; Draws a variable sized Graphics Bitmap such as a\r
+                               ; picture or an Icon on the current Display Page in\r
+                               ; Mode X.  The Bitmap is stored in a linear byte array\r
+                               ; corresponding to (0,0) (1,0), (2,0) .. (Width, Height)\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/02/14 15:18:33\r
+modex.asm                                                   Page 12 - 1\r
+\r
+\r
+                               ; This is the same linear manner as mode 13h graphics.\r
+                               ;\r
+                               ; ENTRY: Image  = Far Pointer to Bitmap Data\r
+                               ;        Xpos   = X position to Place Upper Left pixel at\r
+                               ;        Ypos   = Y position to Place Upper Left pixel at\r
+                               ;        Width  = Width of the Bitmap in Pixels\r
+                               ;        Height = Height of the Bitmap in Pixels\r
+                               ;\r
+                               ; EXIT:  No meaningful values returned\r
+                               ;\r
+                                \r
+ 0022                          DB_STACK    STRUC\r
+ 0000  0000                        DB_LineO    DW  ?   ; Offset to Next Line\r
+ 0002  0000                        DB_PixCount DW  ?   ; (Minimum) # of Pixels/Line\r
+ 0004  0000                        DB_Start    DW  ?   ; Addr of Upper Left Pixel\r
+ 0006  0000                        DB_PixSkew  DW  ?   ; # of bytes to Adjust EOL\r
+ 0008  0000                        DB_SkewFlag DW  ?   ; Extra Pix on Plane Flag\r
+ 000A  0000 0000 0000                          DW  ?x4 ; DI, SI, DS, BP\r
+       0000\r
+ 0012  00000000                                        DD  ?   ; Caller\r
+ 0016  0000                        DB_Height   DW  ?   ; Height of Bitmap in Pixels\r
+ 0018  0000                        DB_Width    DW  ?   ; Width of Bitmap in Pixels\r
+ 001A  0000                        DB_Ypos     DW  ?   ; Y position to Draw Bitmap at\r
+ 001C  0000                        DB_Xpos     DW  ?   ; X position to Draw Bitmap at\r
+ 001E  00000000                            DB_Image    DD  ?   ; Far Pointer to Graphics Bitmap\r
+                               DB_STACK    ENDS\r
+                                \r
+                                       PUBLIC    DRAW_BITMAP\r
+                                \r
+ 0A0F                          DRAW_BITMAP PROC    FAR\r
+                                \r
+                                   PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+ 0A0F  55                   1          PUSH    BP              ; Save R1\r
+ 0A10  1E                   2          PUSH    DS              ; Save R1\r
+ 0A11  56                   3          PUSH    SI              ; Save R1\r
+ 0A12  57                   4          PUSH    DI              ; Save R1\r
+ 0A13  83 EC 0A                            SUB     SP, 10              ; Allocate workspace\r
+ 0A16  8B EC                       MOV     BP, SP              ; Set up Stack Frame\r
+                                \r
+ 0A18  C4 3E 0014 R                LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+ 0A1C  FC                          CLD                         ; Direction Flag = Forward\r
+                                \r
+ 0A1D  8B 46 1A                            MOV     AX, [BP].DB_Ypos    ; Get UL Corner Ypos\r
+ 0A20  F7 26 0000 R                MUL     SCREEN_WIDTH        ; AX = Offset to Line Ypos\r
+                                \r
+ 0A24  8B 5E 1C                            MOV     BX, [BP].DB_Xpos    ; Get UL Corner Xpos\r
+ 0A27  8A CB                       MOV     CL, BL              ; Save Plane # in CL\r
+ 0A29  C1 EB 02                            SHR     BX, 2               ; Xpos/4 = Offset Into Line\r
+                                \r
+ 0A2C  03 F8                       ADD     DI, AX              ; ES:DI -> Start of Line\r
+ 0A2E  03 FB                       ADD     DI, BX              ; ES:DI -> Upper Left Pixel\r
+ 0A30  89 7E 04                            MOV     [BP].DB_Start, DI   ; Save Starting Addr\r
+                                \r
+                                   ; Compute line to line offset\r
+                                \r
+ 0A33  8B 5E 18                            MOV     BX, [BP].DB_Width   ; Get Width of Image\r
+ 0A36  8B D3                       MOV     DX, BX              ; Save Copy in DX\r
+ 0A38  C1 EB 02                            SHR     BX, 2               ; /4 = width in bands\r
+ 0A3B  A1 0000 R                   MOV     AX, SCREEN_WIDTH    ; Get Screen Width\r
+ 0A3E  2B C3                       SUB     AX, BX              ; - (Bitmap Width/4)\r
+                                \r
+ 0A40  89 46 00                            MOV     [BP].DB_LineO, AX       ; Save Line Width offset\r
+ 0A43  89 5E 02                            MOV     [BP].DB_PixCount, BX    ; Minimum # pix to copy\r
+                                \r
+ 0A46  83 E2 03                            AND     DX, PLANE_BITS          ; Get "partial band" size (0-3)\r
+ 0A49  89 56 06                            MOV     [BP].DB_PixSkew, DX     ; Also End of Line Skew\r
+ 0A4C  89 56 08                            MOV     [BP].DB_SkewFlag, DX    ; Save as Flag/Count\r
+                                \r
+ 0A4F  83 E1 03                            AND     CX, PLANE_BITS      ; CL = Starting Plane #\r
+ 0A52  B8 1102                     MOV     AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select\r
+ 0A55  D2 E4                       SHL     AH, CL              ; Select correct Plane\r
+                                   OUT_16  SC_Index, AX        ; Select Plane...\r
+ 0A57  BA 03C4              1          MOV     DX, SC_Index        ; then Select Register\r
+ 0A5A  EF                   1          OUT     DX, AX              ; Set I/O Register(s)\r
+ 0A5B  8A FC                       MOV     BH, AH              ; BH = Saved Plane Mask\r
+ 0A5D  B3 04                       MOV     BL, 4               ; BL = Planes to Copy\r
+                                \r
+ 0A5F                          @DB_COPY_PLANE:\r
+                                \r
+ 0A5F  C5 76 1E                            LDS     SI, [BP].DB_Image   ; DS:SI-> Source Image\r
+ 0A62  8B 56 16                            MOV     DX, [BP].DB_Height  ; # of Lines to Copy\r
+ 0A65  8B 7E 04                            MOV     DI, [BP].DB_Start   ; ES:DI-> Dest pos\r
+                                \r
+ 0A68                          @DB_COPY_LINE:\r
+ 0A68  8B 4E 02                            MOV     CX, [BP].DB_PixCount    ; Min # to copy\r
+                                \r
+ 0A6B  F6 C1 FC                            TEST    CL, 0FCh            ; 16+PixWide?\r
+ 0A6E  74 18                       JZ      @DB_COPY_REMAINDER  ; Nope...\r
+                                \r
+                                   ; Pixel Copy loop has been unrolled to x4\r
+                                \r
+ 0A70                          @DB_COPY_LOOP:\r
+ 0A70  A4                          MOVSB                       ; Copy Bitmap Pixel\r
+ 0A71  83 C6 03                            ADD     SI, 3               ; Skip to Next Byte in same plane\r
+ 0A74  A4                          MOVSB                       ; Copy Bitmap Pixel\r
+ 0A75  83 C6 03                            ADD     SI, 3               ; Skip to Next Byte in same plane\r
+ 0A78  A4                          MOVSB                       ; Copy Bitmap Pixel\r
+ 0A79  83 C6 03                            ADD     SI, 3               ; Skip to Next Byte in same plane\r
+ 0A7C  A4                          MOVSB                       ; Copy Bitmap Pixel\r
+ 0A7D  83 C6 03                            ADD     SI, 3               ; Skip to Next Byte in same plane\r
+                                \r
+ 0A80  80 E9 04                            SUB     CL, 4               ; Pixels to Copy=-4\r
+ 0A83  F6 C1 FC                            TEST    CL, 0FCh            ; 4+ Pixels Left?\r
+ 0A86  75 E8                       JNZ     @DB_COPY_LOOP       ; if so, do another block\r
+                                \r
+ 0A88                          @DB_COPY_REMAINDER:\r
+ 0A88  E3 07                       JCXZ    @DB_NEXT_LINE       ; Any Pixels left on line\r
+                                \r
+ 0A8A                          @DB_COPY2:\r
+ 0A8A  A4                          MOVSB                       ; Copy Bitmap Pixel\r
+ 0A8B  83 C6 03                            ADD     SI,3                ; Skip to Next Byte in same plane\r
+                                   LOOPx   CX, @DB_COPY2       ; Pixels to Copy--, Loop until done\r
+ 0A8E  49                   1      DEC     CX                ; Counter--\r
+ 0A8F  75 F9                1      JNZ     @DB_COPY2             ; Jump if not 0\r
+                                \r
+ 0A91                          @DB_NEXT_LINE:\r
+                                \r
+                                   ; any Partial Pixels? (some planes only)\r
+                                \r
+ 0A91  0B 4E 08                            OR      CX, [BP].DB_SkewFlag    ; Get Skew Count\r
+ 0A94  74 03                       JZ      @DB_NEXT2               ; if no partial pixels\r
+                                \r
+ 0A96  A4                          MOVSB                       ; Copy Bitmap Pixel\r
+ 0A97  4F                          DEC     DI                  ; Back up to align\r
+ 0A98  4E                          DEC     SI                  ; Back up to align\r
+                                \r
+ 0A99                          @DB_NEXT2:\r
+ 0A99  03 76 06                            ADD     SI, [BP].DB_PixSkew ; Adjust Skew\r
+ 0A9C  03 7E 00                            ADD     DI, [BP].DB_LineO   ; Set to Next Display Line\r
+                                   LOOPx   DX, @DB_COPY_LINE   ; Lines to Copy--, Loop if more\r
+ 0A9F  4A                   1      DEC     DX                ; Counter--\r
+ 0AA0  75 C6                1      JNZ     @DB_COPY_LINE             ; Jump if not 0\r
+                                \r
+                                   ; Copy Next Plane....\r
+                                \r
+ 0AA2  FE CB                       DEC     BL                  ; Planes to Go--\r
+ 0AA4  74 1B                       JZ      @DB_Exit            ; Hey! We are done\r
+                                \r
+ 0AA6  D0 C7                       ROL     BH, 1               ; Next Plane in line...\r
+                                   OUT_8   SC_Data, BH         ; Select Plane\r
+ 0AA8  BA 03C5              1          MOV     DX, SC_Data        ; then Select Register\r
+ 0AAB  8A C7                1          MOV     AL, BH           ; then Get Data Value\r
+ 0AAD  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+                                \r
+ 0AAE  3C 12                       CMP     AL, 12h             ; Carry Set if AL=11h\r
+ 0AB0  83 56 04 00                 ADC     [BP].DB_Start, 0    ; Screen Addr =+Carry\r
+ 0AB4  FF 46 1E                            INC     w [BP].DB_Image     ; Start @ Next Byte\r
+                                \r
+ 0AB7  83 6E 08 01                 SUB     [BP].DB_SkewFlag, 1 ; Reduce Planes to Skew\r
+ 0ABB  83 56 08 00                 ADC     [BP].DB_SkewFlag, 0 ; Back to 0 if it was -1\r
+                                \r
+ 0ABF  EB 9E                       JMP     s @DB_COPY_PLANE    ; Go Copy the Next Plane\r
+                                \r
+ 0AC1                          @DB_Exit:\r
+ 0AC1  83 C4 0A                            ADD     SP, 10              ; Deallocate workspace\r
+                                   POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+ 0AC4  5F                   1          POP     DI              ; Restore R1\r
+ 0AC5  5E                   2          POP     SI              ; Restore R1\r
+ 0AC6  1F                   3          POP     DS              ; Restore R1\r
+ 0AC7  5D                   4          POP     BP              ; Restore R1\r
+ 0AC8  CA 000C                     RET     12                  ; Exit and Clean up Stack\r
+                                \r
+ 0ACB                          DRAW_BITMAP   ENDP\r
+                                \r
+                                \r
+                               ;=======================================================\r
+                               ;TDRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%)\r
+                               ;=======================================================\r
+                               ;\r
+                               ; Transparently Draws a variable sized Graphics Bitmap\r
+                               ; such as a picture or an Icon on the current Display Page\r
+                               ; in Mode X.  Pixels with a value of 0 are not drawn,\r
+                               ; leaving the previous "background" contents intact.\r
+                               ;\r
+                               ; The Bitmap format is the same as for the DRAW_BITMAP function.\r
+                               ;\r
+                               ; ENTRY: Image  = Far Pointer to Bitmap Data\r
+                               ;        Xpos   = X position to Place Upper Left pixel at\r
+                               ;        Ypos   = Y position to Place Upper Left pixel at\r
+                               ;        Width  = Width of the Bitmap in Pixels\r
+                               ;        Height = Height of the Bitmap in Pixels\r
+                               ;\r
+                               ; EXIT:  No meaningful values returned\r
+                               ;\r
+                                \r
+ 0022                          TB_STACK    STRUC\r
+ 0000  0000                        TB_LineO    DW  ?   ; Offset to Next Line\r
+ 0002  0000                        TB_PixCount DW  ?   ; (Minimum) # of Pixels/Line\r
+ 0004  0000                        TB_Start    DW  ?   ; Addr of Upper Left Pixel\r
+ 0006  0000                        TB_PixSkew  DW  ?   ; # of bytes to Adjust EOL\r
+ 0008  0000                        TB_SkewFlag DW  ?   ; Extra Pix on Plane Flag\r
+ 000A  0000 0000 0000                          DW  ?x4 ; DI, SI, DS, BP\r
+       0000\r
+ 0012  00000000                                        DD  ?   ; Caller\r
+ 0016  0000                        TB_Height   DW  ?   ; Height of Bitmap in Pixels\r
+ 0018  0000                        TB_Width    DW  ?   ; Width of Bitmap in Pixels\r
+ 001A  0000                        TB_Ypos     DW  ?   ; Y position to Draw Bitmap at\r
+ 001C  0000                        TB_Xpos     DW  ?   ; X position to Draw Bitmap at\r
+ 001E  00000000                            TB_Image    DD  ?   ; Far Pointer to Graphics Bitmap\r
+                               TB_STACK    ENDS\r
+                                \r
+                                       PUBLIC    TDRAW_BITMAP\r
+                                \r
+ 0ACB                          TDRAW_BITMAP    PROC    FAR\r
+                                \r
+                                   PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+ 0ACB  55                   1          PUSH    BP              ; Save R1\r
+ 0ACC  1E                   2          PUSH    DS              ; Save R1\r
+ 0ACD  56                   3          PUSH    SI              ; Save R1\r
+ 0ACE  57                   4          PUSH    DI              ; Save R1\r
+ 0ACF  83 EC 0A                            SUB     SP, 10              ; Allocate workspace\r
+ 0AD2  8B EC                       MOV     BP, SP              ; Set up Stack Frame\r
+                                \r
+ 0AD4  C4 3E 0014 R                LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
+ 0AD8  FC                          CLD                         ; Direction Flag = Forward\r
+                                \r
+ 0AD9  8B 46 1A                            MOV     AX, [BP].TB_Ypos    ; Get UL Corner Ypos\r
+ 0ADC  F7 26 0000 R                MUL     SCREEN_WIDTH        ; AX = Offset to Line Ypos\r
+                                \r
+ 0AE0  8B 5E 1C                            MOV     BX, [BP].TB_Xpos    ; Get UL Corner Xpos\r
+ 0AE3  8A CB                       MOV     CL, BL              ; Save Plane # in CL\r
+ 0AE5  C1 EB 02                            SHR     BX, 2               ; Xpos/4 = Offset Into Line\r
+                                \r
+ 0AE8  03 F8                       ADD     DI, AX              ; ES:DI -> Start of Line\r
+ 0AEA  03 FB                       ADD     DI, BX              ; ES:DI -> Upper Left Pixel\r
+ 0AEC  89 7E 04                            MOV     [BP].TB_Start, DI   ; Save Starting Addr\r
+                                \r
+                                   ; Compute line to line offset\r
+                                \r
+ 0AEF  8B 5E 18                            MOV     BX, [BP].TB_Width   ; Get Width of Image\r
+ 0AF2  8B D3                       MOV     DX, BX              ; Save Copy in DX\r
+ 0AF4  C1 EB 02                            SHR     BX, 2               ; /4 = width in bands\r
+ 0AF7  A1 0000 R                   MOV     AX, SCREEN_WIDTH    ; Get Screen Width\r
+ 0AFA  2B C3                       SUB     AX, BX              ; - (Bitmap Width/4)\r
+                                \r
+ 0AFC  89 46 00                            MOV     [BP].TB_LineO, AX       ; Save Line Width offset\r
+ 0AFF  89 5E 02                            MOV     [BP].TB_PixCount, BX    ; Minimum # pix to copy\r
+                                \r
+ 0B02  83 E2 03                            AND     DX, PLANE_BITS          ; Get "partial band" size (0-3)\r
+ 0B05  89 56 06                            MOV     [BP].TB_PixSkew, DX     ; Also End of Line Skew\r
+ 0B08  89 56 08                            MOV     [BP].TB_SkewFlag, DX    ; Save as Flag/Count\r
+                                \r
+ 0B0B  83 E1 03                            AND     CX, PLANE_BITS      ; CL = Starting Plane #\r
+ 0B0E  B8 1102                     MOV     AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select\r
+ 0B11  D2 E4                       SHL     AH, CL              ; Select correct Plane\r
+                                   OUT_16  SC_Index, AX        ; Select Plane...\r
+ 0B13  BA 03C4              1          MOV     DX, SC_Index        ; then Select Register\r
+ 0B16  EF                   1          OUT     DX, AX              ; Set I/O Register(s)\r
+ 0B17  8A FC                       MOV     BH, AH              ; BH = Saved Plane Mask\r
+ 0B19  B3 04                       MOV     BL, 4               ; BL = Planes to Copy\r
+                                \r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/02/14 15:18:33\r
+modex.asm                                                   Page 13 - 1\r
+\r
+\r
+ 0B1B                          @TB_COPY_PLANE:\r
+                                \r
+ 0B1B  C5 76 1E                            LDS     SI, [BP].TB_Image   ; DS:SI-> Source Image\r
+ 0B1E  8B 56 16                            MOV     DX, [BP].TB_Height  ; # of Lines to Copy\r
+ 0B21  8B 7E 04                            MOV     DI, [BP].TB_Start   ; ES:DI-> Dest pos\r
+                                \r
+                                   ; Here AH is set with the value to be considered\r
+                                   ; "Transparent".  It can be changed!\r
+                                \r
+ 0B24  B4 00                       MOV     AH, 0               ; Value to Detect 0\r
+                                \r
+ 0B26                          @TB_COPY_LINE:\r
+ 0B26  8B 4E 02                            MOV     CX, [BP].TB_PixCount    ; Min # to copy\r
+                                \r
+ 0B29  F6 C1 FC                            TEST    CL, 0FCh            ; 16+PixWide?\r
+ 0B2C  74 3A                       JZ      @TB_COPY_REMAINDER  ; Nope...\r
+                                \r
+                                   ; Pixel Copy loop has been unrolled to x4\r
+                                \r
+ 0B2E                          @TB_COPY_LOOP:\r
+ 0B2E  AC                          LODSB                       ; Get Pixel Value in AL\r
+ 0B2F  83 C6 03                            ADD     SI, 3               ; Skip to Next Byte in same plane\r
+ 0B32  38 E0                       CMP     AL, AH              ; It is "Transparent"?\r
+ 0B34  74 03                       JE      @TB_SKIP_01         ; Skip ahead if so\r
+ 0B36  26: 88 05                   MOV     ES:[DI], AL         ; Copy Pixel to VGA screen\r
+                                \r
+ 0B39                          @TB_SKIP_01:\r
+ 0B39  AC                          LODSB                       ; Get Pixel Value in AL\r
+ 0B3A  83 C6 03                            ADD     SI, 3               ; Skip to Next Byte in same plane\r
+ 0B3D  38 E0                       CMP     AL, AH              ; It is "Transparent"?\r
+ 0B3F  74 04                       JE      @TB_SKIP_02         ; Skip ahead if so\r
+ 0B41  26: 88 45 01                MOV     ES:[DI+1], AL       ; Copy Pixel to VGA screen\r
+                                \r
+ 0B45                          @TB_SKIP_02:\r
+ 0B45  AC                          LODSB                       ; Get Pixel Value in AL\r
+ 0B46  83 C6 03                            ADD     SI, 3               ; Skip to Next Byte in same plane\r
+ 0B49  38 E0                       CMP     AL, AH              ; It is "Transparent"?\r
+ 0B4B  74 04                       JE      @TB_SKIP_03         ; Skip ahead if so\r
+ 0B4D  26: 88 45 02                MOV     ES:[DI+2], AL       ; Copy Pixel to VGA screen\r
+                                \r
+ 0B51                          @TB_SKIP_03:\r
+ 0B51  AC                          LODSB                       ; Get Pixel Value in AL\r
+ 0B52  83 C6 03                            ADD     SI, 3               ; Skip to Next Byte in same plane\r
+ 0B55  38 E0                       CMP     AL, AH              ; It is "Transparent"?\r
+ 0B57  74 04                       JE      @TB_SKIP_04         ; Skip ahead if so\r
+ 0B59  26: 88 45 03                MOV     ES:[DI+3], AL       ; Copy Pixel to VGA screen\r
+                                \r
+ 0B5D                          @TB_SKIP_04:\r
+ 0B5D  83 C7 04                            ADD     DI, 4               ; Adjust Pixel Write Location\r
+ 0B60  80 E9 04                            SUB     CL, 4               ; Pixels to Copy=-4\r
+ 0B63  F6 C1 FC                            TEST    CL, 0FCh            ; 4+ Pixels Left?\r
+ 0B66  75 C6                       JNZ     @TB_COPY_LOOP       ; if so, do another block\r
+                                \r
+ 0B68                          @TB_COPY_REMAINDER:\r
+ 0B68  E3 0F                       JCXZ    @TB_NEXT_LINE       ; Any Pixels left on line\r
+                                \r
+ 0B6A                          @TB_COPY2:\r
+ 0B6A  AC                          LODSB                       ; Get Pixel Value in AL\r
+ 0B6B  83 C6 03                            ADD     SI, 3               ; Skip to Next Byte in same plane\r
+ 0B6E  38 E0                       CMP     AL, AH              ; It is "Transparent"?\r
+ 0B70  74 03                       JE      @TB_SKIP_05         ; Skip ahead if so\r
+ 0B72  26: 88 05                   MOV     ES:[DI], AL         ; Copy Pixel to VGA screen\r
+                                \r
+ 0B75                          @TB_SKIP_05:\r
+ 0B75  47                          INC     DI                  ; Advance Dest Addr\r
+                                   LOOPx   CX, @TB_COPY2       ; Pixels to Copy--, Loop until done\r
+ 0B76  49                   1      DEC     CX                ; Counter--\r
+ 0B77  75 F1                1      JNZ     @TB_COPY2             ; Jump if not 0\r
+                                \r
+ 0B79                          @TB_NEXT_LINE:\r
+                                \r
+                                   ; any Partial Pixels? (some planes only)\r
+                                \r
+ 0B79  0B 4E 08                            OR      CX, [BP].TB_SkewFlag    ; Get Skew Count\r
+ 0B7C  74 09                       JZ      @TB_NEXT2               ; if no partial pixels\r
+                                \r
+ 0B7E  AC                          LODSB                       ; Get Pixel Value in AL\r
+ 0B7F  4E                          DEC     SI                  ; Backup to Align\r
+ 0B80  38 E0                       CMP     AL, AH              ; It is "Transparent"?\r
+ 0B82  74 03                       JE      @TB_NEXT2           ; Skip ahead if so\r
+ 0B84  26: 88 05                   MOV     ES:[DI], AL         ; Copy Pixel to VGA screen\r
+                                \r
+ 0B87                          @TB_NEXT2:\r
+ 0B87  03 76 06                            ADD     SI, [BP].TB_PixSkew ; Adjust Skew\r
+ 0B8A  03 7E 00                            ADD     DI, [BP].TB_LineO   ; Set to Next Display Line\r
+                                   LOOPx   DX, @TB_COPY_LINE   ; Lines to Copy--, Loop if More\r
+ 0B8D  4A                   1      DEC     DX                ; Counter--\r
+ 0B8E  75 96                1      JNZ     @TB_COPY_LINE             ; Jump if not 0\r
+                                \r
+                                   ;Copy Next Plane....\r
+                                \r
+ 0B90  FE CB                       DEC     BL                  ; Planes to Go--\r
+ 0B92  74 1C                       JZ      @TB_Exit            ; Hey! We are done\r
+                                \r
+ 0B94  D0 C7                       ROL     BH, 1               ; Next Plane in line...\r
+                                   OUT_8   SC_Data, BH         ; Select Plane\r
+ 0B96  BA 03C5              1          MOV     DX, SC_Data        ; then Select Register\r
+ 0B99  8A C7                1          MOV     AL, BH           ; then Get Data Value\r
+ 0B9B  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+                                \r
+ 0B9C  3C 12                       CMP     AL, 12h             ; Carry Set if AL=11h\r
+ 0B9E  83 56 04 00                 ADC     [BP].TB_Start, 0    ; Screen Addr =+Carry\r
+ 0BA2  FF 46 1E                            INC     w [BP].TB_Image     ; Start @ Next Byte\r
+                                \r
+ 0BA5  83 6E 08 01                 SUB     [BP].TB_SkewFlag, 1 ; Reduce Planes to Skew\r
+ 0BA9  83 56 08 00                 ADC     [BP].TB_SkewFlag, 0 ; Back to 0 if it was -1\r
+                                \r
+ 0BAD  E9 FF6B                     JMP     @TB_COPY_PLANE      ; Go Copy the next Plane\r
+                                \r
+ 0BB0                          @TB_Exit:\r
+ 0BB0  83 C4 0A                            ADD     SP, 10              ; Deallocate workspace\r
+                                   POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+ 0BB3  5F                   1          POP     DI              ; Restore R1\r
+ 0BB4  5E                   2          POP     SI              ; Restore R1\r
+ 0BB5  1F                   3          POP     DS              ; Restore R1\r
+ 0BB6  5D                   4          POP     BP              ; Restore R1\r
+ 0BB7  CA 000C                     RET     12                  ; Exit and Clean up Stack\r
+                                \r
+ 0BBA                          TDRAW_BITMAP    ENDP\r
+                                \r
+                                \r
+                                   ; ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====\r
+                                \r
+                               ;==================================\r
+                               ;COPY_PAGE (SourcePage%, DestPage%)\r
+                               ;==================================\r
+                               ;\r
+                               ; Duplicate on display page onto another\r
+                               ;\r
+                               ; ENTRY: SourcePage = Display Page # to Duplicate\r
+                               ;        DestPage   = Display Page # to hold copy\r
+                               ;\r
+                               ; EXIT:  No meaningful values returned\r
+                               ;\r
+                                \r
+ 0010                          CP_STACK    STRUC\r
+ 0000  0000 0000 0000                          DW  ?x4 ; DI, SI, DS, BP\r
+       0000\r
+ 0008  00000000                                        DD  ?   ; Caller\r
+ 000C  0000                        CP_DestP    DW  ?   ; Page to hold copied image\r
+ 000E  0000                        CP_SourceP  DW  ?   ; Page to Make copy from\r
+                               CP_STACK    ENDS\r
+                                \r
+                                       PUBLIC    COPY_PAGE\r
+                                \r
+ 0BBA                          COPY_PAGE   PROC    FAR\r
+                                \r
+                                   PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+ 0BBA  55                   1          PUSH    BP              ; Save R1\r
+ 0BBB  1E                   2          PUSH    DS              ; Save R1\r
+ 0BBC  56                   3          PUSH    SI              ; Save R1\r
+ 0BBD  57                   4          PUSH    DI              ; Save R1\r
+ 0BBE  8B EC                       MOV     BP, SP              ; Set up Stack Frame\r
+ 0BC0  FC                          CLD                         ; Block Xfer Forwards\r
+                                \r
+                                   ; Make sure Page #'s are valid\r
+                                \r
+ 0BC1  8B 46 0E                            MOV     AX, [BP].CP_SourceP ; Get Source Page #\r
+ 0BC4  3B 06 0004 R                CMP     AX, LAST_PAGE       ; is it > Max Page #?\r
+ 0BC8  73 3D                       JAE     @CP_Exit            ; if so, abort\r
+                                \r
+ 0BCA  8B 5E 0C                            MOV     BX, [BP].CP_DestP   ; Get Destination Page #\r
+ 0BCD  3B 1E 0004 R                CMP     BX, LAST_PAGE       ; is it > Max Page #?\r
+ 0BD1  73 34                       JAE     @CP_Exit            ; if so, abort\r
+                                \r
+ 0BD3  3B C3                       CMP     AX, BX              ; Pages #'s the same?\r
+ 0BD5  74 30                       JE      @CP_Exit            ; if so, abort\r
+                                \r
+                                   ; Setup DS:SI and ES:DI to Video Pages\r
+                                \r
+ 0BD7  D1 E3                       SHL     BX, 1               ; Scale index to Word\r
+ 0BD9  8B BF 0006 R                MOV     DI, PAGE_ADDR[BX]   ; Offset to Dest Page\r
+                                \r
+ 0BDD  8B D8                       MOV     BX, AX              ; Index to Source page\r
+ 0BDF  D1 E3                       SHL     BX, 1               ; Scale index to Word\r
+ 0BE1  8B B7 0006 R                MOV     SI, PAGE_ADDR[BX]   ; Offset to Source Page\r
+                                \r
+ 0BE5  8B 0E 000E R                MOV     CX, PAGE_SIZE       ; Get size of Page\r
+ 0BE9  A1 0016 R                   MOV     AX, CURRENT_SEGMENT ; Get Video Mem Segment\r
+ 0BEC  8E C0                       MOV     ES, AX              ; ES:DI -> Dest Page\r
+ 0BEE  8E D8                       MOV     DS, AX              ; DS:SI -> Source Page\r
+                                \r
+                                   ; Setup VGA registers for Mem to Mem copy\r
+                                \r
+                                   OUT_16  GC_Index, LATCHES_ON    ; Data from Latches = on\r
+ 0BF0  BA 03CE              1          MOV     DX, GC_Index        ; then Select Register\r
+ 0BF3  B8 0008              1          MOV     AX, LATCHES_ON           ; then Get Data Value\r
+ 0BF6  EF                   1          OUT     DX, AX              ; Set I/O Register(s)\r
+                                   OUT_16  SC_Index, ALL_PLANES_ON ; Copy all Planes\r
+ 0BF7  BA 03C4              1          MOV     DX, SC_Index        ; then Select Register\r
+ 0BFA  B8 0F02              1          MOV     AX, ALL_PLANES_ON           ; then Get Data Value\r
+ 0BFD  EF                   1          OUT     DX, AX              ; Set I/O Register(s)\r
+                                \r
+                                   ; Note.. Do *NOT* use MOVSW or MOVSD - they will\r
+                                   ; Screw with the latches which are 8 bits x 4\r
+                                \r
+ 0BFE  F3/ A4                      REP     MOVSB               ; Copy entire Page!\r
+                                \r
+                                   ; Reset VGA for normal memory access\r
+                                \r
+                                   OUT_16  GC_Index, LATCHES_OFF   ; Data from Latches = off\r
+ 0C00  BA 03CE              1          MOV     DX, GC_Index        ; then Select Register\r
+ 0C03  B8 FF08              1          MOV     AX, LATCHES_OFF           ; then Get Data Value\r
+ 0C06  EF                   1          OUT     DX, AX              ; Set I/O Register(s)\r
+                                \r
+ 0C07                          @CP_Exit:\r
+                                   POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+ 0C07  5F                   1          POP     DI              ; Restore R1\r
+ 0C08  5E                   2          POP     SI              ; Restore R1\r
+ 0C09  1F                   3          POP     DS              ; Restore R1\r
+ 0C0A  5D                   4          POP     BP              ; Restore R1\r
+ 0C0B  CA 0004                     RET     4                   ; Exit and Clean up Stack\r
+                                \r
+ 0C0E                          COPY_PAGE   ENDP\r
+                                \r
+                                \r
+                               ;==========================================================================\r
+                               ;COPY_BITMAP (SourcePage%, X1%, Y1%, X2%, Y2%, DestPage%, DestX1%, DestY1%)\r
+                               ;==========================================================================\r
+                               ;\r
+                               ; Copies a Bitmap Image from one Display Page to Another\r
+                               ; This Routine is Limited to copying Images with the same\r
+                               ; Plane Alignment.  To Work: (X1 MOD 4) must = (DestX1 MOD 4)\r
+                               ; Copying an Image to the Same Page is supported, but results\r
+                               ; may be defined when the when the rectangular areas\r
+                               ; (X1, Y1) - (X2, Y2) and (DestX1, DestY1) -\r
+                               ; (DestX1+(X2-X1), DestY1+(Y2-Y1)) overlap...\r
+                               ; No Paramter checking to done to insure that\r
+                               ; X2 >= X1 and Y2 >= Y1.  Be Careful...\r
+                               ;\r
+                               ; ENTRY: SourcePage = Display Page # with Source Image\r
+                               ;        X1         = Upper Left Xpos of Source Image\r
+                               ;        Y1         = Upper Left Ypos of Source Image\r
+                               ;        X2         = Lower Right Xpos of Source Image\r
+                               ;        Y2         = Lower Right Ypos of Source Image\r
+                               ;        DestPage   = Display Page # to copy Image to\r
+                               ;        DestX1     = Xpos to Copy UL Corner of Image to\r
+                               ;        DestY1     = Ypos to Copy UL Corner of Image to\r
+                               ;\r
+                               ; EXIT:  AX = Success Flag:   0 = Failure / -1= Success\r
+                               ;\r
+                                \r
+ 0020                          CB_STACK    STRUC\r
+ 0000  0000                        CB_Height   DW  ?   ; Height of Image in Lines\r
+ 0002  0000                        CB_Width    DW  ?   ; Width of Image in "bands"\r
+ 0004  0000 0000 0000                          DW  ?x4 ; DI, SI, DS, BP\r
+       0000\r
+ 000C  00000000                                        DD  ?   ; Caller\r
+ 0010  0000                        CB_DestY1   DW  ?   ; Destination Ypos\r
+ 0012  0000                        CB_DestX1   DW  ?   ; Destination Xpos\r
+ 0014  0000                        CB_DestP    DW  ?   ; Page to Copy Bitmap To\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/02/14 15:18:33\r
+modex.asm                                                   Page 14 - 1\r
+\r
+\r
+ 0016  0000                        CB_Y2       DW  ?   ; LR Ypos of Image\r
+ 0018  0000                        CB_X2       DW  ?   ; LR Xpos of Image\r
+ 001A  0000                        CB_Y1       DW  ?   ; UL Ypos of Image\r
+ 001C  0000                        CB_X1       DW  ?   ; UL Xpos of Image\r
+ 001E  0000                        CB_SourceP  DW  ?   ; Page containing Source Bitmap\r
+                               CB_STACK    ENDS\r
+                                \r
+                                       PUBLIC    COPY_BITMAP\r
+                                \r
+ 0C0E                          COPY_BITMAP PROC    FAR\r
+                                \r
+                                   PUSHx   BP, DS, SI, DI      ; Preserve Important Registers\r
+ 0C0E  55                   1          PUSH    BP              ; Save R1\r
+ 0C0F  1E                   2          PUSH    DS              ; Save R1\r
+ 0C10  56                   3          PUSH    SI              ; Save R1\r
+ 0C11  57                   4          PUSH    DI              ; Save R1\r
+ 0C12  83 EC 04                            SUB     SP, 4               ; Allocate WorkSpace on Stack\r
+ 0C15  8B EC                       MOV     BP, SP              ; Set up Stack Frame\r
+                                \r
+                                   ; Prep Registers (and keep jumps short!)\r
+                                \r
+ 0C17  8E 06 0016 R                MOV     ES, CURRENT_SEGMENT ; ES -> VGA Ram\r
+ 0C1B  FC                          CLD                         ; Block Xfer Forwards\r
+                                \r
+                                   ; Make sure Parameters are valid\r
+                                \r
+ 0C1C  8B 5E 1E                            MOV     BX, [BP].CB_SourceP ; Get Source Page #\r
+ 0C1F  3B 1E 0004 R                CMP     BX, LAST_PAGE       ; is it > Max Page #?\r
+ 0C23  73 7D                       JAE     @CB_Abort           ; if so, abort\r
+                                \r
+ 0C25  8B 4E 14                            MOV     CX, [BP].CB_DestP   ; Get Destination Page #\r
+ 0C28  3B 0E 0004 R                CMP     CX, LAST_PAGE       ; is it > Max Page #?\r
+ 0C2C  73 74                       JAE     @CB_Abort           ; if so, abort\r
+                                \r
+ 0C2E  8B 46 1C                            MOV     AX, [BP].CB_X1      ; Get Source X1\r
+ 0C31  33 46 12                            XOR     AX, [BP].CB_DestX1  ; Compare Bits 0-1\r
+ 0C34  83 E0 03                            AND     AX, PLANE_BITS      ; Check Plane Bits\r
+ 0C37  75 69                       JNZ     @CB_Abort           ; They should cancel out\r
+                                \r
+                                   ; Setup for Copy processing\r
+                                \r
+                                   OUT_8   SC_INDEX, MAP_MASK      ; Set up for Plane Select\r
+ 0C39  BA 03C4              1          MOV     DX, SC_INDEX        ; then Select Register\r
+ 0C3C  B0 02                1          MOV     AL, MAP_MASK           ; then Get Data Value\r
+ 0C3E  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+                                   OUT_16  GC_Index, LATCHES_ON    ; Data from Latches = on\r
+ 0C3F  BA 03CE              1          MOV     DX, GC_Index        ; then Select Register\r
+ 0C42  B8 0008              1          MOV     AX, LATCHES_ON           ; then Get Data Value\r
+ 0C45  EF                   1          OUT     DX, AX              ; Set I/O Register(s)\r
+                                \r
+                                   ; Compute Info About Images, Setup ES:SI & ES:DI\r
+                                \r
+ 0C46  8B 46 16                            MOV     AX, [BP].CB_Y2      ; Height of Bitmap in lines\r
+ 0C49  2B 46 1A                            SUB     AX, [BP].CB_Y1      ; is Y2 - Y1 + 1\r
+ 0C4C  40                          INC     AX                  ; (add 1 since were not 0 based)\r
+ 0C4D  89 46 00                            MOV     [BP].CB_Height, AX  ; Save on Stack for later use\r
+                                \r
+ 0C50  8B 46 18                            MOV     AX, [BP].CB_X2      ; Get # of "Bands" of 4 Pixels\r
+ 0C53  8B 56 1C                            MOV     DX, [BP].CB_X1      ; the Bitmap Occupies as X2-X1\r
+ 0C56  C1 E8 02                            SHR     AX, 2               ; Get X2 Band (X2 / 4)\r
+ 0C59  C1 EA 02                            SHR     DX, 2               ; Get X1 Band (X1 / 4)\r
+ 0C5C  2B C2                       SUB     AX, DX              ; AX = # of Bands - 1\r
+ 0C5E  40                          INC     AX                  ; AX = # of Bands\r
+ 0C5F  89 46 02                            MOV     [BP].CB_Width, AX   ; Save on Stack for later use\r
+                                \r
+ 0C62  D1 E3                       SHL     BX, 1               ; Scale Source Page to Word\r
+ 0C64  8B B7 0006 R                MOV     SI, PAGE_ADDR[BX]   ; SI = Offset of Source Page\r
+ 0C68  8B 46 1A                            MOV     AX, [BP].CB_Y1      ; Get Source Y1 Line\r
+ 0C6B  F7 26 0000 R                MUL     SCREEN_WIDTH        ; AX = Offset to Line Y1\r
+ 0C6F  03 F0                       ADD     SI, AX              ; SI = Offset to Line Y1\r
+ 0C71  8B 46 1C                            MOV     AX, [BP].CB_X1      ; Get Source X1\r
+ 0C74  C1 E8 02                            SHR     AX, 2               ; X1 / 4 = Byte offset\r
+ 0C77  03 F0                       ADD     SI, AX              ; SI = Byte Offset to (X1,Y1)\r
+                                \r
+ 0C79  8B D9                       MOV     BX, CX              ; Dest Page Index to BX\r
+ 0C7B  D1 E3                       SHL     BX, 1               ; Scale Source Page to Word\r
+ 0C7D  8B BF 0006 R                MOV     DI, PAGE_ADDR[BX]   ; DI = Offset of Dest Page\r
+ 0C81  8B 46 10                            MOV     AX, [BP].CB_DestY1  ; Get Dest Y1 Line\r
+ 0C84  F7 26 0000 R                MUL     SCREEN_WIDTH        ; AX = Offset to Line Y1\r
+ 0C88  03 F8                       ADD     DI, AX              ; DI = Offset to Line Y1\r
+ 0C8A  8B 46 12                            MOV     AX, [BP].CB_DestX1  ; Get Dest X1\r
+ 0C8D  C1 E8 02                            SHR     AX, 2               ; X1 / 4 = Byte offset\r
+ 0C90  03 F8                       ADD     DI, AX              ; DI = Byte Offset to (D-X1,D-Y1)\r
+                                \r
+ 0C92  8B 4E 02                            MOV     CX, [BP].CB_Width   ; CX = Width of Image (Bands)\r
+ 0C95  49                          DEC     CX                  ; CX = 1?\r
+ 0C96  74 0F                       JE      @CB_Only_One_Band   ; 0 Means Image Width of 1 Band\r
+                                \r
+ 0C98  8B 5E 1C                            MOV     BX, [BP].CB_X1      ; Get Source X1\r
+ 0C9B  83 E3 03                            AND     BX, PLANE_BITS      ; Aligned? (bits 0-1 = 00?)\r
+ 0C9E  74 70                       JZ      @CB_Check_Right     ; if so, check right alignment\r
+ 0CA0  75 41                       JNZ     @CB_Left_Band       ; not aligned? well..\r
+                                \r
+ 0CA2                          @CB_Abort:\r
+                                   CLR     AX                  ; Return False (Failure)\r
+ 0CA2  33 C0                1          XOR     AX, AX      ; Set Register = 0\r
+ 0CA4  E9 00D7                     JMP     @CB_Exit            ; and Finish Up\r
+                                \r
+                                   ; Copy when Left & Right Clip Masks overlap...\r
+                                \r
+ 0CA7                          @CB_Only_One_Band:\r
+ 0CA7  8B 5E 1C                            MOV     BX, [BP].CB_X1          ; Get Left Clip Mask\r
+ 0CAA  83 E3 03                            AND     BX, PLANE_BITS          ; Mask out Row #\r
+ 0CAD  2E: 8A 87 0000 R                    MOV     AL, Left_Clip_Mask[BX]  ; Get Left Edge Mask\r
+ 0CB2  8B 5E 18                            MOV     BX, [BP].CB_X2          ; Get Right Clip Mask\r
+ 0CB5  83 E3 03                            AND     BX, PLANE_BITS          ; Mask out Row #\r
+ 0CB8  2E: 22 87 0004 R                    AND     AL, Right_Clip_Mask[BX] ; Get Right Edge Mask byte\r
+                                \r
+                                   OUT_8   SC_Data, AL         ; Clip For Left & Right Masks\r
+ 0CBD  BA 03C5              1          MOV     DX, SC_Data        ; then Select Register\r
+ 0CC0  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+                                \r
+ 0CC1  8B 4E 00                            MOV     CX, [BP].CB_Height  ; CX = # of Lines to Copy\r
+ 0CC4  8B 16 0000 R                MOV     DX, SCREEN_WIDTH    ; DX = Width of Screen\r
+                                   CLR     BX                  ; BX = Offset into Image\r
+ 0CC8  33 DB                1          XOR     BX, BX      ; Set Register = 0\r
+                                \r
+ 0CCA                          @CB_One_Loop:\r
+ 0CCA  26: 8A 00                   MOV     AL, ES:[SI+BX]      ; Load Latches\r
+ 0CCD  26: 88 01                   MOV     ES:[DI+BX], AL      ; Unload Latches\r
+ 0CD0  03 DA                       ADD     BX, DX              ; Advance Offset to Next Line\r
+                                   LOOPjz  CX, @CB_One_Done    ; Exit Loop if Finished\r
+ 0CD2  49                   1      DEC     CX                ; Counter--\r
+ 0CD3  74 0B                1      JZ      @CB_One_Done             ; Jump if 0\r
+                                \r
+ 0CD5  26: 8A 00                   MOV     AL, ES:[SI+BX]      ; Load Latches\r
+ 0CD8  26: 88 01                   MOV     ES:[DI+BX], AL      ; Unload Latches\r
+ 0CDB  03 DA                       ADD     BX, DX              ; Advance Offset to Next Line\r
+                                   LOOPx   CX, @CB_One_Loop    ; Loop until Finished\r
+ 0CDD  49                   1      DEC     CX                ; Counter--\r
+ 0CDE  75 EA                1      JNZ     @CB_One_Loop             ; Jump if not 0\r
+                                \r
+ 0CE0                          @CB_One_Done:\r
+ 0CE0  E9 0094                     JMP     @CB_Finish          ; Outa Here!\r
+                                \r
+                                   ; Copy Left Edge of Bitmap\r
+                                \r
+ 0CE3                          @CB_Left_Band:\r
+                                \r
+                                   OUT_8   SC_Data, Left_Clip_Mask[BX] ; Set Left Edge Plane Mask\r
+ 0CE3  BA 03C5              1          MOV     DX, SC_Data        ; then Select Register\r
+ 0CE6  2E: 8A 87 0000 R             1          MOV     AL, Left_Clip_Mask[BX]           ; then Get Data Value\r
+ 0CEB  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+                                \r
+ 0CEC  8B 4E 00                            MOV     CX, [BP].CB_Height  ; CX = # of Lines to Copy\r
+ 0CEF  8B 16 0000 R                MOV     DX, SCREEN_WIDTH    ; DX = Width of Screen\r
+                                   CLR     BX                  ; BX = Offset into Image\r
+ 0CF3  33 DB                1          XOR     BX, BX      ; Set Register = 0\r
+                                \r
+ 0CF5                          @CB_Left_Loop:\r
+ 0CF5  26: 8A 00                   MOV     AL, ES:[SI+BX]      ; Load Latches\r
+ 0CF8  26: 88 01                   MOV     ES:[DI+BX], AL      ; Unload Latches\r
+ 0CFB  03 DA                       ADD     BX, DX              ; Advance Offset to Next Line\r
+                                   LOOPjz  CX, @CB_Left_Done   ; Exit Loop if Finished\r
+ 0CFD  49                   1      DEC     CX                ; Counter--\r
+ 0CFE  74 0B                1      JZ      @CB_Left_Done             ; Jump if 0\r
+                                \r
+ 0D00  26: 8A 00                   MOV     AL, ES:[SI+BX]      ; Load Latches\r
+ 0D03  26: 88 01                   MOV     ES:[DI+BX], AL      ; Unload Latches\r
+ 0D06  03 DA                       ADD     BX, DX              ; Advance Offset to Next Line\r
+                                   LOOPx   CX, @CB_Left_Loop   ; Loop until Finished\r
+ 0D08  49                   1      DEC     CX                ; Counter--\r
+ 0D09  75 EA                1      JNZ     @CB_Left_Loop             ; Jump if not 0\r
+                                \r
+ 0D0B                          @CB_Left_Done:\r
+ 0D0B  47                          INC     DI                  ; Move Dest Over 1 band\r
+ 0D0C  46                          INC     SI                  ; Move Source Over 1 band\r
+ 0D0D  FF 4E 02                            DEC     [BP].CB_Width       ; Band Width--\r
+                                \r
+                                   ; Determine if Right Edge of Bitmap needs special copy\r
+                                \r
+ 0D10                          @CB_Check_Right:\r
+ 0D10  8B 5E 18                            MOV     BX, [BP].CB_X2      ; Get Source X2\r
+ 0D13  83 E3 03                            AND     BX, PLANE_BITS      ; Aligned? (bits 0-1 = 11?)\r
+ 0D16  80 FB 03                            CMP     BL, 03h             ; Plane = 3?\r
+ 0D19  74 2C                       JE      @CB_Copy_Middle     ; Copy the Middle then!\r
+                                \r
+                                   ; Copy Right Edge of Bitmap\r
+                                \r
+ 0D1B                          @CB_Right_Band:\r
+                                \r
+                                   OUT_8   SC_Data, Right_Clip_Mask[BX]    ; Set Right Edge Plane Mask\r
+ 0D1B  BA 03C5              1          MOV     DX, SC_Data        ; then Select Register\r
+ 0D1E  2E: 8A 87 0004 R             1          MOV     AL, Right_Clip_Mask[BX]           ; then Get Data Value\r
+ 0D23  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+                                \r
+ 0D24  FF 4E 02                            DEC     [BP].CB_Width       ; Band Width--\r
+ 0D27  8B 4E 00                            MOV     CX, [BP].CB_Height  ; CX = # of Lines to Copy\r
+ 0D2A  8B 16 0000 R                MOV     DX, SCREEN_WIDTH    ; DX = Width of Screen\r
+ 0D2E  8B 5E 02                            MOV     BX, [BP].CB_Width   ; BX = Offset to Right Edge\r
+                                \r
+ 0D31                          @CB_Right_Loop:\r
+ 0D31  26: 8A 00                   MOV     AL, ES:[SI+BX]      ; Load Latches\r
+ 0D34  26: 88 01                   MOV     ES:[DI+BX], AL      ; Unload Latches\r
+ 0D37  03 DA                       ADD     BX, DX              ; Advance Offset to Next Line\r
+                                   LOOPjz  CX, @CB_Right_Done  ; Exit Loop if Finished\r
+ 0D39  49                   1      DEC     CX                ; Counter--\r
+ 0D3A  74 0B                1      JZ      @CB_Right_Done             ; Jump if 0\r
+                                \r
+ 0D3C  26: 8A 00                   MOV     AL, ES:[SI+BX]      ; Load Latches\r
+ 0D3F  26: 88 01                   MOV     ES:[DI+BX], AL      ; Unload Latches\r
+ 0D42  03 DA                       ADD     BX, DX              ; Advance Offset to Next Line\r
+                                   LOOPx   CX, @CB_Right_Loop  ; Loop until Finished\r
+ 0D44  49                   1      DEC     CX                ; Counter--\r
+ 0D45  75 EA                1      JNZ     @CB_Right_Loop             ; Jump if not 0\r
+                                \r
+ 0D47                          @CB_Right_Done:\r
+                                \r
+                                   ; Copy the Main Block of the Bitmap\r
+                                \r
+ 0D47                          @CB_Copy_Middle:\r
+                                \r
+ 0D47  8B 4E 02                            MOV     CX, [BP].CB_Width   ; Get Width Remaining\r
+ 0D4A  E3 2B                       JCXZ    @CB_Finish          ; Exit if Done\r
+                                \r
+                                   OUT_8   SC_Data, ALL_PLANES ; Copy all Planes\r
+ 0D4C  BA 03C5              1          MOV     DX, SC_Data        ; then Select Register\r
+ 0D4F  B0 0F                1          MOV     AL, ALL_PLANES           ; then Get Data Value\r
+ 0D51  EE                   1          OUT     DX, AL              ; Set I/O Register\r
+                                \r
+ 0D52  8B 16 0000 R                MOV     DX, SCREEN_WIDTH    ; Get Width of Screen minus\r
+ 0D56  2B D1                       SUB     DX, CX              ; Image width (for Adjustment)\r
+ 0D58  8B 46 00                            MOV     AX, [BP].CB_Height  ; AX = # of Lines to Copy\r
+ 0D5B  8B D9                       MOV     BX, CX              ; BX = Quick REP reload count\r
+ 0D5D  8C C1                       MOV     CX, ES              ; Move VGA Segment\r
+ 0D5F  8E D9                       MOV     DS, CX              ; Into DS\r
+                                \r
+                                   ; Actual Copy Loop.  REP MOVSB does the work\r
+                                \r
+ 0D61                          @CB_Middle_Copy:\r
+ 0D61  8B CB                       MOV     CX, BX              ; Recharge Rep Count\r
+ 0D63  F3/ A4                      REP     MOVSB               ; Move Bands\r
+                                   LOOPjz  AX, @CB_Finish      ; Exit Loop if Finished\r
+ 0D65  48                   1      DEC     AX                ; Counter--\r
+ 0D66  74 0F                1      JZ      @CB_Finish             ; Jump if 0\r
+                                \r
+ 0D68  03 F2                       ADD     SI, DX              ; Adjust DS:SI to Next Line\r
+ 0D6A  03 FA                       ADD     DI, DX              ; Adjust ES:DI to Next Line\r
+                                \r
+ 0D6C  8B CB                       MOV     CX, BX              ; Recharge Rep Count\r
+ 0D6E  F3/ A4                      REP     MOVSB               ; Move Bands\r
+                                \r
+ 0D70  03 F2                       ADD     SI, DX              ; Adjust DS:SI to Next Line\r
+ 0D72  03 FA                       ADD     DI, DX              ; Adjust ES:DI to Next Line\r
+                                   LOOPx   AX, @CB_Middle_Copy ; Copy Lines until Done\r
+ 0D74  48                   1      DEC     AX                ; Counter--\r
+ 0D75  75 EA                1      JNZ     @CB_Middle_Copy             ; Jump if not 0\r
+                                \r
+ 0D77                          @CB_Finish:\r
+                                   OUT_16  GC_Index, LATCHES_OFF   ; Data from Latches = on\r
+ 0D77  BA 03CE              1          MOV     DX, GC_Index        ; then Select Register\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/02/14 15:18:33\r
+modex.asm                                                   Page 15 - 1\r
+\r
+\r
+ 0D7A  B8 FF08              1          MOV     AX, LATCHES_OFF           ; then Get Data Value\r
+ 0D7D  EF                   1          OUT     DX, AX              ; Set I/O Register(s)\r
+                                \r
+ 0D7E                          @CB_Exit:\r
+ 0D7E  83 C4 04                            ADD     SP, 04              ; Deallocate stack workspace\r
+                                   POPx    DI, SI, DS, BP      ; Restore Saved Registers\r
+ 0D81  5F                   1          POP     DI              ; Restore R1\r
+ 0D82  5E                   2          POP     SI              ; Restore R1\r
+ 0D83  1F                   3          POP     DS              ; Restore R1\r
+ 0D84  5D                   4          POP     BP              ; Restore R1\r
+ 0D85  CA 0010                     RET     16                  ; Exit and Clean up Stack\r
+                                \r
+ 0D88                          COPY_BITMAP ENDP\r
+                                \r
+                                   END                         ; End of Code Segment\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/02/14 15:18:33\r
+modex.asm                                                   Symbols 16 - 1\r
+\r
+\r
+\r
+\r
+Macros:\r
+\r
+                N a m e                 Type\r
+\r
+CLR  . . . . . . . . . . . . . .       Proc\r
+LOOPjz . . . . . . . . . . . . .       Proc\r
+LOOPx  . . . . . . . . . . . . .       Proc\r
+OUT_16 . . . . . . . . . . . . .       Proc\r
+OUT_8  . . . . . . . . . . . . .       Proc\r
+POPx . . . . . . . . . . . . . .       Proc\r
+PUSHx  . . . . . . . . . . . . .       Proc\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/02/14 15:18:33\r
+modex.asm                                                   Symbols 17 - 1\r
+\r
+\r
+\r
+\r
+Structures and Unions:\r
+\r
+                N a m e                  Size\r
+                                         Offset      Type\r
+\r
+CB_STACK . . . . . . . . . . . .        0020\r
+  CB_Height  . . . . . . . . . .        0000        Word\r
+  CB_Width . . . . . . . . . . .        0002        Word\r
+  CB_DestY1  . . . . . . . . . .        0010        Word\r
+  CB_DestX1  . . . . . . . . . .        0012        Word\r
+  CB_DestP . . . . . . . . . . .        0014        Word\r
+  CB_Y2  . . . . . . . . . . . .        0016        Word\r
+  CB_X2  . . . . . . . . . . . .        0018        Word\r
+  CB_Y1  . . . . . . . . . . . .        001A        Word\r
+  CB_X1  . . . . . . . . . . . .        001C        Word\r
+  CB_SourceP . . . . . . . . . .        001E        Word\r
+CP_STACK . . . . . . . . . . . .        0010\r
+  CP_DestP . . . . . . . . . . .        000C        Word\r
+  CP_SourceP . . . . . . . . . .        000E        Word\r
+CVS_STACK  . . . . . . . . . . .        000A\r
+  CVS_COLOR  . . . . . . . . . .        0008        Byte\r
+DB_STACK . . . . . . . . . . . .        0022\r
+  DB_LineO . . . . . . . . . . .        0000        Word\r
+  DB_PixCount  . . . . . . . . .        0002        Word\r
+  DB_Start . . . . . . . . . . .        0004        Word\r
+  DB_PixSkew . . . . . . . . . .        0006        Word\r
+  DB_SkewFlag  . . . . . . . . .        0008        Word\r
+  DB_Height  . . . . . . . . . .        0016        Word\r
+  DB_Width . . . . . . . . . . .        0018        Word\r
+  DB_Ypos  . . . . . . . . . . .        001A        Word\r
+  DB_Xpos  . . . . . . . . . . .        001C        Word\r
+  DB_Image . . . . . . . . . . .        001E        DWord\r
+DL_STACK . . . . . . . . . . . .        0014\r
+  DL_ColorF  . . . . . . . . . .        000A        Byte\r
+  DL_Ypos2 . . . . . . . . . . .        000C        Word\r
+  DL_Xpos2 . . . . . . . . . . .        000E        Word\r
+  DL_Ypos1 . . . . . . . . . . .        0010        Word\r
+  DL_Xpos1 . . . . . . . . . . .        0012        Word\r
+FB_STACK . . . . . . . . . . . .        0016\r
+  FB_Color . . . . . . . . . . .        000C        Byte\r
+  FB_Ypos2 . . . . . . . . . . .        000E        Word\r
+  FB_Xpos2 . . . . . . . . . . .        0010        Word\r
+  FB_Ypos1 . . . . . . . . . . .        0012        Word\r
+  FB_Xpos1 . . . . . . . . . . .        0014        Word\r
+GDR_STACK  . . . . . . . . . . .        000E\r
+  GDR_Blue . . . . . . . . . . .        0006        Word\r
+  GDR_Green  . . . . . . . . . .        0008        Word\r
+  GDR_Red  . . . . . . . . . . .        000A        Word\r
+  GDR_Register . . . . . . . . .        000C        Byte\r
+GPC_STACK  . . . . . . . . . . .        001E\r
+  GPC_Width  . . . . . . . . . .        0000        Word\r
+  GPC_Lines  . . . . . . . . . .        0002        Byte\r
+  GPC_T_SETS . . . . . . . . . .        0004        Word\r
+  GPC_T_SETO . . . . . . . . . .        0006        Word\r
+  GPC_ColorB . . . . . . . . . .        0014        Byte\r
+  GPC_ColorF . . . . . . . . . .        0016        Byte\r
+  GPC_Ypos . . . . . . . . . . .        0018        Word\r
+  GPC_Xpos . . . . . . . . . . .        001A        Word\r
+  GPC_Char . . . . . . . . . . .        001C        Byte\r
+LDR_STACK  . . . . . . . . . . .        0014\r
+  LDR_Sync . . . . . . . . . . .        000A        Word\r
+  LDR_EndReg . . . . . . . . . .        000C        Byte\r
+  LDR_StartReg . . . . . . . . .        000E        Byte\r
+  LDR_PalData  . . . . . . . . .        0010        DWord\r
+Mode_Data_Table  . . . . . . . .        000C\r
+  M_MiscR  . . . . . . . . . . .        0000        Byte\r
+  M_Pages  . . . . . . . . . . .        0001        Byte\r
+  M_XSize  . . . . . . . . . . .        0002        Word\r
+  M_YSize  . . . . . . . . . . .        0004        Word\r
+  M_XMax . . . . . . . . . . . .        0006        Word\r
+  M_YMax . . . . . . . . . . . .        0008        Word\r
+  M_CRTC . . . . . . . . . . . .        000A        Word\r
+PS_STACK . . . . . . . . . . . .        001A\r
+  PS_ColorB  . . . . . . . . . .        000C        Word\r
+  PS_ColorF  . . . . . . . . . .        000E        Word\r
+  PS_Ypos  . . . . . . . . . . .        0010        Word\r
+  PS_Xpos  . . . . . . . . . . .        0012        Word\r
+  PS_Len . . . . . . . . . . . .        0014        Word\r
+  PS_Text  . . . . . . . . . . .        0016        Word\r
+RDR_STACK  . . . . . . . . . . .        0012\r
+  RDR_EndReg . . . . . . . . . .        000A        Byte\r
+  RDR_StartReg . . . . . . . . .        000C        Byte\r
+  RDR_PalData  . . . . . . . . .        000E        DWord\r
+RP_STACK . . . . . . . . . . . .        000C\r
+  RP_Ypos  . . . . . . . . . . .        0008        Word\r
+  RP_Xpos  . . . . . . . . . . .        000A        Word\r
+SAP_STACK  . . . . . . . . . . .        0008\r
+  SAP_Page . . . . . . . . . . .        0006        Word\r
+SDF_STACK  . . . . . . . . . . .        000C\r
+  SDF_Which  . . . . . . . . . .        0006        Word\r
+  SDF_Font . . . . . . . . . . .        0008        DWord\r
+SDP_STACK  . . . . . . . . . . .        0008\r
+  SDP_Page . . . . . . . . . . .        0006        Word\r
+SDR_STACK  . . . . . . . . . . .        000E\r
+  SDR_Blue . . . . . . . . . . .        0006        Byte\r
+  SDR_Green  . . . . . . . . . .        0008        Byte\r
+  SDR_Red  . . . . . . . . . . .        000A        Byte\r
+  SDR_Register . . . . . . . . .        000C        Byte\r
+SM_STACK . . . . . . . . . . . .        000A\r
+  SM_Mode  . . . . . . . . . . .        0008        Word\r
+SP_STACK . . . . . . . . . . . .        000E\r
+  SETP_Color . . . . . . . . . .        0008        Byte\r
+  SETP_Ypos  . . . . . . . . . .        000A        Word\r
+  SETP_Xpos  . . . . . . . . . .        000C        Word\r
+SVM_STACK  . . . . . . . . . . .        0016\r
+  SVM_Table  . . . . . . . . . .        0000        Word\r
+  SVM_Pages  . . . . . . . . . .        000E        Word\r
+  SVM_Ysize  . . . . . . . . . .        0010        Word\r
+  SVM_Xsize  . . . . . . . . . .        0012        Word\r
+  SVM_Mode . . . . . . . . . . .        0014        Word\r
+SW_STACK . . . . . . . . . . . .        000C\r
+  SW_Ypos  . . . . . . . . . . .        0006        Word\r
+  SW_Xpos  . . . . . . . . . . .        0008        Word\r
+  SW_Page  . . . . . . . . . . .        000A        Word\r
+TB_STACK . . . . . . . . . . . .        0022\r
+  TB_LineO . . . . . . . . . . .        0000        Word\r
+  TB_PixCount  . . . . . . . . .        0002        Word\r
+  TB_Start . . . . . . . . . . .        0004        Word\r
+  TB_PixSkew . . . . . . . . . .        0006        Word\r
+  TB_SkewFlag  . . . . . . . . .        0008        Word\r
+  TB_Height  . . . . . . . . . .        0016        Word\r
+  TB_Width . . . . . . . . . . .        0018        Word\r
+  TB_Ypos  . . . . . . . . . . .        001A        Word\r
+  TB_Xpos  . . . . . . . . . . .        001C        Word\r
+  TB_Image . . . . . . . . . . .        001E        DWord\r
+TGP_STACK  . . . . . . . . . . .        001C\r
+  TGP_Width  . . . . . . . . . .        0000        Word\r
+  TGP_Lines  . . . . . . . . . .        0002        Byte\r
+  TGP_T_SETS . . . . . . . . . .        0004        Word\r
+  TGP_T_SETO . . . . . . . . . .        0006        Word\r
+  TGP_ColorF . . . . . . . . . .        0014        Byte\r
+  TGP_Ypos . . . . . . . . . . .        0016        Word\r
+  TGP_Xpos . . . . . . . . . . .        0018        Word\r
+  TGP_Char . . . . . . . . . . .        001A        Byte\r
+TPS_STACK  . . . . . . . . . . .        0018\r
+  TPS_ColorF . . . . . . . . . .        000C        Word\r
+  TPS_Ypos . . . . . . . . . . .        000E        Word\r
+  TPS_Xpos . . . . . . . . . . .        0010        Word\r
+  TPS_Len  . . . . . . . . . . .        0012        Word\r
+  TPS_Text . . . . . . . . . . .        0014        Word\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/02/14 15:18:33\r
+modex.asm                                                   Symbols 18 - 1\r
+\r
+\r
+\r
+\r
+Segments and Groups:\r
+\r
+                N a m e                 Size     Length   Align   Combine Class\r
+\r
+DGROUP . . . . . . . . . . . . .       GROUP\r
+_DATA  . . . . . . . . . . . . .       16 Bit   0000     Word    Public  'DATA'        \r
+_BSS . . . . . . . . . . . . . .       16 Bit   002A     Word    Public  'BSS'  \r
+MODEX_TEXT . . . . . . . . . . .       16 Bit   0D88     Word    Public  'CODE'        \r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/02/14 15:18:33\r
+modex.asm                                                   Symbols 19 - 1\r
+\r
+\r
+\r
+\r
+Procedures,  parameters and locals:\r
+\r
+                N a m e                 Type     Value    Attr\r
+\r
+CLEAR_VGA_SCREEN . . . . . . . .       P Far    0280     MODEX_TEXT    Length= 0022 Public\r
+COPY_BITMAP  . . . . . . . . . .       P Far    0C0E     MODEX_TEXT    Length= 017E Public\r
+COPY_PAGE  . . . . . . . . . . .       P Far    0BBA     MODEX_TEXT    Length= 0054 Public\r
+DRAW_BITMAP  . . . . . . . . . .       P Far    0A0F     MODEX_TEXT    Length= 00BC Public\r
+DRAW_LINE  . . . . . . . . . . .       P Far    040B     MODEX_TEXT    Length= 02A7 Public\r
+FILL_BLOCK . . . . . . . . . . .       P Far    0300     MODEX_TEXT    Length= 010B Public\r
+GET_ACTIVE_PAGE  . . . . . . . .       P Far    06E5     MODEX_TEXT    Length= 0004 Public\r
+GET_DAC_REGISTER . . . . . . . .       P Far    0641     MODEX_TEXT    Length= 0025 Public\r
+GET_DISPLAY_PAGE . . . . . . . .       P Far    0724     MODEX_TEXT    Length= 0004 Public\r
+GET_X_OFFSET . . . . . . . . . .       P Far    078D     MODEX_TEXT    Length= 0004 Public\r
+GET_Y_OFFSET . . . . . . . . . .       P Far    0791     MODEX_TEXT    Length= 0004 Public\r
+GPRINTC  . . . . . . . . . . . .       P Far    07A3     MODEX_TEXT    Length= 00FE Public\r
+LOAD_DAC_REGISTERS . . . . . . .       P Far    0666     MODEX_TEXT    Length= 0037 Public\r
+PRINT_STR  . . . . . . . . . . .       P Far    0975     MODEX_TEXT    Length= 0041 Public\r
+READ_DAC_REGISTERS . . . . . . .       P Far    069D     MODEX_TEXT    Length= 002B Public\r
+READ_POINT . . . . . . . . . . .       P Far    02D2     MODEX_TEXT    Length= 002E Public\r
+SET_ACTIVE_PAGE  . . . . . . . .       P Far    06C8     MODEX_TEXT    Length= 001D Public\r
+SET_DAC_REGISTER . . . . . . . .       P Far    0624     MODEX_TEXT    Length= 001D Public\r
+SET_DISPLAY_FONT . . . . . . . .       P Far    09F3     MODEX_TEXT    Length= 001C Public\r
+SET_DISPLAY_PAGE . . . . . . . .       P Far    06E9     MODEX_TEXT    Length= 003B Public\r
+SET_MODEX  . . . . . . . . . . .       P Far    0251     MODEX_TEXT    Length= 002F Public\r
+SET_POINT  . . . . . . . . . . .       P Far    02A2     MODEX_TEXT    Length= 0030 Public\r
+SET_VGA_MODEX  . . . . . . . . .       P Far    0104     MODEX_TEXT    Length= 014D Public\r
+SET_WINDOW . . . . . . . . . . .       P Far    0728     MODEX_TEXT    Length= 0065 Public\r
+SYNC_DISPLAY . . . . . . . . . .       P Far    0795     MODEX_TEXT    Length= 000E Public\r
+TDRAW_BITMAP . . . . . . . . . .       P Far    0ACB     MODEX_TEXT    Length= 00EF Public\r
+TGPRINTC . . . . . . . . . . . .       P Far    08A1     MODEX_TEXT    Length= 00D4 Public\r
+TPRINT_STR . . . . . . . . . . .       P Far    09B6     MODEX_TEXT    Length= 003D Public\r
+\fMicrosoft (R) Macro Assembler Version 6.11                07/02/14 15:18:33\r
+modex.asm                                                   Symbols 20 - 1\r
+\r
+\r
+\r
+\r
+Symbols:\r
+\r
+                N a m e                 Type     Value    Attr\r
+\r
+?x3  . . . . . . . . . . . . . .       Text     ?,?,?\r
+?x4  . . . . . . . . . . . . . .       Text     ?,?,?,?\r
+@CB_Abort  . . . . . . . . . . .       L Near   0CA2     MODEX_TEXT    \r
+@CB_Check_Right  . . . . . . . .       L Near   0D10     MODEX_TEXT    \r
+@CB_Copy_Middle  . . . . . . . .       L Near   0D47     MODEX_TEXT    \r
+@CB_Exit . . . . . . . . . . . .       L Near   0D7E     MODEX_TEXT    \r
+@CB_Finish . . . . . . . . . . .       L Near   0D77     MODEX_TEXT    \r
+@CB_Left_Band  . . . . . . . . .       L Near   0CE3     MODEX_TEXT    \r
+@CB_Left_Done  . . . . . . . . .       L Near   0D0B     MODEX_TEXT    \r
+@CB_Left_Loop  . . . . . . . . .       L Near   0CF5     MODEX_TEXT    \r
+@CB_Middle_Copy  . . . . . . . .       L Near   0D61     MODEX_TEXT    \r
+@CB_One_Done . . . . . . . . . .       L Near   0CE0     MODEX_TEXT    \r
+@CB_One_Loop . . . . . . . . . .       L Near   0CCA     MODEX_TEXT    \r
+@CB_Only_One_Band  . . . . . . .       L Near   0CA7     MODEX_TEXT    \r
+@CB_Right_Band . . . . . . . . .       L Near   0D1B     MODEX_TEXT    \r
+@CB_Right_Done . . . . . . . . .       L Near   0D47     MODEX_TEXT    \r
+@CB_Right_Loop . . . . . . . . .       L Near   0D31     MODEX_TEXT    \r
+@CP_Exit . . . . . . . . . . . .       L Near   0C07     MODEX_TEXT    \r
+@CodeSize  . . . . . . . . . . .       Number   0001h   \r
+@DB_COPY2  . . . . . . . . . . .       L Near   0A8A     MODEX_TEXT    \r
+@DB_COPY_LINE  . . . . . . . . .       L Near   0A68     MODEX_TEXT    \r
+@DB_COPY_LOOP  . . . . . . . . .       L Near   0A70     MODEX_TEXT    \r
+@DB_COPY_PLANE . . . . . . . . .       L Near   0A5F     MODEX_TEXT    \r
+@DB_COPY_REMAINDER . . . . . . .       L Near   0A88     MODEX_TEXT    \r
+@DB_Exit . . . . . . . . . . . .       L Near   0AC1     MODEX_TEXT    \r
+@DB_NEXT2  . . . . . . . . . . .       L Near   0A99     MODEX_TEXT    \r
+@DB_NEXT_LINE  . . . . . . . . .       L Near   0A91     MODEX_TEXT    \r
+@DL_BREZHAM  . . . . . . . . . .       L Near   04C7     MODEX_TEXT    \r
+@DL_DeltaYOK2  . . . . . . . . .       L Near   0515     MODEX_TEXT    \r
+@DL_DeltaYOK . . . . . . . . . .       L Near   04DC     MODEX_TEXT    \r
+@DL_DrawLeft . . . . . . . . . .       L Near   051F     MODEX_TEXT    \r
+@DL_DrawRight  . . . . . . . . .       L Near   05A3     MODEX_TEXT    \r
+@DL_EXIT2  . . . . . . . . . . .       L Near   061E     MODEX_TEXT    \r
+@DL_EXIT . . . . . . . . . . . .       L Near   04C4     MODEX_TEXT    \r
+@DL_HORZ . . . . . . . . . . . .       L Near   0433     MODEX_TEXT    \r
+@DL_LONGLN . . . . . . . . . . .       L Near   0461     MODEX_TEXT    \r
+@DL_NOSWAP1  . . . . . . . . . .       L Near   0428     MODEX_TEXT    \r
+@DL_NOSWAP2  . . . . . . . . . .       L Near   048C     MODEX_TEXT    \r
+@DL_SLLExit  . . . . . . . . . .       L Near   0563     MODEX_TEXT    \r
+@DL_SLLL2nc  . . . . . . . . . .       L Near   0543     MODEX_TEXT    \r
+@DL_SLLL3nc  . . . . . . . . . .       L Near   0558     MODEX_TEXT    \r
+@DL_SLLLoop  . . . . . . . . . .       L Near   0537     MODEX_TEXT    \r
+@DL_SLR2nc . . . . . . . . . . .       L Near   05C5     MODEX_TEXT    \r
+@DL_SLR3nc . . . . . . . . . . .       L Near   05D9     MODEX_TEXT    \r
+@DL_SLRExit  . . . . . . . . . .       L Near   05E3     MODEX_TEXT    \r
+@DL_SLRLoop  . . . . . . . . . .       L Near   05B9     MODEX_TEXT    \r
+@DL_STLExit  . . . . . . . . . .       L Near   05A1     MODEX_TEXT    \r
+@DL_STLLoop  . . . . . . . . . .       L Near   0575     MODEX_TEXT    \r
+@DL_STLnc2 . . . . . . . . . . .       L Near   0588     MODEX_TEXT    \r
+@DL_STLnc3 . . . . . . . . . . .       L Near   059D     MODEX_TEXT    \r
+@DL_ShallowLeft  . . . . . . . .       L Near   0525     MODEX_TEXT    \r
+@DL_ShallowRight . . . . . . . .       L Near   05A7     MODEX_TEXT    \r
+@DL_SteepLeft  . . . . . . . . .       L Near   0566     MODEX_TEXT    \r
+@DL_SteepRight . . . . . . . . .       L Near   05E5     MODEX_TEXT    \r
+@DL_VLINE  . . . . . . . . . . .       L Near   0481     MODEX_TEXT    \r
+@DL_VLoop  . . . . . . . . . . .       L Near   04B4     MODEX_TEXT    \r
+@DL_XRSEG  . . . . . . . . . . .       L Near   0479     MODEX_TEXT    \r
+@DP_WAIT0  . . . . . . . . . . .       L Near   0706     MODEX_TEXT    \r
+@DP_WAIT1  . . . . . . . . . . .       L Near   071B     MODEX_TEXT    \r
+@DataSize  . . . . . . . . . . .       Number   0000h   \r
+@FB_EXIT . . . . . . . . . . . .       L Near   0404     MODEX_TEXT    \r
+@FB_LEFT_CONT  . . . . . . . . .       L Near   037A     MODEX_TEXT    \r
+@FB_LEFT_LOOP  . . . . . . . . .       L Near   036A     MODEX_TEXT    \r
+@FB_L_PLANE_FLUSH  . . . . . . .       L Near   037C     MODEX_TEXT    \r
+@FB_MIDDLE_LOOP  . . . . . . . .       L Near   03C7     MODEX_TEXT    \r
+@FB_NORMAL . . . . . . . . . . .       L Near   034C     MODEX_TEXT    \r
+@FB_NOSWAP1  . . . . . . . . . .       L Near   031F     MODEX_TEXT    \r
+@FB_NOSWAP2  . . . . . . . . . .       L Near   0339     MODEX_TEXT    \r
+@FB_ONE_BAND_ONLY  . . . . . . .       L Near   03D2     MODEX_TEXT    \r
+@FB_ONE_LOOP . . . . . . . . . .       L Near   03F4     MODEX_TEXT    \r
+@FB_RIGHT_CONT . . . . . . . . .       L Near   03B0     MODEX_TEXT    \r
+@FB_RIGHT_LOOP . . . . . . . . .       L Near   03A0     MODEX_TEXT    \r
+@FB_RIGHT  . . . . . . . . . . .       L Near   037D     MODEX_TEXT    \r
+@FB_R_EDGE_FLUSH . . . . . . . .       L Near   03B3     MODEX_TEXT    \r
+@GPC_DECODE_CHAR_BYTE  . . . . .       L Near   080F     MODEX_TEXT    \r
+@GPC_EXIT  . . . . . . . . . . .       L Near   0897     MODEX_TEXT    \r
+@GPC_LowChar . . . . . . . . . .       L Near   07DB     MODEX_TEXT    \r
+@GPC_NEXT_LINE . . . . . . . . .       L Near   0889     MODEX_TEXT    \r
+@GPC_NO_LEFT0BITS  . . . . . . .       L Near   083C     MODEX_TEXT    \r
+@GPC_NO_LEFT1BITS  . . . . . . .       L Near   0831     MODEX_TEXT    \r
+@GPC_NO_MIDDLE0BITS  . . . . . .       L Near   085E     MODEX_TEXT    \r
+@GPC_NO_MIDDLE1BITS  . . . . . .       L Near   0853     MODEX_TEXT    \r
+@GPC_NO_RIGHT0BITS . . . . . . .       L Near   0888     MODEX_TEXT    \r
+@GPC_NO_RIGHT1BITS . . . . . . .       L Near   087D     MODEX_TEXT    \r
+@GPC_Set_Char  . . . . . . . . .       L Near   07E3     MODEX_TEXT    \r
+@Interface . . . . . . . . . . .       Number   0000h   \r
+@LDR_Load  . . . . . . . . . . .       L Near   0677     MODEX_TEXT    \r
+@Model . . . . . . . . . . . . .       Number   0004h   \r
+@PS_Exit . . . . . . . . . . . .       L Near   09AF     MODEX_TEXT    \r
+@PS_Print_It . . . . . . . . . .       L Near   097B     MODEX_TEXT    \r
+@SAP_Exit  . . . . . . . . . . .       L Near   06E1     MODEX_TEXT    \r
+@SDF_Set_Font  . . . . . . . . .       L Near   0A06     MODEX_TEXT    \r
+@SDP_Exit  . . . . . . . . . . .       L Near   0720     MODEX_TEXT    \r
+@SD_WAIT0  . . . . . . . . . . .       L Near   0798     MODEX_TEXT    \r
+@SD_WAIT1  . . . . . . . . . . .       L Near   079D     MODEX_TEXT    \r
+@SMX_Exit  . . . . . . . . . . .       L Near   027B     MODEX_TEXT    \r
+@STRLoop . . . . . . . . . . . .       L Near   05F4     MODEX_TEXT    \r
+@STRnc2  . . . . . . . . . . . .       L Near   0606     MODEX_TEXT    \r
+@STRnc3  . . . . . . . . . . . .       L Near   061A     MODEX_TEXT    \r
+@SVM_BadModeSetup  . . . . . . .       L Near   015C     MODEX_TEXT    \r
+@SVM_Continue  . . . . . . . . .       L Near   0161     MODEX_TEXT    \r
+@SVM_EXIT  . . . . . . . . . . .       L Near   0247     MODEX_TEXT    \r
+@SVM_Set_Data  . . . . . . . . .       L Near   01AA     MODEX_TEXT    \r
+@SVM_Set_Pages . . . . . . . . .       L Near   0207     MODEX_TEXT    \r
+@SVM_Setup_CRTC  . . . . . . . .       L Near   019D     MODEX_TEXT    \r
+@SVM_Setup_Table . . . . . . . .       L Near   0193     MODEX_TEXT    \r
+@SW_Exit . . . . . . . . . . . .       L Near   0789     MODEX_TEXT    \r
+@SW_WAIT0  . . . . . . . . . . .       L Near   0761     MODEX_TEXT    \r
+@SW_WAIT1  . . . . . . . . . . .       L Near   0776     MODEX_TEXT    \r
+@TB_COPY2  . . . . . . . . . . .       L Near   0B6A     MODEX_TEXT    \r
+@TB_COPY_LINE  . . . . . . . . .       L Near   0B26     MODEX_TEXT    \r
+@TB_COPY_LOOP  . . . . . . . . .       L Near   0B2E     MODEX_TEXT    \r
+@TB_COPY_PLANE . . . . . . . . .       L Near   0B1B     MODEX_TEXT    \r
+@TB_COPY_REMAINDER . . . . . . .       L Near   0B68     MODEX_TEXT    \r
+@TB_Exit . . . . . . . . . . . .       L Near   0BB0     MODEX_TEXT    \r
+@TB_NEXT2  . . . . . . . . . . .       L Near   0B87     MODEX_TEXT    \r
+@TB_NEXT_LINE  . . . . . . . . .       L Near   0B79     MODEX_TEXT    \r
+@TB_SKIP_01  . . . . . . . . . .       L Near   0B39     MODEX_TEXT    \r
+@TB_SKIP_02  . . . . . . . . . .       L Near   0B45     MODEX_TEXT    \r
+@TB_SKIP_03  . . . . . . . . . .       L Near   0B51     MODEX_TEXT    \r
+@TB_SKIP_04  . . . . . . . . . .       L Near   0B5D     MODEX_TEXT    \r
+@TB_SKIP_05  . . . . . . . . . .       L Near   0B75     MODEX_TEXT    \r
+@TGP_DECODE_CHAR_BYTE  . . . . .       L Near   090D     MODEX_TEXT    \r
+@TGP_EXIT  . . . . . . . . . . .       L Near   096B     MODEX_TEXT    \r
+@TGP_LowChar . . . . . . . . . .       L Near   08D9     MODEX_TEXT    \r
+@TGP_NEXT_LINE . . . . . . . . .       L Near   095E     MODEX_TEXT    \r
+@TGP_NO_LEFT1BITS  . . . . . . .       L Near   092D     MODEX_TEXT    \r
+@TGP_NO_MIDDLE1BITS  . . . . . .       L Near   0941     MODEX_TEXT    \r
+@TGP_NO_RIGHT1BITS . . . . . . .       L Near   095D     MODEX_TEXT    \r
+@TGP_Set_Char  . . . . . . . . .       L Near   08E1     MODEX_TEXT    \r
+@TPS_Exit  . . . . . . . . . . .       L Near   09EC     MODEX_TEXT    \r
+@TPS_Print_It  . . . . . . . . .       L Near   09BC     MODEX_TEXT    \r
+@code  . . . . . . . . . . . . .       Text     MODEX_TEXT\r
+@data  . . . . . . . . . . . . .       Text     DGROUP\r
+@fardata?  . . . . . . . . . . .       Text     FAR_BSS\r
+@fardata . . . . . . . . . . . .       Text     FAR_DATA\r
+@stack . . . . . . . . . . . . .       Text     DGROUP\r
+ACTIVE_PAGE  . . . . . . . . . .       Word     0012     _BSS  \r
+ALL_PLANES_ON  . . . . . . . . .       Number   0F02h   \r
+ALL_PLANES . . . . . . . . . . .       Number   000Fh   \r
+ASYNC_RESET  . . . . . . . . . .       Number   0100h   \r
+ATTRIB_Ctrl  . . . . . . . . . .       Number   03C0h   \r
+CHAIN4_OFF . . . . . . . . . . .       Number   0604h   \r
+CHARSET_HI . . . . . . . . . . .       Word     0026     _BSS  \r
+CHARSET_LOW  . . . . . . . . . .       Word     0022     _BSS  \r
+CHAR_BITS  . . . . . . . . . . .       Number   000Fh   \r
+CRTC_Data  . . . . . . . . . . .       Number   03D5h   \r
+CRTC_Index . . . . . . . . . . .       Number   03D4h   \r
+CURRENT_MOFFSET  . . . . . . . .       Word     001C     _BSS  \r
+CURRENT_PAGE . . . . . . . . . .       Word     0014     _BSS  \r
+CURRENT_SEGMENT  . . . . . . . .       Word     0016     _BSS  \r
+CURRENT_XOFFSET  . . . . . . . .       Word     0018     _BSS  \r
+CURRENT_YOFFSET  . . . . . . . .       Word     001A     _BSS  \r
+Char_Plane_Data  . . . . . . . .       Byte     0008     MODEX_TEXT    \r
+DAC_READ_ADDR  . . . . . . . . .       Number   03C7h   \r
+DAC_WRITE_ADDR . . . . . . . . .       Number   03C8h   \r
+DISPLAY_PAGE . . . . . . . . . .       Word     0010     _BSS  \r
+False  . . . . . . . . . . . . .       Number   0000h   \r
+GC_Index . . . . . . . . . . . .       Number   03CEh   \r
+GET_CHAR_PTR . . . . . . . . . .       Number   1130h   \r
+INPUT_1  . . . . . . . . . . . .       Number   03DAh   \r
+LAST_PAGE  . . . . . . . . . . .       Word     0004     _BSS  \r
+LATCHES_OFF  . . . . . . . . . .       Number   FF08h   \r
+LATCHES_ON . . . . . . . . . . .       Number   0008h   \r
+Left_Clip_Mask . . . . . . . . .       Byte     0000     MODEX_TEXT    \r
+MAP_MASK_PLANE1  . . . . . . . .       Number   0102h   \r
+MAP_MASK_PLANE2  . . . . . . . .       Number   1102h   \r
+MAP_MASK . . . . . . . . . . . .       Number   0002h   \r
+MAX_XOFFSET  . . . . . . . . . .       Word     001E     _BSS  \r
+MAX_YOFFSET  . . . . . . . . . .       Word     0020     _BSS  \r
+MISC_OUTPUT  . . . . . . . . . .       Number   03C2h   \r
+MODE_200_Tall  . . . . . . . . .       L Near   0044     MODEX_TEXT    \r
+MODE_240_Tall  . . . . . . . . .       L Near   0054     MODEX_TEXT    \r
+MODE_320_Wide  . . . . . . . . .       L Near   0028     MODEX_TEXT    \r
+MODE_320x200 . . . . . . . . . .       L Near   0074     MODEX_TEXT    \r
+MODE_320x240 . . . . . . . . . .       L Near   00BC     MODEX_TEXT    \r
+MODE_320x400 . . . . . . . . . .       L Near   0086     MODEX_TEXT    \r
+MODE_320x480 . . . . . . . . . .       L Near   00CE     MODEX_TEXT    \r
+MODE_360_Wide  . . . . . . . . .       L Near   0036     MODEX_TEXT    \r
+MODE_360x200 . . . . . . . . . .       L Near   00E0     MODEX_TEXT    \r
+MODE_360x240 . . . . . . . . . .       L Near   0098     MODEX_TEXT    \r
+MODE_360x400 . . . . . . . . . .       L Near   00F2     MODEX_TEXT    \r
+MODE_360x480 . . . . . . . . . .       L Near   00AA     MODEX_TEXT    \r
+MODE_400_Tall  . . . . . . . . .       L Near   0044     MODEX_TEXT    \r
+MODE_480_Tall  . . . . . . . . .       L Near   0054     MODEX_TEXT    \r
+MODE_Double_Line . . . . . . . .       L Near   0020     MODEX_TEXT    \r
+MODE_Single_Line . . . . . . . .       L Near   0018     MODEX_TEXT    \r
+MODE_TABLE . . . . . . . . . . .       L Near   0064     MODEX_TEXT    \r
+NUM_MODES  . . . . . . . . . . .       Number   0008h   \r
+PAGE_ADDR  . . . . . . . . . . .       Word     0006     _BSS  \r
+PAGE_SIZE  . . . . . . . . . . .       Word     000E     _BSS  \r
+PEL_DATA_REG . . . . . . . . . .       Number   03C9h   \r
+PIXEL_PAN_REG  . . . . . . . . .       Number   0033h   \r
+PLANE_BITS . . . . . . . . . . .       Number   0003h   \r
+READ_MAP . . . . . . . . . . . .       Number   0004h   \r
+ROM_8x8_Hi . . . . . . . . . . .       Number   0004h   \r
+ROM_8x8_Lo . . . . . . . . . . .       Number   0003h   \r
+Right_Clip_Mask  . . . . . . . .       Byte     0004     MODEX_TEXT    \r
+SCREEN_HEIGHT  . . . . . . . . .       Word     0002     _BSS  \r
+SCREEN_WIDTH . . . . . . . . . .       Word     0000     _BSS  \r
+SC_Data  . . . . . . . . . . . .       Number   03C5h   \r
+SC_Index . . . . . . . . . . . .       Number   03C4h   \r
+SEQU_RESTART . . . . . . . . . .       Number   0300h   \r
+START_DISP_HI  . . . . . . . . .       Number   000Ch   \r
+START_DISP_LO  . . . . . . . . .       Number   000Dh   \r
+True . . . . . . . . . . . . . .       Number   -0001h   \r
+VERT_RETRACE . . . . . . . . . .       Number   0008h   \r
+VGA_Segment  . . . . . . . . . .       Number   A000h   \r
+b  . . . . . . . . . . . . . . .       Text     BYTE PTR\r
+d  . . . . . . . . . . . . . . .       Text     DWORD PTR\r
+f  . . . . . . . . . . . . . . .       Text     FAR PTR\r
+nil  . . . . . . . . . . . . . .       Number   0000h   \r
+o  . . . . . . . . . . . . . . .       Text     OFFSET\r
+s  . . . . . . . . . . . . . . .       Text     SHORT\r
+w  . . . . . . . . . . . . . . .       Text     WORD PTR\r
+\r
+          0 Warnings\r
+          0 Errors\r
diff --git a/src/lib/modex/modex.sbr b/src/lib/modex/modex.sbr
new file mode 100755 (executable)
index 0000000..4da653b
Binary files /dev/null and b/src/lib/modex/modex.sbr differ
diff --git a/src/lib/modex/modex105.zip b/src/lib/modex/modex105.zip
new file mode 100755 (executable)
index 0000000..9457bd9
Binary files /dev/null and b/src/lib/modex/modex105.zip differ
diff --git a/src/lib/modex/packing.lst b/src/lib/modex/packing.lst
new file mode 100755 (executable)
index 0000000..88f817c
--- /dev/null
@@ -0,0 +1,87 @@
+\r
+PACKING LIST FOR MODEX104\r
+\r
+DIRECTORY: \               - The Mode X Library versoon 1.04 \r
+\r
+ASM      BAT        26 05-14-93   6:00p - Batch File to Assemble MODEX.ASM\r
+MODE-X   TXT      2135 05-14-93   6:00p - File Describing MODE X Routines\r
+MODEX    ASM    117039 05-14-93   6:00p - Assembly source to Mode X Library\r
+MODEX    BI       3238 05-14-93   6:00p - Include File for BASIC/PDS\r
+MODEX    H        2943 05-14-93   6:00p - Include File for C/C++\r
+MODEX    OBJ      5208 05-14-93   6:00p - The Mode X Library\r
+README   DOC      3259 05-14-93   6:00p - Information on this Product\r
+PACKING  LST      4767 05-14-93   6:00p - This File\r
+\r
+DIRECTORY: \DEMOS          - Mode X Demos\r
+\r
+CHARDEMO EXE     13066 05-14-93   6:00p - Demo of Multiple Fonts & Color Cycling\r
+TEST6    EXE     19990 05-14-93   6:00p - Main Mode X Demo\r
+ROM_8X8  FNT      1024 05-14-93   6:00p - Font for CHARDEMO.EXE\r
+SPACEAGE FNT      1024 05-14-93   6:00p - Font for CHARDEMO.EXE\r
+SYSTEM   FNT      1024 05-14-93   6:00p - Font for CHARDEMO.EXE\r
+\r
+DIRECTORY: \DEMOS\BASIC7   - Demo Sources for Microsoft BASIC 7.1 (PDS)\r
+\r
+MAKE-LIB BAT       166 05-14-93   6:00p - Batch File to make MODEX.LIB/.QLB\r
+MODEX    BI       3238 05-14-93   6:00p - Include File for MODE X Library\r
+MODEX    LIB      7189 05-14-93   6:00p - Mode X & Utility Libraries for QBX\r
+MODEX    OBJ      5208 05-14-93   6:00p - Mode X Library - Object File\r
+MODEX    QLB     11141 05-14-93   6:00p - Mode X & Utility Quick Library\r
+TEST6    BAS     12733 05-14-93   6:00p - Main Demo Source Code (TEST6.EXE)\r
+UASM-BC7 BAT        43 05-14-93   6:00p - Batch file to Make UTILS.OBJ for QBX\r
+UTILS    ASM      8506 05-14-93   6:00p - Basic Utilities - Assembler source\r
+UTILS    BI       2028 05-14-93   6:00p - Basic Utilities - Basic Includes\r
+UTILS    OBJ       681 05-14-93   6:00p - Basic Utilities - Object File\r
+CHARDEMO BAS      3431 05-14-93   6:00p - Source to CHARDEMO.EXE\r
+\r
+DIRECTORY: \DEMOS\C        - Demo Sources for Borland C/C++\r
+\r
+C_UTILS  ASM      8782 05-14-93   6:00p - C Utilities - Assembler source\r
+C_UTILS  H        2623 05-14-93   6:00p - C Utilities - C Includes\r
+C_UTILS  OBJ       648 05-14-93   6:00p - C Utilities - Object File\r
+MODEX    H        2943 05-14-93   6:00p - Mode X Library C Incldues\r
+MODEX    OBJ      5208 05-14-93   6:00p - Mode X Library\r
+UTLS-ASM BAT        36 05-14-93   6:00p - Batch File to Make C_UTILS.OBJ\r
+X-DEMO   C       15085 05-14-93   6:00p - Source to Main Demo (TEST6) in C\r
+X-DEMO   EXE     41090 05-14-93   6:00p - C Version of Main Demo\r
+X-DEMO   PRJ      5188 05-14-93   6:00p - Borland C Project file\r
+\r
+DIRECTORY: \DEMOS\PASCAL  - Demo Sources for Turbo Pascal\r
+\r
+TEST5    PAS     15873 05-14-93   6:00p - Source for a TP Version of TEST6.EXE\r
+\r
+DIRECTORY: \DEMOS\QB45    - Demo Sources for Microsoft QuickBASIC 4.5\r
+\r
+MAKE-LIB BAT       164 05-14-93   6:00p - Batch File to make MODEX.LIB/.QLB\r
+MODEX    BI       3238 05-14-93   6:00p - Include File for MODE X Library\r
+MODEX    LIB      7189 05-14-93   6:00p - Mode X & Utility Libraries for QB45\r
+MODEX    OBJ      5208 05-14-93   6:00p - Mode X Library - Object File\r
+MODEX    QLB      9739 05-14-93   6:00p - Mode X & Utility Quick Library/QB45\r
+TEST6A   BAS     12743 05-14-93   6:00p - Main Demo Source Code (TEST6.EXE)\r
+TEST6A   EXE     40544 05-14-93   6:00p - QB45 Version of Main Demo\r
+UASM-QB4 BAT        30 05-14-93   6:00p - Batch file to Make UTILS.OBJ for QB45\r
+UTILS    ASM      8506 05-14-93   6:00p - Basic Utilities - Assembler source\r
+UTILS    BI       2028 05-14-93   6:00p - Basic Utilities - Basic Includes\r
+UTILS    OBJ       628 05-14-93   6:00p - Basic Utilities - Object File\r
+\r
+DIRECTORY: \FONTEDIT      - Font Editor\r
+\r
+CSEDIT   EXE     39242 05-14-93   6:00p - Font Editor Program\r
+CSEDIT   DOC      8629 05-14-93   6:00p - Font Editor Documentation\r
+CHARSETS CS       2144 05-14-93   6:00p - Internal Fonts for Editor\r
+MOUSEIMG CS        128 05-14-93   6:00p - Mouse Pointers for Editor\r
+PALETTE  CS        768 05-14-93   6:00p - Palette for Editor\r
+INVERSE  FNT      1024 05-14-93   6:00p - Sample Font\r
+ROM_8X8  FNT      1024 05-14-93   6:00p - Sample Font\r
+SPACEAGE FNT      1024 05-14-93   6:00p - Sample Font\r
+SYSTEM   FNT      1024 05-14-93   6:00p - Sample Font\r
+\r
+DIRECTORY: \PALEDIT       - Palette Editor\r
+\r
+PALEDIT  EXE     31954 05-14-93   6:00p - Palette Editor Program\r
+PALEDIT  DOC      6688 05-14-93   6:00p - Palette Editor Documentation\r
+CHARSETS CS       2144 05-14-93   6:00p - Internal Fonts for Editor\r
+MOUSEIMG CS        128 05-14-93   6:00p - Mouse Pointers for Editor\r
+GAMECOLR PAL       768 05-14-93   6:00p - Sample Palette\r
+PRIME    PAL       768 05-14-93   6:00p - Sample Palette\r
+RGB      PAL       768 05-14-93   6:00p - Sample Palette\r
diff --git a/src/lib/modex/paledit/bakapi.pal b/src/lib/modex/paledit/bakapi.pal
new file mode 100755 (executable)
index 0000000..d4d4a6a
Binary files /dev/null and b/src/lib/modex/paledit/bakapi.pal differ
diff --git a/src/lib/modex/paledit/charsets.cs b/src/lib/modex/paledit/charsets.cs
new file mode 100755 (executable)
index 0000000..97fe608
Binary files /dev/null and b/src/lib/modex/paledit/charsets.cs differ
diff --git a/src/lib/modex/paledit/diagonal.pal b/src/lib/modex/paledit/diagonal.pal
new file mode 100755 (executable)
index 0000000..5dee196
Binary files /dev/null and b/src/lib/modex/paledit/diagonal.pal differ
diff --git a/src/lib/modex/paledit/gamecolr.pal b/src/lib/modex/paledit/gamecolr.pal
new file mode 100755 (executable)
index 0000000..621b1e5
Binary files /dev/null and b/src/lib/modex/paledit/gamecolr.pal differ
diff --git a/src/lib/modex/paledit/mouseimg.cs b/src/lib/modex/paledit/mouseimg.cs
new file mode 100755 (executable)
index 0000000..101e208
Binary files /dev/null and b/src/lib/modex/paledit/mouseimg.cs differ
diff --git a/src/lib/modex/paledit/paledit.doc b/src/lib/modex/paledit/paledit.doc
new file mode 100755 (executable)
index 0000000..61d0b2e
--- /dev/null
@@ -0,0 +1,166 @@
\r
+PALEDIT - A Simple VGA 256 Color Palette Editor\r
\r
\r
+PALEDIT is distributed with MODEXnnn.ZIP, the general purpose MODE X\r
+Library for VGA Graphics.\r
\r
+WHAT YOU NEED TO RUN PALEDIT:\r
\r
+    * A Vga Monitor\r
+    * A Microsoft Compatible Mouse\r
\r
+    A Mouse is most definitely required, as the keyboard is used for\r
+    nothing except entering file names.\r
\r
+FILES NEEDED IN THE CURRENT DIRECTORY:\r
\r
+    PALEDIT.EXE  - The Palette Editor Program\r
+    CHARSETS.CS  - The Palette Editor's Internal Fonts\r
+    MOUSEIMG.CS  - The Palette Editor's Mouse Pointer\r
\r
+SAMPLE PALETTE FILE THAT SHOULD BE INCLUDED:\r
\r
+     RGB.PAL   - A Simple Palette with Reds, Greens, and Blues\r
+     PRIME.PAL    - A Simple Palette\r
+     GAMECOLR.PAL - A Bright Palette from a Game of mine.\r
\r
+WHAT IT EDITS:\r
\r
+     The VGA DAC Registers, all 256 of them.\r
\r
+HOW IT WORKS/FEATURES:\r
\r
+    PALEDIT allows the user to see the entire VGA Palette of 256 colors\r
+    and select and modify the RED, GREEN, and BLUE values of any individual\r
+    color (DAC) register.  The entire group of 256 colors can be saved to\r
+    a disk file for later retrieval.\r
\r
+    Individual "SLIDERS" show the current RED, GREEN, and BLUE color\r
+    components of the current color and allow them to be changed.\r
\r
+    The Following operations can be performed.\r
\r
+    * Raise, Lower, and set the RED, GREEN, or BLUE components.\r
+    * Copy the current RGB values to another Color (DAC) Register\r
+    * Brighten the selected color\r
+    * Darken and selected color\r
+    * Reset the selected color to its original state\r
+    * Blend an entire range of colors, creating a smooth\r
+      Transition from one color to another\r
+    * Optionally Lock out the first 16 colors to prevent\r
+      Accidental Modification\r
\r
+DESCRIPTION OF OBJECTS/FEATURES FROM THE TOP DOWN:\r
\r
+    COLOR SLIDERS:  In the upper left of the screen there are\r
+        Three Rectangular Boxes: One for each primary color:\r
+        RED, GREEN, and BLUE.  Each Box has an arrow at each\r
+        end, and a scale bar in the middle, connecting the two\r
+        arrows.  The scale bar is much like a thermometer,\r
+        indicating how much of that color is in the selected\r
+        color.  To the right of each Box, the name of the color\r
+        is indicated, along with the content color in the form\r
+        of a number from 0 to 63; where 0 means none of that\r
+        color goes into making the selected color, and 63 means\r
+        that the selected color is saturated with that color.\r
\r
+        Clicking the mouse on the slider's left arrow box will\r
+        decrease the amount of that primary color in the selected\r
+        color.  Holding the mouse button down will reduce the\r
+        color value all the way to 0.\r
\r
+        Clicking the mouse on the slider's right arrow box will\r
+        increase the amount of that primary color in the selected\r
+        color.  Holding the mouse button down will increase the\r
+        color value all the way to 63.\r
\r
+        Clicking the mouse on the scale bar will set the amount\r
+        of that primary color to the value the represents that\r
+        position on the slider.\r
\r
+    LOCK Button:  Clicking the button toggles the lockout of the\r
+        first 16 colors.  When they are locked out, they can not\r
+        be modified, and when selected the word "LOCKED" will\r
+        appear below the color # on the Color Information Display.\r
\r
+    LOAD Button:  Clicking this button will load the Palette file\r
+        that is named in the Palette File name box.  If no name is\r
+        given or no such file exists, then nothing will be loaded.\r
\r
+    SAVE Button: Clicking this button will save the current Palette\r
+        in a file using the name given in the Palette File Name Box.\r
+        If a Valid name is not provided, nothing will be saved.\r
\r
+    QUIT Button: Clicking this button will return you to DOS.\r
+        Nothing is saved, and no confirmation is given.\r
\r
\r
+    Color Information Display:  This Box is on the left side of the\r
+        Screen, below the Color Sliders.  It shows the number of the\r
+        currently selected color (from 0 to 255) and indicates if\r
+        that color is locked.  To the right of this box is a big\r
+        square showing the current color.\r
\r
+    LIGHTER Button:  Clicking this button will make the selected\r
+        color brighter.\r
\r
+    DARKER Button:  Clicking this button will make the selected\r
+        color darker.\r
\r
+    RESET Button:  Clicking this button will restore the selected\r
+        color to the value it had when it was first selected.\r
\r
+    BLEND Button:  Clicking this button will let you Blend a range\r
+        of colors together.  One end of the range of colors is the\r
+        currently selected color.  After Clicking the BLEND button.\r
+        You must click on the color at the other end of the range\r
+        in the Palette Display Box.  All of the colors in between\r
+        those two colors will be changed to represent a gradual\r
+        transition from the color at one end to the color at the\r
+        other end.\r
\r
+    PALETTE FILE NAME BOX:  This Text Box is used to enter the name\r
+        of a Palette file to load or the name to save the current\r
+        Palette as.  Just click on the Box, and it will change color\r
+        and a flashing cursor will appear.  Now you type in a filename\r
+        or edit the existing filename.  Press <RETURN> or click\r
+        outside the text box to end editing.\r
\r
+    PALETTE DISPLAY BOX:  This Box shows all 256 colors in an array\r
+        of 32 by 8 color blocks.  The Currently Selected Color will\r
+        have a Box around it.  Clicking on a color with the Left\r
+        Mouse button will make that color the new currently selected\r
+        color.  Clicking on a color with the Right Mouse Button will\r
+        copy the color value from the old selected color to it, before\r
+        it is made the new selected color.\r
\r
+    Message Bar:  At the very bottom of the screen, this Bar will display\r
+        information and messages for various functions.\r
\r
+PALETTE FILE FORMAT:\r
\r
+     BINARY image, in order of VGA DAC (Color) Number.  3 Bytes Per\r
+     Color, 256 Colors.  768 Bytes total.  The Files will be exactly\r
+     768 bytes in size.\r
\r
+    COLOR:\r
+        RED:    1 BYTE\r
+        GREEN: 1 BYTE\r
+        BLUE:   1 BYTE\r
\r
+    PALETTE:  Array (0 to 255) of COLOR\r
\r
+COMMENTS, QUESTIONS, BUG REPORTS, etc:\r
\r
+    Send the to the Author:  Matt Pritchard\r
\r
+    Through the 80xxx Fidonet Echo or\r
\r
+    Matt Pritchard\r
+    P.O. Box 140264\r
+    Irving, TX  75014\r
\r
+CREDITS:\r
\r
+    This Palette Editor was written in QuickBASIC 4.5\r
diff --git a/src/lib/modex/paledit/paledit.exe b/src/lib/modex/paledit/paledit.exe
new file mode 100755 (executable)
index 0000000..f69e172
Binary files /dev/null and b/src/lib/modex/paledit/paledit.exe differ
diff --git a/src/lib/modex/paledit/palview.exe b/src/lib/modex/paledit/palview.exe
new file mode 100755 (executable)
index 0000000..4c721d3
Binary files /dev/null and b/src/lib/modex/paledit/palview.exe differ
diff --git a/src/lib/modex/paledit/prime.pal b/src/lib/modex/paledit/prime.pal
new file mode 100755 (executable)
index 0000000..310ca6e
Binary files /dev/null and b/src/lib/modex/paledit/prime.pal differ
diff --git a/src/lib/modex/paledit/rgb.pal b/src/lib/modex/paledit/rgb.pal
new file mode 100755 (executable)
index 0000000..bc03425
Binary files /dev/null and b/src/lib/modex/paledit/rgb.pal differ
diff --git a/src/lib/modex/paledit/scroll.pal b/src/lib/modex/paledit/scroll.pal
new file mode 100755 (executable)
index 0000000..5dee196
Binary files /dev/null and b/src/lib/modex/paledit/scroll.pal differ
diff --git a/src/lib/modex/readme.doc b/src/lib/modex/readme.doc
new file mode 100755 (executable)
index 0000000..63a9053
--- /dev/null
@@ -0,0 +1,76 @@
+\r
+=========================================================================\r
+  þ   þ   þþþþþ   þþþþ    þþþþþ      þ   þ       þ        þþþþþ   þ   þ   \r
+  þþ þþ   þ   þ   þ   þ   þ           þ þ       þþ        þ   þ   þ   þ\r
+  þ þ þ   þ   þ   þ   þ   þþþþ         þ         þ        þ þ þ   þþþþþ\r
+  þ   þ   þ   þ   þ   þ   þ           þ þ        þ        þ   þ       þ\r
+  þ   þ   þþþþþ   þþþþ    þþþþþ      þ   þ     þþþþþ  þþ  þþþþþ       þ\r
+=========================================================================\r
+                               MODE X  1.04\r
+=========================================================================\r
+     Library & Editors by Matt Pritchard:  Release 1.04 on 14 Mar 93\r
+=========================================================================\r
+\r
+MODEX104 is a library of high performance assembler routines for setting,\r
+accessing, and manipulating the Undocumented 256 Color Modes available in\r
+all VGA adaptors.\r
+\r
+MODEX104 includes the following elements:\r
+\r
+    MODE X Library - A library of MODE X routines written in assembly.\r
+\r
+    FONT EDITOR - An editor for creating and modifying fonts for use by\r
+                  The MODE X Library.\r
+\r
+    PALETTE EDITOR - An editor for creating and modifying palettes for\r
+                     use in VGA 256 Color modes.\r
+\r
+    MODE X Demos  - Programs that show off the various features of the\r
+                    MODE X Library\r
+\r
+    MODE X Demo Source - The Full source code for the MODE X Demos for \r
+                         the following Languages:  Microsoft QuickBASIC 4.5,\r
+                         Microsoft BASIC 7.1 PDS, Borland C/C++ 3.1,\r
+                         and Borland Turbo Pascal.\r
+\r
+THE LEGAL STUFF:\r
+\r
+    The Mode X Library has been placed into the Public Domain by the\r
+    Author (Matt Pritchard).  The Font Editor and Palette Editor are also\r
+    placed into the Public Domain by the Author (Matt Pritchard).  The\r
+    Source Code to the above editors is not in the Public Domain.\r
+\r
+    The Mode X Demos and the Mode X Demo Sources have been placed into the\r
+    Public domain by the Author (Matt Pritchard).\r
+\r
+    The Mode X Library may be used freely in any non commerical product.\r
+    It would be nice if the author was credited for the contribution, \r
+    but it is not necessary.  No $$$ involved.\r
+    \r
+    The Mode X Library may be used freely in a commercial product, *IF*\r
+    the author (Matt Pritchard) is credited for the contribution.  That's\r
+    it.  No $$$ involved.\r
+\r
+    The Mode X Library should not be re-sold or modified and re-sold.\r
+    No fee in excess of $5 should be charged for duplication of this\r
+    Library.\r
+\r
+CONTRIBUTORS:    The following people have contributed to this effort.\r
+\r
+    Michael Abrash   - He told us all how to do it in the first place.\r
+    Scott Wyatt      - He ported the Main Demo code to Turbo Pascal.\r
+\r
+THE AUTHOR:\r
+\r
+    The author of MODEX104 is Matt Pritchard.\r
+    All Questions and correspondance can be directed to:\r
+\r
+    "Matt Pritchard" on Fido Net ECHO Conference: 80xxx\r
+\r
+    or mailed to:  Matt Pritchard\r
+                   P.O. Box 140264\r
+                   Irving, TX  75014-0264\r
+\r
+    Questions, Inquiries, Comments, Donations, etc are quite welcome.\r
+\r
+\r
diff --git a/src/lib/modex/utls-asm.bat b/src/lib/modex/utls-asm.bat
new file mode 100755 (executable)
index 0000000..d996978
--- /dev/null
@@ -0,0 +1 @@
+MASM c_utils, c_utils, c_utils, nul;
\ No newline at end of file
diff --git a/src/lib/modex/w.sh b/src/lib/modex/w.sh
new file mode 100755 (executable)
index 0000000..4483916
--- /dev/null
@@ -0,0 +1,3 @@
+#! /bin/bash
+wmake clean;wmake
+cp x_demo.exe ../../../
diff --git a/src/lib/modex/x.exe b/src/lib/modex/x.exe
new file mode 100755 (executable)
index 0000000..7742d14
Binary files /dev/null and b/src/lib/modex/x.exe differ
diff --git a/src/lib/modex/x_demo.c b/src/lib/modex/x_demo.c
new file mode 100755 (executable)
index 0000000..dfe9a3e
--- /dev/null
@@ -0,0 +1,786 @@
+/* X-DEMO.C - a Mode "X" Demo      */\r
+/* By Matt Pritchard, 14 Apr, 1993 */\r
+\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+\r
+#include "modex.h"\r
+#include "c_utils.h"\r
+\r
+#define MAX_SHAPES  32\r
+#define MAX_SPRITES 64\r
+\r
+       /* routines in this file */\r
+\r
+void demo_res (int, int, int);\r
+int  get_key (void);\r
+void error_out (char*);\r
+void load_shapes (void);\r
+int  int_sqrt (int, int);\r
+void page_demo (void);\r
+\r
+       /* Structures for Sprites */\r
+\r
+struct Shape\r
+{\r
+       unsigned char Image[512];\r
+       int           X_Width;\r
+       int                       Y_Width;\r
+}   Img [MAX_SHAPES];\r
+\r
+struct Sprite\r
+{\r
+       int     X_pos;\r
+       int     Y_pos;\r
+       int X_Dir;\r
+       int Y_Dir;\r
+       int     Shape;\r
+       int     Last_X [2];\r
+       int Last_Y [2];\r
+}   Obj [MAX_SPRITES];\r
+\r
+\r
+       /* MAIN */\r
+\r
+\r
+int main(int argc, char *argv[])\r
+{\r
+\r
+   /*  if (argc > 0)\r
+       {\r
+               while (argc > 0)\r
+               {\r
+                       dos_print ("Unknown Argument: ");\r
+                       dos_print (makefp argv[argc]);\r
+                       argc--;\r
+               }\r
+               return (0);\r
+\r
+       }\r
+        */\r
+\r
+       init_random ();\r
+\r
+       load_shapes ();\r
+\r
+       demo_res ( Mode_320x200, 320, 200 );\r
+       demo_res ( Mode_320x400, 320, 400 );\r
+\r
+       demo_res ( Mode_360x200, 360, 200 );\r
+       demo_res ( Mode_360x400, 360, 400 );\r
+\r
+       demo_res ( Mode_320x240, 320, 240 );\r
+       demo_res ( Mode_320x480, 320, 480 );\r
+\r
+       demo_res ( Mode_360x240, 360, 240 );\r
+       demo_res ( Mode_360x480, 360, 480 );\r
+\r
+       page_demo ();\r
+\r
+       set_video_mode (3);\r
+       dos_print ("This Mode X Demo is Finished");\r
+       return (0);\r
+\r
+}\r
+\r
+\r
+       /* Demonstrate a given resolution */\r
+\r
+\r
+void demo_res (int Screen_Mode, int X_max, int Y_max)\r
+{\r
+\r
+char   *Error1 = "Failure while calling SET_MODEX";\r
+char   *Error2 = "Failure during READ_PIXEL test";\r
+\r
+char   *Abort_Msg = "Demo aborted by User";\r
+\r
+char   *Demo_Msg = " This is a MODE X demo ";\r
+char   *Scrn_Msg = "Screen Resolution is     by    ";\r
+char   *Cont_Msg = "Press <ANY KEY> to Continue";\r
+\r
+char    *Line_Msg = "LINE TEST";\r
+char   *Fill_Msg = "FILL TEST";\r
+char   *Pixel_Msg = "PIXEL TEST";\r
+\r
+char   Text[10];\r
+\r
+int            x1, y1, x2, y2 = 0;\r
+int            x, y, z = 0;\r
+int            X_Center, gap = 0;\r
+\r
+\r
+       if (set_modex (Screen_Mode) == 0)\r
+       {\r
+               error_out (Error1);\r
+       }\r
+\r
+       X_Center = X_max / 2;\r
+\r
+       x1 = 10;\r
+       y1 = 10;\r
+       x2 = X_max - 1;\r
+       y2 = Y_max - 1;\r
+\r
+       for (z = 0; z <= 3; z++)\r
+       {\r
+               y = 31 - z -z;\r
+               draw_line (x1+z, y1+z, x2-z, y1+z, y);\r
+               draw_line (x1+z, y1+z, x1+z, y2-z, y);\r
+               draw_line (x1+z, y2-z, x2-z, y2-z, y);\r
+               draw_line (x2-z, y1+z, x2-z, y2-z, y);\r
+       }\r
+\r
+       for (x = 0; x < (X_max / 10); x++)\r
+       {\r
+               tgprintc (48 + ((x+1) % 10), x*10+1, 1, 9 + ((x/8) % 7) );\r
+               draw_line (x*10+9, 0, x*10+9, 3, c_bWHITE);\r
+       }\r
+\r
+       for (y = 0; y < (Y_max / 10); y++)\r
+       {\r
+               tgprintc (48 + ((y+1) % 10), 1, y*10+1, 9 + ((y/10) % 7) );\r
+               draw_line (0, y*10+9, 3, y*10+9, c_bWHITE);\r
+       }\r
+\r
+       for (x = 0; x <= 63; x++)\r
+       {\r
+               z = 15 + (x * 3 / 4);\r
+               set_dac_register (64+x, z, z, z);\r
+               set_dac_register (128+x, 0, z, z);\r
+\r
+               draw_line (103-x, 60, 40+x, 123, 64+x);\r
+               draw_line (40, 60+x, 103, 123-x, 128+x);\r
+\r
+       }\r
+\r
+       tprint_str (Line_Msg, 9, 37, 130, c_BLUE);\r
+\r
+       y = 60;\r
+       gap = 0;\r
+       for (x = 0; x <= 9; x++)\r
+       {\r
+               fill_block (120, y, 120+x, y+gap, 64+x);\r
+               fill_block (140 - (15-x), y, 150+x, y+gap, 230+x);\r
+               fill_block (170 - (15-x), y, 170, y+gap, 128+x);\r
+               y = y + gap + 2;\r
+               gap++;\r
+       }\r
+\r
+       tprint_str (Fill_Msg, 9, 110, 46, c_GREEN);\r
+\r
+       for (x = 190; x <= 250; x+=2)\r
+       {\r
+               for (y = 60; y <= 122; y+=2)\r
+               {\r
+                       z = (x+x+y+y) & 0xff;\r
+                       set_point (x, y, z);\r
+               }\r
+       }\r
+\r
+       tprint_str (Pixel_Msg, 10, 182, 130, c_RED);\r
+\r
+       for (x = 190; x <= 250; x+=2)\r
+       {\r
+               for (y = 60; y <= 122; y+=2)\r
+               {\r
+                       z = (x+x+y+y) & 0xff;\r
+                       if (read_point(x, y) != z)\r
+                       {\r
+                               error_out (Error2);\r
+                       }\r
+               }\r
+       }\r
+\r
+       print_str (Demo_Msg, 23, X_Center - 92, 20, c_bRED, c_BLUE);\r
+\r
+       x = X_Center - 124;\r
+       print_str (Scrn_Msg, 28, x, 30, c_bGREEN, c_BLACK);\r
+\r
+       sprintf (Text, "%3d", X_max);\r
+       print_str (Text, 3, x+168, 30, c_bPURPLE, c_BLACK);\r
+\r
+       sprintf (Text, "%3d", Y_max);\r
+       print_str (Text, 3, x + 224, 30, c_bWHITE, c_BLACK);\r
+\r
+       for (x = 0; x <= 15; x++)\r
+       {\r
+               set_dac_register (230+x, 63-x*4, 0, 15+x*3);\r
+               draw_line (30+x, Y_max-6-x, X_max-20-x, Y_max-6-x, 230+x);\r
+       }\r
+\r
+       tprint_str (Cont_Msg, 27, X_Center - 103, Y_max-18, c_YELLOW);\r
+\r
+       if (get_key () == Ky_ESC)\r
+       {\r
+               error_out (Abort_Msg);\r
+       }\r
+\r
+       return ;\r
+\r
+}\r
+\r
+\r
+       /* Wait for a Keystroke */\r
+\r
+\r
+int get_key(void)\r
+{\r
+\r
+int    c = 0;\r
+\r
+       while (c == 0)\r
+       {\r
+               c = scan_keyboard ();\r
+       }\r
+\r
+       return (c);\r
+\r
+}\r
+\r
+\r
+       /* Error Handling Routine */\r
+\r
+\r
+void error_out (char * text)\r
+{\r
+\r
+       set_video_mode (3);\r
+       dos_print (text);\r
+       exit (EXIT_SUCCESS);\r
+\r
+}\r
+\r
+\r
+       /* Routine to generate random sprites */\r
+\r
+\r
+void load_shapes ()\r
+{\r
+\r
+unsigned char  Grid[33][33];\r
+\r
+char   *Error1 = "Bad Shape Selected Error";\r
+\r
+int            Shape;\r
+int            x, y, z;\r
+int            Style, Color;\r
+int            X_Width, Y_Width, Center, S_Width;\r
+int            Hollow_X, Hollow_Y;\r
+\r
+       for (Shape = 0; Shape < MAX_SHAPES; Shape++)\r
+       {\r
+               for (y = 0; y <= 32; y++)\r
+               {\r
+                       for (x = 0; x <= 32; x++)\r
+                       {\r
+                               Grid[x][y] = c_BLACK;\r
+                       }\r
+               }\r
+\r
+               Style = random_int (6);\r
+               Color = 1 + random_int (15);\r
+\r
+               switch (Style)\r
+\r
+               {\r
+                               /* SOLID BOXES */\r
+\r
+                       case 0:\r
+\r
+                       {\r
+                               do\r
+                               {\r
+                                       X_Width = 3 + random_int(30);\r
+                                       Y_Width = 3 + random_int(30);\r
+\r
+                               } while ( (X_Width * Y_Width) >= 512);\r
+\r
+                               for (x = 1; x <= X_Width; x++)\r
+                               {\r
+                                       for (y = 1; y <= Y_Width; y++)\r
+                                       {\r
+                                          Grid[x][y] = Color;\r
+                                       }\r
+                               }\r
+\r
+                               break;\r
+\r
+                       }\r
+                               /* HOLLOW BOXES */\r
+\r
+                       case 1:\r
+\r
+                       {\r
+                               do {\r
+                                       X_Width = 6 + random_int(27);\r
+                                       Y_Width = 6 + random_int(27);\r
+                               } while ( (X_Width * Y_Width) >= 512);\r
+\r
+                               for (y = 1; y <= Y_Width; y++)\r
+                               {\r
+                                       for (x = 1; x <= X_Width; x++)\r
+                                       {\r
+                                               Grid[x][y] = Color;\r
+                                       }\r
+                               }\r
+\r
+                               Hollow_X = 1 + random_int ((X_Width / 2) -1);\r
+                               Hollow_Y = 1 + random_int ((Y_Width / 2) -1);\r
+\r
+                               for (y = Hollow_Y+1; y <= Y_Width-Hollow_Y; y++)\r
+                               {\r
+                                       for (x = Hollow_X+1; x <= X_Width-Hollow_X; x++)\r
+                                       {\r
+                                               Grid[x][y] = c_BLACK;\r
+                                       }\r
+                               }\r
+\r
+                               break;\r
+\r
+                       }\r
+\r
+                               /* SOLID DIAMOND */\r
+\r
+                       case 2:\r
+\r
+                       {\r
+\r
+                               X_Width = 3 + 2 * random_int(10);\r
+                               Y_Width = X_Width;\r
+                               Center = X_Width / 2;\r
+\r
+                               for (y = 0; y <= Center; y++)\r
+                               {\r
+                                       for (x = 0; x <= y; x++)\r
+                                       {\r
+                                               Grid [Center-x+1][y+1] = Color;\r
+                                               Grid [Center+x+1][y+1] = Color;\r
+                                               Grid [Center-x+1][Y_Width-y] = Color;\r
+                                               Grid [Center+x+1][Y_Width-y] = Color;\r
+                                       }\r
+                               }\r
+\r
+                               break;\r
+\r
+                       }\r
+\r
+                               /* HOLLOW DIAMOND */\r
+\r
+                       case 3:\r
+\r
+                       {\r
+\r
+                               X_Width = 3 + 2 * random_int(10);\r
+                               Y_Width = X_Width;\r
+                               Center = X_Width / 2;\r
+                               S_Width = random_int (Center);\r
+\r
+                               for (y = 0; y <= Center; y++)\r
+                               {\r
+                                       for (x = 0; x <= y; x++)\r
+                                       {\r
+                                               if ( x+(Center-y) >= S_Width )\r
+                                               {\r
+                                                       Grid [Center-x+1][y+1] = Color;\r
+                                                       Grid [Center+x+1][y+1] = Color;\r
+                                                       Grid [Center-x+1][Y_Width-y] = Color;\r
+                                                       Grid [Center+x+1][Y_Width-y] = Color;\r
+                                               }\r
+                                       }\r
+                               }\r
+\r
+                               break;\r
+\r
+                       }\r
+\r
+                               /* BALL */\r
+\r
+                       case 4:\r
+\r
+                       {\r
+\r
+                               X_Width = 7 + 2 * random_int (8);\r
+                               Y_Width = X_Width;\r
+                               Center  = 1 + X_Width / 2;\r
+\r
+                               for (y = 1; y <= Y_Width; y++)\r
+                               {\r
+                                       for (x = 1; x <= X_Width; x++)\r
+                                       {\r
+                                               z = int_sqrt(Center-x, Center-y);\r
+                                               if (z < Center)\r
+                                               {\r
+                                                       Grid[x][y] = 150 + Color * 2 + z * 3;\r
+                                               }\r
+                                       }\r
+                               }\r
+\r
+                               break;\r
+                       }\r
+\r
+                               /* HOLLOW BALLS */\r
+\r
+                       case 5:\r
+\r
+                       {\r
+                               X_Width = 7 + 2 * random_int (8);\r
+                               Y_Width = X_Width;\r
+                               Center  = 1 + X_Width / 2;\r
+                               S_Width = random_int (X_Width);\r
+\r
+                               for (y = 1; y <= Y_Width; y++)\r
+                               {\r
+                                       for (x = 1; x <= X_Width; x++)\r
+                                       {\r
+                                               z = int_sqrt(Center-x, Center-y);\r
+                                               if ( (z < Center) && (z >= S_Width) )\r
+                                               {\r
+                                                       Grid[x][y] = 150 + Color * 2 + z * 3;\r
+                                               }\r
+                                       }\r
+                               }\r
+\r
+\r
+                               break;\r
+                       }\r
+\r
+                       default:\r
+\r
+                       {\r
+                               error_out (Error1);\r
+                               break;\r
+\r
+                       }\r
+\r
+               }\r
+\r
+               z = 0;\r
+               for (y = 1; y <= Y_Width; y++)\r
+               {\r
+                       for (x = 1; x <= X_Width; x++)\r
+                       {\r
+                               Img[Shape].Image[z] = Grid[x][y];\r
+                               z++;\r
+                       }\r
+               }\r
+\r
+               Img[Shape].X_Width = X_Width;\r
+               Img[Shape].Y_Width = Y_Width;\r
+\r
+       }\r
+\r
+       return;\r
+}\r
+\r
+\r
+       /* Quickie Psuedo Integer Square Root Routine */\r
+\r
+\r
+int int_sqrt ( int x, int y )\r
+{\r
+\r
+int    Sqr_Table[12] = {1, 4, 9, 6, 25, 36, 49, 64, 81, 100, 121, 144};\r
+\r
+int    r, d;\r
+\r
+       d = (x * x) + (y * y);\r
+       r = 0;\r
+\r
+       while ( d >= Sqr_Table[r] )\r
+       {\r
+               r++;\r
+       }\r
+\r
+       return (r);\r
+\r
+}\r
+\r
+\r
+       /* The Bit Sprite Demo */\r
+\r
+\r
+void page_demo ()\r
+{\r
+\r
+char   *Error1 = "Failure during SET_VGA_MODEX (0, 320, 200, 2) call";\r
+\r
+int            Last_Objects[2], Visible_Objects;\r
+\r
+int            Screen_X = 384;\r
+int            Screen_Y = 224;\r
+\r
+int            x, y, z;\r
+int            c, dc;\r
+int            x1, y1, x2, y2;\r
+\r
+int            Sprite_X, Sprite_Y;\r
+int            Current_Page;\r
+int            New_X, New_Y;\r
+\r
+int            View_X, View_Y, View_Max, View_Cnt, View_XD, View_YD;\r
+int            Set_Color, Prev_Color, S_Dir, P_Dir;\r
+\r
+int            Demo_Running = True;\r
+int            redo, code;\r
+\r
+int pee;\r
+pee = set_vga_modex(Mode_320x200, Screen_X, Screen_Y, 3);\r
+       if ( pee > 0)\r
+       {\r
+               set_video_mode (3);\r
+               dos_print (Error1);\r
+               fprintf(stdout, "return value is %d\n", pee);\r
+               //error_out (Error1);\r
+               exit (EXIT_SUCCESS);\r
+       }\r
+\r
+       set_active_page (0);\r
+       clear_vga_screen (c_BLACK);\r
+\r
+       print_str ("This is a Test of the Following Functions:", 99, 10, 9, c_bWHITE, c_BLACK);\r
+\r
+       draw_line (10, 18, 350, 18, c_YELLOW);\r
+       print_str ("SET_ACTIVE_PAGE", 99, 10, 20, c_bBLUE, c_BLACK);\r
+       print_str ("SET_DISPLAY_PAGE", 99, 10, 30, c_GREEN, c_BLACK);\r
+       print_str ("SET_DAC_REGISTER", 99, 10, 40, c_RED, c_BLACK);\r
+       print_str ("CLEAR_VGA_SCREEN", 99, 10, 50, c_CYAN, c_BLACK);\r
+\r
+       print_str ("TDRAW_BITMAP", 99, 10, 60, c_PURPLE, c_BLACK);\r
+       print_str ("COPY_PAGE", 99, 10, 70, c_GREEN, c_BLACK);\r
+       print_str ("COPY_BITMAP", 99, 10, 80, c_CYAN, c_BLACK);\r
+\r
+       print_str ("GPRINTC", 99, 10, 90, c_BLUE, c_BLACK);\r
+       print_str ("TGPRINTC", 99, 10, 100, c_GREEN, c_BLACK);\r
+       print_str ("SET_WINDOW", 99, 10, 110, c_RED, c_BLACK);\r
+\r
+       print_str ("VIRTUAL SCREEN SIZES", 20, 190, 20, c_bBLUE, c_BLACK);\r
+       print_str ("    SMOOTH SCROLLING", 20, 190, 30, c_GREEN, c_BLACK);\r
+       print_str ("    SPRITE ANIMATION", 20, 190, 40, c_CYAN, c_BLACK);\r
+       print_str ("       PAGE FLIPPING", 20, 190, 50, c_RED, c_BLACK);\r
+       print_str ("       COLOR CYCLING", 20, 190, 60, c_PURPLE, c_BLACK);\r
+\r
+       for (x = 0; x <=60; x++)\r
+       {\r
+               set_dac_register (50 + x, 3 + x, 0, 60 - x);\r
+               set_dac_register (150 + x, 3 + x, 0, 60 - x);\r
+       }\r
+\r
+       c = 0;\r
+       dc = 1;\r
+       for (x = 0; x <= (Screen_X / 2); x++)\r
+       {\r
+               draw_line (Screen_X / 2 - 1, Screen_Y / 4, x, Screen_Y - 1, c + 50);\r
+               draw_line (Screen_X / 2, Screen_Y / 4, Screen_X - x - 1, Screen_Y - 1, c + 50);\r
+               c+= dc;\r
+               if ((c == 0) || (c == 60) ) { dc = -dc;}\r
+       }\r
+\r
+       tprint_str ("Press <ANY KEY> to Continue", 99, 72, 190, c_bWHITE);\r
+       tprint_str ("< > = Faster   < > = Slower", 99, 72, 204, c_bGREEN);\r
+       tprint_str ("< > = Fewer Shapes  < > = More Shapes", 99, 32, 218, c_bCYAN);\r
+\r
+       tgprintc (43, 80, 204, c_YELLOW);\r
+       tgprintc (45, 200, 204, c_YELLOW);\r
+\r
+       tgprintc (25, 40, 218, c_YELLOW);\r
+       tgprintc (24, 200, 218, c_YELLOW);\r
+\r
+       copy_page (0, 1);\r
+       copy_page (0, 2);\r
+\r
+       for (x = 0; x < MAX_SPRITES; x++)\r
+       {\r
+               do {\r
+                       Obj[x].X_Dir = random_int(7) - 3;\r
+                       Obj[x].Y_Dir = random_int(7) - 3;\r
+               } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) );\r
+\r
+               Obj[x].Shape = x % MAX_SHAPES;\r
+\r
+               Sprite_X = Img[Obj[x].Shape].X_Width;\r
+               Sprite_Y = Img[Obj[x].Shape].Y_Width;\r
+\r
+               Obj[x].X_pos = 1 + random_int(Screen_X - Sprite_X - 2);\r
+               Obj[x].Y_pos = 1 + random_int(Screen_Y - Sprite_Y - 2);\r
+\r
+               Obj[x].Last_X[0] = Obj[x].X_pos;\r
+               Obj[x].Last_X[1] = Obj[x].X_pos;\r
+               Obj[x].Last_Y[0] = Obj[x].Y_pos;\r
+               Obj[x].Last_Y[1] = Obj[x].Y_pos;\r
+\r
+       }\r
+\r
+       Current_Page = 0;\r
+\r
+       View_X = 0;\r
+       View_Y = 0;\r
+       View_Max = 3;\r
+       View_Cnt = 0;\r
+       View_XD = 1;\r
+       View_YD = 1;\r
+\r
+       Set_Color = 3;\r
+       S_Dir = 1;\r
+       Prev_Color = 0;\r
+       P_Dir = 1;\r
+\r
+       Visible_Objects = MAX_SPRITES / 2;\r
+       Last_Objects[0] = 0;\r
+       Last_Objects[1] = 0;\r
+\r
+       while (Demo_Running)\r
+       {\r
+\r
+               set_active_page (Current_Page);\r
+\r
+                       /* Erase Old Images */\r
+\r
+               for (x = 0; x <= Last_Objects[Current_Page]; x++)\r
+               {\r
+                       z = 2;\r
+                       y = Obj[x].Shape;\r
+                       x1 = Obj[x].Last_X[Current_Page];\r
+                       y1 = Obj[x].Last_Y[Current_Page];\r
+                       x2 = x1 + Img[y].X_Width -1;\r
+                       y2 = y1 + Img[y].Y_Width -1;\r
+\r
+                       x1 = x1 & 0xfffc;\r
+                       x2 = x2 | 0x0003;\r
+\r
+                       copy_bitmap (z, x1, y1, x2, y2, Current_Page, x1, y1);\r
+               }\r
+\r
+                       /* Draw new images */\r
+\r
+               for (x = 0; x <= Visible_Objects; x++)\r
+               {\r
+                       Sprite_X = Img[Obj[x].Shape].X_Width;\r
+                       Sprite_Y = Img[Obj[x].Shape].Y_Width;\r
+\r
+                       /*  Move Sprite */\r
+\r
+                       do\r
+                       {\r
+                               redo = False;\r
+                               New_X = Obj[x].X_pos + Obj[x].X_Dir;\r
+\r
+                               if (( New_X < 0 ) || (New_X + Sprite_X > Screen_X) )\r
+                               {\r
+                                       Obj[x].X_Dir = -Obj[x].X_Dir;\r
+                                       if (random_int(20) == 1)\r
+                                       {\r
+                                               do\r
+                                               {\r
+                                                       Obj[x].X_Dir = random_int(7) - 3;\r
+                                                       Obj[x].Y_Dir = random_int(7) - 3;\r
+                                               } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) );\r
+                                               redo = True;\r
+                                       }\r
+                               }\r
+                       } while (redo);\r
+                       Obj[x].X_pos = Obj[x].X_pos + Obj[x].X_Dir;\r
+\r
+\r
+                       do\r
+                       {\r
+                               redo = False;\r
+                               New_Y = Obj[x].Y_pos + Obj[x].Y_Dir;\r
+\r
+                               if ( (New_Y < 0) || (New_Y + Sprite_Y > Screen_Y) )\r
+                               {\r
+                                       Obj[x].Y_Dir = -Obj[x].Y_Dir;\r
+                                       if (random_int(20) == 1)\r
+                                       {\r
+                                               do\r
+                                               {\r
+                                                       Obj[x].X_Dir = random_int(7) - 3;\r
+                                                       Obj[x].Y_Dir = random_int(7) - 3;\r
+                                               } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) );\r
+                                               redo = True;\r
+                                       }\r
+                               }\r
+                       } while (redo);\r
+\r
+                       Obj[x].Y_pos = Obj[x].Y_pos + Obj[x].Y_Dir;\r
+\r
+                       /* Draw Sprite */\r
+\r
+                       tdraw_bitmap ((char far*) &Img[Obj[x].Shape], Obj[x].X_pos, Obj[x].Y_pos, Sprite_X, Sprite_Y);\r
+\r
+                       Obj[x].Last_X[Current_Page] = Obj[x].X_pos;\r
+                       Obj[x].Last_Y[Current_Page] = Obj[x].Y_pos;\r
+\r
+               }\r
+\r
+               Last_Objects[Current_Page] = Visible_Objects;\r
+\r
+\r
+               /* Pan Screen Back & Forth */\r
+\r
+               View_Cnt++;\r
+               if (View_Cnt >= View_Max)\r
+               {\r
+                       View_X+= View_XD;\r
+                       if ( (View_X == 0) || (View_X == 39) ) {View_XD = -View_XD;}\r
+                       if (View_XD < 0)\r
+                       {\r
+                               View_Y+= View_YD;\r
+                               if ( (View_Y == 0) || (View_Y == 39) ) {View_YD = -View_YD;}\r
+                       }\r
+\r
+                       set_window (Current_Page, View_X, View_Y);\r
+\r
+                       View_Cnt = 0;\r
+               }\r
+               else\r
+               {\r
+                       set_display_page (Current_Page);\r
+               }\r
+\r
+               /* Cycle Colors */\r
+\r
+               set_dac_register (50 + Prev_Color, 3 + Prev_Color, 0, 60 - Prev_Color);\r
+               set_dac_register (50 + Set_Color, Set_Color, 10, 63 - Set_Color);\r
+\r
+               set_dac_register (150 + Prev_Color, 3 + Prev_Color, 0, 60 - Prev_Color);\r
+               set_dac_register (150 + Set_Color, 63, 63, Set_Color);\r
+\r
+               Set_Color+= S_Dir;\r
+               if ( (Set_Color == 60) || (Set_Color == 0) ) {S_Dir = -S_Dir;}\r
+\r
+               Prev_Color+= P_Dir;\r
+               if ( (Prev_Color == 60) || (Prev_Color == 0) ) {P_Dir = -P_Dir;}\r
+\r
+               /* Check for Keystroke */\r
+\r
+               Current_Page = Current_Page ^ 0x01;\r
+\r
+               code = scan_keyboard ();\r
+\r
+               if (code == Ky_ESC) {Demo_Running = False;}\r
+\r
+               if (code == Ky_Plus)\r
+               {\r
+                       if (View_Max < 12) {View_Max++;}\r
+               }\r
+\r
+               if (code == Ky_Minus)\r
+               {\r
+                       if (View_Max > 1) {View_Max--;}\r
+                       if (View_Cnt >= View_Max) {View_Cnt = 0;}\r
+               }\r
+\r
+               if (code == Ky_Up)\r
+               {\r
+                       if (Visible_Objects < MAX_SPRITES-1) {Visible_Objects++;}\r
+               }\r
+\r
+               if (code == Ky_Down)\r
+               {\r
+                       if (Visible_Objects > 0) {Visible_Objects--;}\r
+               }\r
+\r
+       }\r
+\r
+}\r
diff --git a/src/lib/modex/x_demo.dsk b/src/lib/modex/x_demo.dsk
new file mode 100755 (executable)
index 0000000..5573e71
Binary files /dev/null and b/src/lib/modex/x_demo.dsk differ
diff --git a/src/lib/modex/x_demo.exe b/src/lib/modex/x_demo.exe
new file mode 100755 (executable)
index 0000000..75369ab
Binary files /dev/null and b/src/lib/modex/x_demo.exe differ
diff --git a/src/lib/modex/x_demo.prj b/src/lib/modex/x_demo.prj
new file mode 100755 (executable)
index 0000000..b3f307e
Binary files /dev/null and b/src/lib/modex/x_demo.prj differ
index 218959c44d87e24559deef90d2c1e9b427f5cf06..78e4ac3298fcc36b279628ea872371fd48d53ce2 100755 (executable)
Binary files a/test.exe and b/test.exe differ
index 243e4682b4290fe5fcebf7662c3669c4c59d5712..fb16b1f74f7dc82134251b02cb84b1da1d5e9d92 100755 (executable)
Binary files a/test2.exe and b/test2.exe differ
index 892afa7ebd4a9f70eac2d885b59bdd1d13e9f365..2ccb997a3e3b9a4c71a99539d7498d1be0f07e81 100755 (executable)
Binary files a/vgmtest.exe and b/vgmtest.exe differ
diff --git a/x-demo.smp b/x-demo.smp
new file mode 100755 (executable)
index 0000000..42aafa3
Binary files /dev/null and b/x-demo.smp differ
diff --git a/x_demo.exe b/x_demo.exe
new file mode 100755 (executable)
index 0000000..75369ab
Binary files /dev/null and b/x_demo.exe differ
diff --git a/x_demo.smp b/x_demo.smp
new file mode 100755 (executable)
index 0000000..85d0078
Binary files /dev/null and b/x_demo.smp differ