From 75a35fd2843da7105acc7eee68674131431d0ccb Mon Sep 17 00:00:00 2001 From: sparky4 Date: Mon, 21 Dec 2015 10:08:03 -0600 Subject: [PATCH] wwww --- 16.exe | Bin 46304 -> 77504 bytes 16/x/default.fnt | 260 ++ 16/x/makefile | 81 + 16/x/modex.def | 163 + 16/x/modex.h | 153 + 16/x/modex.lbr | 38 + 16/x/modex.pas | 194 ++ 16/x/modex/DEMO01.EXE | Bin 0 -> 10208 bytes 16/x/modex/DEMO01.PAS | 126 + 16/x/modex/DEMO02.EXE | Bin 0 -> 24688 bytes 16/x/modex/DEMO02.PAS | 125 + 16/x/modex/DEMO03.EXE | Bin 0 -> 14256 bytes 16/x/modex/DEMO03.PAS | 152 + 16/x/modex/DEMO04.DAT | Bin 0 -> 37662 bytes 16/x/modex/DEMO04.EXE | Bin 0 -> 24384 bytes 16/x/modex/DEMO04.PAS | 198 ++ 16/x/modex/DEMO05.EXE | Bin 0 -> 22528 bytes 16/x/modex/DEMO05.PAS | 131 + 16/x/modex/DEMO06.DAT | Bin 0 -> 77568 bytes 16/x/modex/DEMO06.EXE | Bin 0 -> 10864 bytes 16/x/modex/DEMO06.PAS | 135 + 16/x/modex/DEMO07.EXE | Bin 0 -> 7440 bytes 16/x/modex/DEMO07.PAS | 68 + 16/x/modex/MATH.INC | 34 + 16/x/modex/PLASMA.PAS | 103 + 16/x/modex/QIX2.EXE | Bin 0 -> 10336 bytes 16/x/modex/QIX2.PAS | 210 ++ 16/x/modex/README.TXT | 8 + 16/x/modex/SINCOS.INC | 518 +++ 16/x/modex/THREED.ASM | 872 +++++ 16/x/modex/THREED.H | 32 + 16/x/modex/THREED.PAS | 40 + 16/x/mxbb.asm | 278 ++ 16/x/mxcc.asm | 644 ++++ 16/x/mxcg.asm | 69 + 16/x/mxcl.asm | 151 + 16/x/mxcr.asm | 380 +++ 16/x/mxel.asm | 167 + 16/x/mxfb.asm | 194 ++ 16/x/mxfp.asm | 326 ++ 16/x/mxgc.asm | 54 + 16/x/mxgi.asm | 132 + 16/x/mxgm.asm | 63 + 16/x/mxgp.asm | 56 + 16/x/mxgv.asm | 25 + 16/x/mxhl.asm | 76 + 16/x/mxit.asm | 98 + 16/x/mxll.asm | 82 + 16/x/mxln.asm | 414 +++ 16/x/mxot.asm | 330 ++ 16/x/mxpb.asm | 22 + 16/x/mxpf.asm | 420 +++ 16/x/mxpg.asm | 589 ++++ 16/x/mxpi.asm | 267 ++ 16/x/mxpn.asm | 60 + 16/x/mxpp.asm | 121 + 16/x/mxra.asm | 37 + 16/x/mxrp.asm | 101 + 16/x/mxsa.asm | 44 + 16/x/mxsc.asm | 50 + 16/x/mxsi.asm | 317 ++ 16/x/mxsl.asm | 62 + 16/x/mxsm.asm | 508 +++ 16/x/mxsp.asm | 57 + 16/x/mxss.asm | 72 + 16/x/mxtl.asm | 169 + 16/x/mxvs.asm | 110 + 16/x/mxwd.asm | 28 + 16/x/mxwm.asm | 39 + 16/x/mxwp.asm | 62 + 16/x/mxwr.asm | 28 + 16/x/readme.txt | 8 + 16/x_/MODEX.BAK | Bin 0 -> 59392 bytes 16/x_/default.fnt | 260 ++ 16/x_/makefile | 82 + 16/x_/modex.def | 154 + 16/x_/modex.h | 153 + 16/x_/modex.lbr | 38 + 16/x_/modex.pas | 194 ++ 16/x_/modex/DEMO01.EXE | Bin 0 -> 10208 bytes 16/x_/modex/DEMO01.PAS | 126 + 16/x_/modex/DEMO02.EXE | Bin 0 -> 24688 bytes 16/x_/modex/DEMO02.PAS | 125 + 16/x_/modex/DEMO03.EXE | Bin 0 -> 14256 bytes 16/x_/modex/DEMO03.PAS | 152 + 16/x_/modex/DEMO04.DAT | Bin 0 -> 37662 bytes 16/x_/modex/DEMO04.EXE | Bin 0 -> 24384 bytes 16/x_/modex/DEMO04.PAS | 198 ++ 16/x_/modex/DEMO05.EXE | Bin 0 -> 22528 bytes 16/x_/modex/DEMO05.PAS | 131 + 16/x_/modex/DEMO06.DAT | Bin 0 -> 77568 bytes 16/x_/modex/DEMO06.EXE | Bin 0 -> 10864 bytes 16/x_/modex/DEMO06.PAS | 135 + 16/x_/modex/DEMO07.EXE | Bin 0 -> 7440 bytes 16/x_/modex/DEMO07.PAS | 68 + 16/x_/modex/MATH.INC | 34 + 16/x_/modex/PLASMA.PAS | 103 + 16/x_/modex/QIX2.EXE | Bin 0 -> 10336 bytes 16/x_/modex/QIX2.PAS | 210 ++ 16/x_/modex/README.TXT | 8 + 16/x_/modex/SINCOS.INC | 518 +++ 16/x_/modex/THREED.ASM | 872 +++++ 16/x_/modex/THREED.H | 32 + 16/x_/modex/THREED.PAS | 40 + 16/x_/mxbb.asm | 278 ++ 16/x_/mxcc.asm | 644 ++++ 16/x_/mxcg.asm | 69 + 16/x_/mxcl.asm | 151 + 16/x_/mxcr.asm | 380 +++ 16/x_/mxel.asm | 167 + 16/x_/mxfb.asm | 194 ++ 16/x_/mxfp.asm | 326 ++ 16/x_/mxgc.asm | 54 + 16/x_/mxgi.asm | 132 + 16/x_/mxgm.asm | 63 + 16/x_/mxgp.asm | 56 + 16/x_/mxgv.asm | 25 + 16/x_/mxhl.asm | 76 + 16/x_/mxit.asm | 98 + 16/x_/mxll.asm | 82 + 16/x_/mxln.asm | 414 +++ 16/x_/mxot.asm | 330 ++ 16/x_/mxpb.asm | 22 + 16/x_/mxpf.asm | 420 +++ 16/x_/mxpg.asm | 589 ++++ 16/x_/mxpi.asm | 267 ++ 16/x_/mxpn.asm | 60 + 16/x_/mxpp.asm | 121 + 16/x_/mxra.asm | 37 + 16/x_/mxrp.asm | 101 + 16/x_/mxsa.asm | 44 + 16/x_/mxsc.asm | 50 + 16/x_/mxsi.asm | 317 ++ 16/x_/mxsl.asm | 62 + 16/x_/mxsm.asm | 508 +++ 16/x_/mxsp.asm | 57 + 16/x_/mxss.asm | 72 + 16/x_/mxtl.asm | 169 + 16/x_/mxvs.asm | 110 + 16/x_/mxwd.asm | 28 + 16/x_/mxwm.asm | 39 + 16/x_/mxwp.asm | 62 + 16/x_/mxwr.asm | 28 + 16/x_/readme.txt | 8 + 16/xlib/demo1.exe | Bin 41502 -> 0 bytes 16/xlib/demo2.exe | Bin 38496 -> 0 bytes 16/xlib/demo3.exe | Bin 9516 -> 0 bytes 16/xlib/demo4.exe | Bin 22750 -> 0 bytes 16/xlib/demo5.exe | Bin 19556 -> 0 bytes 16/xlib/demo6.exe | Bin 13604 -> 0 bytes 16/xlib/demo7.exe | Bin 14268 -> 0 bytes 16/xlib/demo8.exe | Bin 21266 -> 0 bytes 16/xlib/makefile | 3 + 16/xlib/model.inc | 30 +- 16/xlib/xbmtools.asm | 2 +- 16/xlib/xfileio.asm | 1 - 16/xlib/xlib.inc | 8 +- 16/xlib/xline.asm | 67 +- 16/xlib/xmain.asm | 182 +- 16/xlib/xmain.inc | 4 +- 16/xlib/xpal.asm | 16 +- 16/xlib/xpoint.asm | 22 +- 16/xw/default.fnt | 260 ++ 16/xw/makefile | 132 + 16/xw/makefile.bcc | 81 + 16/xw/modex.bak | Bin 0 -> 25600 bytes 16/xw/modex.def | 163 + 16/xw/modex.h | 153 + 16/xw/modex.lbr | 39 + 16/xw/modex.pas | 194 ++ 16/xw/modex/DEMO01.EXE | Bin 0 -> 10208 bytes 16/xw/modex/DEMO01.PAS | 126 + 16/xw/modex/DEMO02.EXE | Bin 0 -> 24688 bytes 16/xw/modex/DEMO02.PAS | 125 + 16/xw/modex/DEMO03.EXE | Bin 0 -> 14256 bytes 16/xw/modex/DEMO03.PAS | 152 + 16/xw/modex/DEMO04.DAT | Bin 0 -> 37662 bytes 16/xw/modex/DEMO04.EXE | Bin 0 -> 24384 bytes 16/xw/modex/DEMO04.PAS | 198 ++ 16/xw/modex/DEMO05.EXE | Bin 0 -> 22528 bytes 16/xw/modex/DEMO05.PAS | 131 + 16/xw/modex/DEMO06.DAT | Bin 0 -> 77568 bytes 16/xw/modex/DEMO06.EXE | Bin 0 -> 10864 bytes 16/xw/modex/DEMO06.PAS | 135 + 16/xw/modex/DEMO07.EXE | Bin 0 -> 7440 bytes 16/xw/modex/DEMO07.PAS | 68 + 16/xw/modex/MATH.INC | 34 + 16/xw/modex/PLASMA.PAS | 103 + 16/xw/modex/QIX2.EXE | Bin 0 -> 10336 bytes 16/xw/modex/QIX2.PAS | 210 ++ 16/xw/modex/README.TXT | 8 + 16/xw/modex/SINCOS.INC | 518 +++ 16/xw/modex/THREED.ASM | 872 +++++ 16/xw/modex/THREED.H | 32 + 16/xw/modex/THREED.PAS | 40 + 16/xw/modex/demo01.c | 140 + 16/xw/mxbb.asm | 278 ++ 16/xw/mxcc.asm | 644 ++++ 16/xw/mxcg.asm | 69 + 16/xw/mxcl.asm | 151 + 16/xw/mxcr.asm | 380 +++ 16/xw/mxel.asm | 167 + 16/xw/mxfb.asm | 194 ++ 16/xw/mxfp.asm | 326 ++ 16/xw/mxgc.asm | 54 + 16/xw/mxgi.asm | 132 + 16/xw/mxgm.asm | 63 + 16/xw/mxgp.asm | 56 + 16/xw/mxgv.asm | 25 + 16/xw/mxhl.asm | 76 + 16/xw/mxit.asm | 98 + 16/xw/mxll.asm | 82 + 16/xw/mxln.asm | 414 +++ 16/xw/mxot.asm | 330 ++ 16/xw/mxpb.asm | 22 + 16/xw/mxpf.asm | 420 +++ 16/xw/mxpg.asm | 589 ++++ 16/xw/mxpi.asm | 267 ++ 16/xw/mxpn.asm | 60 + 16/xw/mxpp.asm | 121 + 16/xw/mxra.asm | 37 + 16/xw/mxrp.asm | 101 + 16/xw/mxsa.asm | 44 + 16/xw/mxsc.asm | 50 + 16/xw/mxsi.asm | 317 ++ 16/xw/mxsl.asm | 62 + 16/xw/mxsm.asm | 508 +++ 16/xw/mxsp.asm | 57 + 16/xw/mxss.asm | 72 + 16/xw/mxtl.asm | 169 + 16/xw/mxvs.asm | 110 + 16/xw/mxwd.asm | 28 + 16/xw/mxwm.asm | 39 + 16/xw/mxwp.asm | 62 + 16/xw/mxwr.asm | 28 + 16/xw/readme.txt | 8 + 16/xw_/default.fnt | 260 ++ 16/xw_/makefile | 132 + 16/xw_/makefile.bcc | 81 + 16/xw_/modex.bak | Bin 0 -> 25600 bytes 16/xw_/modex.def | 163 + 16/xw_/modex.h | 153 + 16/xw_/modex.lbr | 39 + 16/xw_/modex.pas | 194 ++ 16/xw_/modex/DEMO01.EXE | Bin 0 -> 10208 bytes 16/xw_/modex/DEMO01.PAS | 126 + 16/xw_/modex/DEMO02.EXE | Bin 0 -> 24688 bytes 16/xw_/modex/DEMO02.PAS | 125 + 16/xw_/modex/DEMO03.EXE | Bin 0 -> 14256 bytes 16/xw_/modex/DEMO03.PAS | 152 + 16/xw_/modex/DEMO04.DAT | Bin 0 -> 37662 bytes 16/xw_/modex/DEMO04.EXE | Bin 0 -> 24384 bytes 16/xw_/modex/DEMO04.PAS | 198 ++ 16/xw_/modex/DEMO05.EXE | Bin 0 -> 22528 bytes 16/xw_/modex/DEMO05.PAS | 131 + 16/xw_/modex/DEMO06.DAT | Bin 0 -> 77568 bytes 16/xw_/modex/DEMO06.EXE | Bin 0 -> 10864 bytes 16/xw_/modex/DEMO06.PAS | 135 + 16/xw_/modex/DEMO07.EXE | Bin 0 -> 7440 bytes 16/xw_/modex/DEMO07.PAS | 68 + 16/xw_/modex/MATH.INC | 34 + 16/xw_/modex/PLASMA.PAS | 103 + 16/xw_/modex/QIX2.EXE | Bin 0 -> 10336 bytes 16/xw_/modex/QIX2.PAS | 210 ++ 16/xw_/modex/README.TXT | 8 + 16/xw_/modex/SINCOS.INC | 518 +++ 16/xw_/modex/THREED.ASM | 872 +++++ 16/xw_/modex/THREED.H | 32 + 16/xw_/modex/THREED.PAS | 40 + 16/xw_/modex/demo01.c | 133 + 16/xw_/mxbb.asm | 207 ++ 16/xw_/mxcc.asm | 628 ++++ 16/xw_/mxcg.asm | 42 + 16/xw_/mxcl.asm | 110 + 16/xw_/mxcr.asm | 243 ++ 16/xw_/mxel.asm | 0 16/xw_/mxfb.asm | 133 + 16/xw_/mxfp.asm | 219 ++ 16/xw_/mxgc.asm | 30 + 16/xw_/mxgi.asm | 98 + 16/xw_/mxgm.asm | 68 + 16/xw_/mxgp.asm | 32 + 16/xw_/mxgv.asm | 8 + 16/xw_/mxhl.asm | 45 + 16/xw_/mxit.asm | 98 + 16/xw_/mxll.asm | 50 + 16/xw_/mxln.asm | 332 ++ 16/xw_/mxot.asm | 1330 ++++++++ 16/xw_/mxot_.asm | 333 ++ 16/xw_/mxpb.asm | 4102 ++++++++++++++++++++++ 16/xw_/mxpf.asm | 327 ++ 16/xw_/mxpg.asm | 457 +++ 16/xw_/mxpi.asm | 218 ++ 16/xw_/mxpn.asm | 34 + 16/xw_/mxpp.asm | 84 + 16/xw_/mxra.asm | 17 + 16/xw_/mxrp.asm | 72 + 16/xw_/mxsa.asm | 22 + 16/xw_/mxsc.asm | 26 + 16/xw_/mxsi.asm | 220 ++ 16/xw_/mxsl.asm | 36 + 16/xw_/mxsm.asm | 449 +++ 16/xw_/mxsp.asm | 33 + 16/xw_/mxss.asm | 44 + 16/xw_/mxtl.asm | 122 + 16/xw_/mxvs.asm | 68 + 16/xw_/mxwd.asm | 12 + 16/xw_/mxwm.asm | 18 + 16/xw_/mxwp.asm | 30 + 16/xw_/mxwr.asm | 12 + 16/xw_/readme.txt | 8 + 16/xw_/xw.bat | 39 + 16/xw__/default.fnt | 260 ++ 16/xw__/makefile | 132 + 16/xw__/makefile.bcc | 81 + 16/xw__/modex.bak | Bin 0 -> 25600 bytes 16/xw__/modex.def | 163 + 16/xw__/modex.h | 153 + 16/xw__/modex.lbr | 39 + 16/xw__/modex.pas | 194 ++ 16/xw__/modex/DEMO01.EXE | Bin 0 -> 10208 bytes 16/xw__/modex/DEMO01.PAS | 126 + 16/xw__/modex/DEMO02.EXE | Bin 0 -> 24688 bytes 16/xw__/modex/DEMO02.PAS | 125 + 16/xw__/modex/DEMO03.EXE | Bin 0 -> 14256 bytes 16/xw__/modex/DEMO03.PAS | 152 + 16/xw__/modex/DEMO04.DAT | Bin 0 -> 37662 bytes 16/xw__/modex/DEMO04.EXE | Bin 0 -> 24384 bytes 16/xw__/modex/DEMO04.PAS | 198 ++ 16/xw__/modex/DEMO05.EXE | Bin 0 -> 22528 bytes 16/xw__/modex/DEMO05.PAS | 131 + 16/xw__/modex/DEMO06.DAT | Bin 0 -> 77568 bytes 16/xw__/modex/DEMO06.EXE | Bin 0 -> 10864 bytes 16/xw__/modex/DEMO06.PAS | 135 + 16/xw__/modex/DEMO07.EXE | Bin 0 -> 7440 bytes 16/xw__/modex/DEMO07.PAS | 68 + 16/xw__/modex/MATH.INC | 34 + 16/xw__/modex/PLASMA.PAS | 103 + 16/xw__/modex/QIX2.EXE | Bin 0 -> 10336 bytes 16/xw__/modex/QIX2.PAS | 210 ++ 16/xw__/modex/README.TXT | 8 + 16/xw__/modex/SINCOS.INC | 518 +++ 16/xw__/modex/THREED.ASM | 872 +++++ 16/xw__/modex/THREED.H | 32 + 16/xw__/modex/THREED.PAS | 40 + 16/xw__/modex/demo01.c | 125 + 16/xw__/mxbb.asm | 208 ++ 16/xw__/mxcc.asm | 629 ++++ 16/xw__/mxcg.asm | 43 + 16/xw__/mxcl.asm | 111 + 16/xw__/mxcr.asm | 244 ++ 16/xw__/mxel.asm | 0 16/xw__/mxfb.asm | 134 + 16/xw__/mxfp.asm | 220 ++ 16/xw__/mxgc.asm | 31 + 16/xw__/mxgi.asm | 99 + 16/xw__/mxgm.asm | 69 + 16/xw__/mxgp.asm | 33 + 16/xw__/mxgv.asm | 9 + 16/xw__/mxhl.asm | 45 + 16/xw__/mxit.asm | 92 + 16/xw__/mxll.asm | 51 + 16/xw__/mxln.asm | 333 ++ 16/xw__/mxot.asm | 1310 +++++++ 16/xw__/mxot_.asm | 333 ++ 16/xw__/mxpb.asm | 4103 ++++++++++++++++++++++ 16/xw__/mxpf.asm | 328 ++ 16/xw__/mxpg.asm | 458 +++ 16/xw__/mxpi.asm | 219 ++ 16/xw__/mxpn.asm | 35 + 16/xw__/mxpp.asm | 85 + 16/xw__/mxra.asm | 18 + 16/xw__/mxrp.asm | 73 + 16/xw__/mxsa.asm | 23 + 16/xw__/mxsc.asm | 27 + 16/xw__/mxsi.asm | 221 ++ 16/xw__/mxsl.asm | 37 + 16/xw__/mxsm.asm | 450 +++ 16/xw__/mxsp.asm | 34 + 16/xw__/mxss.asm | 45 + 16/xw__/mxtl.asm | 123 + 16/xw__/mxvs.asm | 69 + 16/xw__/mxwd.asm | 13 + 16/xw__/mxwm.asm | 19 + 16/xw__/mxwp.asm | 31 + 16/xw__/mxwr.asm | 13 + 16/xw__/readme.txt | 8 + 16/xw__/xw.bat | 39 + awoo.sh | 8 +- bakapi.exe | Bin 47537 -> 77981 bytes exmmtest.exe | Bin 36560 -> 60948 bytes fmemtest.exe | Bin 36257 -> 60555 bytes fontgfx.exe | Bin 42906 -> 71333 bytes fonttest.exe | Bin 37108 -> 61949 bytes inputest.exe | Bin 35996 -> 60316 bytes makefile | 53 +- maptest.exe | Bin 46112 -> 77158 bytes palettec.exe | Bin 42372 -> 70705 bytes palettel.exe | Bin 42493 -> 70932 bytes pcxtest.exe | Bin 31026 -> 51372 bytes pcxtest2.exe | Bin 31093 -> 51452 bytes planrpcx.exe | Bin 32345 -> 53349 bytes scroll.exe | Bin 59590 -> 94512 bytes sparky4.do | 10 +- src/bakapi.c | 13 + src/lib/16_in.c | 7 +- src/lib/bakapee.c | 7 +- src/lib/bakapee.h | 7 +- src/lib/modex/asm.bat | 1 + src/lib/modex/c_utils.asm | 456 +++ src/lib/modex/c_utils.h | 117 + src/lib/modex/c_utils.lst | 597 ++++ src/lib/modex/c_utils.sbr | Bin 0 -> 1731 bytes src/lib/modex/demos/basic7/chardemo.bas | 164 + src/lib/modex/demos/basic7/make-lib.bat | 5 + src/lib/modex/demos/basic7/modex.bi | 63 + src/lib/modex/demos/basic7/modex.qlb | Bin 0 -> 11141 bytes src/lib/modex/demos/basic7/test6.bas | 562 +++ src/lib/modex/demos/basic7/uasm-bc7.bat | 1 + src/lib/modex/demos/basic7/utils.asm | 406 +++ src/lib/modex/demos/basic7/utils.bi | 51 + src/lib/modex/demos/c/c_utils.asm | 456 +++ src/lib/modex/demos/c/c_utils.h | 117 + src/lib/modex/demos/c/c_utils.lst | 597 ++++ src/lib/modex/demos/c/c_utils.sbr | Bin 0 -> 1731 bytes src/lib/modex/demos/c/makefile | 30 + src/lib/modex/demos/c/modex.asm | 3505 +++++++++++++++++++ src/lib/modex/demos/c/modex.bi | 63 + src/lib/modex/demos/c/modex.h | 76 + src/lib/modex/demos/c/utls-asm.bat | 1 + src/lib/modex/demos/c/w.sh | 3 + src/lib/modex/demos/c/x-demo.c | 786 +++++ src/lib/modex/demos/c/x-demo.dsk | Bin 0 -> 195 bytes src/lib/modex/demos/c/x-demo.exe | Bin 0 -> 58495 bytes src/lib/modex/demos/c/x-demo.prj | Bin 0 -> 4936 bytes src/lib/modex/demos/c/x.exe | Bin 0 -> 41090 bytes src/lib/modex/demos/chardemo.exe | Bin 0 -> 13066 bytes src/lib/modex/demos/pascal/test5.pas | 488 +++ src/lib/modex/demos/qb45/make-lib.bat | 5 + src/lib/modex/demos/qb45/modex.bi | 63 + src/lib/modex/demos/qb45/modex.qlb | Bin 0 -> 9739 bytes src/lib/modex/demos/qb45/test6a.bas | 561 +++ src/lib/modex/demos/qb45/test6a.exe | Bin 0 -> 40544 bytes src/lib/modex/demos/qb45/uasm-qb4.bat | 1 + src/lib/modex/demos/qb45/utils.asm | 406 +++ src/lib/modex/demos/qb45/utils.bi | 51 + src/lib/modex/demos/rom_8x8.fnt | Bin 0 -> 1024 bytes src/lib/modex/demos/spaceage.fnt | Bin 0 -> 1024 bytes src/lib/modex/demos/system.fnt | Bin 0 -> 1024 bytes src/lib/modex/demos/test6.exe | Bin 0 -> 19990 bytes src/lib/modex/fontedit/charsets.cs | Bin 0 -> 2144 bytes src/lib/modex/fontedit/csedit.doc | 196 ++ src/lib/modex/fontedit/csedit.exe | Bin 0 -> 68368 bytes src/lib/modex/fontedit/inverse.fnt | Bin 0 -> 1024 bytes src/lib/modex/fontedit/mouseimg.cs | Bin 0 -> 128 bytes src/lib/modex/fontedit/palette.cs | Bin 0 -> 768 bytes src/lib/modex/fontedit/rom_8x8.fnt | Bin 0 -> 1024 bytes src/lib/modex/fontedit/spaceage.fnt | Bin 0 -> 1024 bytes src/lib/modex/fontedit/system.fnt | Bin 0 -> 1024 bytes src/lib/modex/makefile | 30 + src/lib/modex/mode-x.txt | 44 + src/lib/modex/modex.asm | 3505 +++++++++++++++++++ src/lib/modex/modex.bi | 63 + src/lib/modex/modex.h | 76 + src/lib/modex/modex.lst | 4122 +++++++++++++++++++++++ src/lib/modex/modex.sbr | Bin 0 -> 12235 bytes src/lib/modex/modex105.zip | Bin 0 -> 264999 bytes src/lib/modex/packing.lst | 87 + src/lib/modex/paledit/bakapi.pal | Bin 0 -> 768 bytes src/lib/modex/paledit/charsets.cs | Bin 0 -> 2144 bytes src/lib/modex/paledit/diagonal.pal | Bin 0 -> 768 bytes src/lib/modex/paledit/gamecolr.pal | Bin 0 -> 768 bytes src/lib/modex/paledit/mouseimg.cs | Bin 0 -> 128 bytes src/lib/modex/paledit/paledit.doc | 166 + src/lib/modex/paledit/paledit.exe | Bin 0 -> 70230 bytes src/lib/modex/paledit/palview.exe | Bin 0 -> 10358 bytes src/lib/modex/paledit/prime.pal | Bin 0 -> 768 bytes src/lib/modex/paledit/rgb.pal | Bin 0 -> 768 bytes src/lib/modex/paledit/scroll.pal | Bin 0 -> 768 bytes src/lib/modex/readme.doc | 76 + src/lib/modex/utls-asm.bat | 1 + src/lib/modex/w.sh | 3 + src/lib/modex/x.exe | Bin 0 -> 41090 bytes src/lib/modex/x_demo.c | 786 +++++ src/lib/modex/x_demo.dsk | Bin 0 -> 195 bytes src/lib/modex/x_demo.exe | Bin 0 -> 58447 bytes src/lib/modex/x_demo.prj | Bin 0 -> 4936 bytes test.exe | Bin 29344 -> 49370 bytes test2.exe | Bin 24167 -> 41238 bytes vgmtest.exe | Bin 40521 -> 67189 bytes x-demo.smp | Bin 0 -> 32352 bytes x_demo.exe | Bin 0 -> 58447 bytes x_demo.smp | Bin 0 -> 15619 bytes 493 files changed, 79104 insertions(+), 168 deletions(-) create mode 100755 16/x/default.fnt create mode 100755 16/x/makefile create mode 100755 16/x/modex.def create mode 100755 16/x/modex.h create mode 100755 16/x/modex.lbr create mode 100755 16/x/modex.pas create mode 100755 16/x/modex/DEMO01.EXE create mode 100755 16/x/modex/DEMO01.PAS create mode 100755 16/x/modex/DEMO02.EXE create mode 100755 16/x/modex/DEMO02.PAS create mode 100755 16/x/modex/DEMO03.EXE create mode 100755 16/x/modex/DEMO03.PAS create mode 100755 16/x/modex/DEMO04.DAT create mode 100755 16/x/modex/DEMO04.EXE create mode 100755 16/x/modex/DEMO04.PAS create mode 100755 16/x/modex/DEMO05.EXE create mode 100755 16/x/modex/DEMO05.PAS create mode 100755 16/x/modex/DEMO06.DAT create mode 100755 16/x/modex/DEMO06.EXE create mode 100755 16/x/modex/DEMO06.PAS create mode 100755 16/x/modex/DEMO07.EXE create mode 100755 16/x/modex/DEMO07.PAS create mode 100755 16/x/modex/MATH.INC create mode 100755 16/x/modex/PLASMA.PAS create mode 100755 16/x/modex/QIX2.EXE create mode 100755 16/x/modex/QIX2.PAS create mode 100755 16/x/modex/README.TXT create mode 100755 16/x/modex/SINCOS.INC create mode 100755 16/x/modex/THREED.ASM create mode 100755 16/x/modex/THREED.H create mode 100755 16/x/modex/THREED.PAS create mode 100755 16/x/mxbb.asm create mode 100755 16/x/mxcc.asm create mode 100755 16/x/mxcg.asm create mode 100755 16/x/mxcl.asm create mode 100755 16/x/mxcr.asm create mode 100755 16/x/mxel.asm create mode 100755 16/x/mxfb.asm create mode 100755 16/x/mxfp.asm create mode 100755 16/x/mxgc.asm create mode 100755 16/x/mxgi.asm create mode 100755 16/x/mxgm.asm create mode 100755 16/x/mxgp.asm create mode 100755 16/x/mxgv.asm create mode 100755 16/x/mxhl.asm create mode 100755 16/x/mxit.asm create mode 100755 16/x/mxll.asm create mode 100755 16/x/mxln.asm create mode 100755 16/x/mxot.asm create mode 100755 16/x/mxpb.asm create mode 100755 16/x/mxpf.asm create mode 100755 16/x/mxpg.asm create mode 100755 16/x/mxpi.asm create mode 100755 16/x/mxpn.asm create mode 100755 16/x/mxpp.asm create mode 100755 16/x/mxra.asm create mode 100755 16/x/mxrp.asm create mode 100755 16/x/mxsa.asm create mode 100755 16/x/mxsc.asm create mode 100755 16/x/mxsi.asm create mode 100755 16/x/mxsl.asm create mode 100755 16/x/mxsm.asm create mode 100755 16/x/mxsp.asm create mode 100755 16/x/mxss.asm create mode 100755 16/x/mxtl.asm create mode 100755 16/x/mxvs.asm create mode 100755 16/x/mxwd.asm create mode 100755 16/x/mxwm.asm create mode 100755 16/x/mxwp.asm create mode 100755 16/x/mxwr.asm create mode 100755 16/x/readme.txt create mode 100755 16/x_/MODEX.BAK create mode 100755 16/x_/default.fnt create mode 100755 16/x_/makefile create mode 100755 16/x_/modex.def create mode 100755 16/x_/modex.h create mode 100755 16/x_/modex.lbr create mode 100755 16/x_/modex.pas create mode 100755 16/x_/modex/DEMO01.EXE create mode 100755 16/x_/modex/DEMO01.PAS create mode 100755 16/x_/modex/DEMO02.EXE create mode 100755 16/x_/modex/DEMO02.PAS create mode 100755 16/x_/modex/DEMO03.EXE create mode 100755 16/x_/modex/DEMO03.PAS create mode 100755 16/x_/modex/DEMO04.DAT create mode 100755 16/x_/modex/DEMO04.EXE create mode 100755 16/x_/modex/DEMO04.PAS create mode 100755 16/x_/modex/DEMO05.EXE create mode 100755 16/x_/modex/DEMO05.PAS create mode 100755 16/x_/modex/DEMO06.DAT create mode 100755 16/x_/modex/DEMO06.EXE create mode 100755 16/x_/modex/DEMO06.PAS create mode 100755 16/x_/modex/DEMO07.EXE create mode 100755 16/x_/modex/DEMO07.PAS create mode 100755 16/x_/modex/MATH.INC create mode 100755 16/x_/modex/PLASMA.PAS create mode 100755 16/x_/modex/QIX2.EXE create mode 100755 16/x_/modex/QIX2.PAS create mode 100755 16/x_/modex/README.TXT create mode 100755 16/x_/modex/SINCOS.INC create mode 100755 16/x_/modex/THREED.ASM create mode 100755 16/x_/modex/THREED.H create mode 100755 16/x_/modex/THREED.PAS create mode 100755 16/x_/mxbb.asm create mode 100755 16/x_/mxcc.asm create mode 100755 16/x_/mxcg.asm create mode 100755 16/x_/mxcl.asm create mode 100755 16/x_/mxcr.asm create mode 100755 16/x_/mxel.asm create mode 100755 16/x_/mxfb.asm create mode 100755 16/x_/mxfp.asm create mode 100755 16/x_/mxgc.asm create mode 100755 16/x_/mxgi.asm create mode 100755 16/x_/mxgm.asm create mode 100755 16/x_/mxgp.asm create mode 100755 16/x_/mxgv.asm create mode 100755 16/x_/mxhl.asm create mode 100755 16/x_/mxit.asm create mode 100755 16/x_/mxll.asm create mode 100755 16/x_/mxln.asm create mode 100755 16/x_/mxot.asm create mode 100755 16/x_/mxpb.asm create mode 100755 16/x_/mxpf.asm create mode 100755 16/x_/mxpg.asm create mode 100755 16/x_/mxpi.asm create mode 100755 16/x_/mxpn.asm create mode 100755 16/x_/mxpp.asm create mode 100755 16/x_/mxra.asm create mode 100755 16/x_/mxrp.asm create mode 100755 16/x_/mxsa.asm create mode 100755 16/x_/mxsc.asm create mode 100755 16/x_/mxsi.asm create mode 100755 16/x_/mxsl.asm create mode 100755 16/x_/mxsm.asm create mode 100755 16/x_/mxsp.asm create mode 100755 16/x_/mxss.asm create mode 100755 16/x_/mxtl.asm create mode 100755 16/x_/mxvs.asm create mode 100755 16/x_/mxwd.asm create mode 100755 16/x_/mxwm.asm create mode 100755 16/x_/mxwp.asm create mode 100755 16/x_/mxwr.asm create mode 100755 16/x_/readme.txt delete mode 100755 16/xlib/demo1.exe delete mode 100755 16/xlib/demo2.exe delete mode 100755 16/xlib/demo3.exe delete mode 100755 16/xlib/demo4.exe delete mode 100755 16/xlib/demo5.exe delete mode 100755 16/xlib/demo6.exe delete mode 100755 16/xlib/demo7.exe delete mode 100755 16/xlib/demo8.exe create mode 100755 16/xw/default.fnt create mode 100755 16/xw/makefile create mode 100755 16/xw/makefile.bcc create mode 100755 16/xw/modex.bak create mode 100755 16/xw/modex.def create mode 100755 16/xw/modex.h create mode 100755 16/xw/modex.lbr create mode 100755 16/xw/modex.pas create mode 100755 16/xw/modex/DEMO01.EXE create mode 100755 16/xw/modex/DEMO01.PAS create mode 100755 16/xw/modex/DEMO02.EXE create mode 100755 16/xw/modex/DEMO02.PAS create mode 100755 16/xw/modex/DEMO03.EXE create mode 100755 16/xw/modex/DEMO03.PAS create mode 100755 16/xw/modex/DEMO04.DAT create mode 100755 16/xw/modex/DEMO04.EXE create mode 100755 16/xw/modex/DEMO04.PAS create mode 100755 16/xw/modex/DEMO05.EXE create mode 100755 16/xw/modex/DEMO05.PAS create mode 100755 16/xw/modex/DEMO06.DAT create mode 100755 16/xw/modex/DEMO06.EXE create mode 100755 16/xw/modex/DEMO06.PAS create mode 100755 16/xw/modex/DEMO07.EXE create mode 100755 16/xw/modex/DEMO07.PAS create mode 100755 16/xw/modex/MATH.INC create mode 100755 16/xw/modex/PLASMA.PAS create mode 100755 16/xw/modex/QIX2.EXE create mode 100755 16/xw/modex/QIX2.PAS create mode 100755 16/xw/modex/README.TXT create mode 100755 16/xw/modex/SINCOS.INC create mode 100755 16/xw/modex/THREED.ASM create mode 100755 16/xw/modex/THREED.H create mode 100755 16/xw/modex/THREED.PAS create mode 100755 16/xw/modex/demo01.c create mode 100755 16/xw/mxbb.asm create mode 100755 16/xw/mxcc.asm create mode 100755 16/xw/mxcg.asm create mode 100755 16/xw/mxcl.asm create mode 100755 16/xw/mxcr.asm create mode 100755 16/xw/mxel.asm create mode 100755 16/xw/mxfb.asm create mode 100755 16/xw/mxfp.asm create mode 100755 16/xw/mxgc.asm create mode 100755 16/xw/mxgi.asm create mode 100755 16/xw/mxgm.asm create mode 100755 16/xw/mxgp.asm create mode 100755 16/xw/mxgv.asm create mode 100755 16/xw/mxhl.asm create mode 100755 16/xw/mxit.asm create mode 100755 16/xw/mxll.asm create mode 100755 16/xw/mxln.asm create mode 100755 16/xw/mxot.asm create mode 100755 16/xw/mxpb.asm create mode 100755 16/xw/mxpf.asm create mode 100755 16/xw/mxpg.asm create mode 100755 16/xw/mxpi.asm create mode 100755 16/xw/mxpn.asm create mode 100755 16/xw/mxpp.asm create mode 100755 16/xw/mxra.asm create mode 100755 16/xw/mxrp.asm create mode 100755 16/xw/mxsa.asm create mode 100755 16/xw/mxsc.asm create mode 100755 16/xw/mxsi.asm create mode 100755 16/xw/mxsl.asm create mode 100755 16/xw/mxsm.asm create mode 100755 16/xw/mxsp.asm create mode 100755 16/xw/mxss.asm create mode 100755 16/xw/mxtl.asm create mode 100755 16/xw/mxvs.asm create mode 100755 16/xw/mxwd.asm create mode 100755 16/xw/mxwm.asm create mode 100755 16/xw/mxwp.asm create mode 100755 16/xw/mxwr.asm create mode 100755 16/xw/readme.txt create mode 100755 16/xw_/default.fnt create mode 100755 16/xw_/makefile create mode 100755 16/xw_/makefile.bcc create mode 100755 16/xw_/modex.bak create mode 100755 16/xw_/modex.def create mode 100755 16/xw_/modex.h create mode 100755 16/xw_/modex.lbr create mode 100755 16/xw_/modex.pas create mode 100755 16/xw_/modex/DEMO01.EXE create mode 100755 16/xw_/modex/DEMO01.PAS create mode 100755 16/xw_/modex/DEMO02.EXE create mode 100755 16/xw_/modex/DEMO02.PAS create mode 100755 16/xw_/modex/DEMO03.EXE create mode 100755 16/xw_/modex/DEMO03.PAS create mode 100755 16/xw_/modex/DEMO04.DAT create mode 100755 16/xw_/modex/DEMO04.EXE create mode 100755 16/xw_/modex/DEMO04.PAS create mode 100755 16/xw_/modex/DEMO05.EXE create mode 100755 16/xw_/modex/DEMO05.PAS create mode 100755 16/xw_/modex/DEMO06.DAT create mode 100755 16/xw_/modex/DEMO06.EXE create mode 100755 16/xw_/modex/DEMO06.PAS create mode 100755 16/xw_/modex/DEMO07.EXE create mode 100755 16/xw_/modex/DEMO07.PAS create mode 100755 16/xw_/modex/MATH.INC create mode 100755 16/xw_/modex/PLASMA.PAS create mode 100755 16/xw_/modex/QIX2.EXE create mode 100755 16/xw_/modex/QIX2.PAS create mode 100755 16/xw_/modex/README.TXT create mode 100755 16/xw_/modex/SINCOS.INC create mode 100755 16/xw_/modex/THREED.ASM create mode 100755 16/xw_/modex/THREED.H create mode 100755 16/xw_/modex/THREED.PAS create mode 100755 16/xw_/modex/demo01.c create mode 100755 16/xw_/mxbb.asm create mode 100755 16/xw_/mxcc.asm create mode 100755 16/xw_/mxcg.asm create mode 100755 16/xw_/mxcl.asm create mode 100755 16/xw_/mxcr.asm create mode 100755 16/xw_/mxel.asm create mode 100755 16/xw_/mxfb.asm create mode 100755 16/xw_/mxfp.asm create mode 100755 16/xw_/mxgc.asm create mode 100755 16/xw_/mxgi.asm create mode 100755 16/xw_/mxgm.asm create mode 100755 16/xw_/mxgp.asm create mode 100755 16/xw_/mxgv.asm create mode 100755 16/xw_/mxhl.asm create mode 100755 16/xw_/mxit.asm create mode 100755 16/xw_/mxll.asm create mode 100755 16/xw_/mxln.asm create mode 100755 16/xw_/mxot.asm create mode 100755 16/xw_/mxot_.asm create mode 100755 16/xw_/mxpb.asm create mode 100755 16/xw_/mxpf.asm create mode 100755 16/xw_/mxpg.asm create mode 100755 16/xw_/mxpi.asm create mode 100755 16/xw_/mxpn.asm create mode 100755 16/xw_/mxpp.asm create mode 100755 16/xw_/mxra.asm create mode 100755 16/xw_/mxrp.asm create mode 100755 16/xw_/mxsa.asm create mode 100755 16/xw_/mxsc.asm create mode 100755 16/xw_/mxsi.asm create mode 100755 16/xw_/mxsl.asm create mode 100755 16/xw_/mxsm.asm create mode 100755 16/xw_/mxsp.asm create mode 100755 16/xw_/mxss.asm create mode 100755 16/xw_/mxtl.asm create mode 100755 16/xw_/mxvs.asm create mode 100755 16/xw_/mxwd.asm create mode 100755 16/xw_/mxwm.asm create mode 100755 16/xw_/mxwp.asm create mode 100755 16/xw_/mxwr.asm create mode 100755 16/xw_/readme.txt create mode 100755 16/xw_/xw.bat create mode 100755 16/xw__/default.fnt create mode 100755 16/xw__/makefile create mode 100755 16/xw__/makefile.bcc create mode 100755 16/xw__/modex.bak create mode 100755 16/xw__/modex.def create mode 100755 16/xw__/modex.h create mode 100755 16/xw__/modex.lbr create mode 100755 16/xw__/modex.pas create mode 100755 16/xw__/modex/DEMO01.EXE create mode 100755 16/xw__/modex/DEMO01.PAS create mode 100755 16/xw__/modex/DEMO02.EXE create mode 100755 16/xw__/modex/DEMO02.PAS create mode 100755 16/xw__/modex/DEMO03.EXE create mode 100755 16/xw__/modex/DEMO03.PAS create mode 100755 16/xw__/modex/DEMO04.DAT create mode 100755 16/xw__/modex/DEMO04.EXE create mode 100755 16/xw__/modex/DEMO04.PAS create mode 100755 16/xw__/modex/DEMO05.EXE create mode 100755 16/xw__/modex/DEMO05.PAS create mode 100755 16/xw__/modex/DEMO06.DAT create mode 100755 16/xw__/modex/DEMO06.EXE create mode 100755 16/xw__/modex/DEMO06.PAS create mode 100755 16/xw__/modex/DEMO07.EXE create mode 100755 16/xw__/modex/DEMO07.PAS create mode 100755 16/xw__/modex/MATH.INC create mode 100755 16/xw__/modex/PLASMA.PAS create mode 100755 16/xw__/modex/QIX2.EXE create mode 100755 16/xw__/modex/QIX2.PAS create mode 100755 16/xw__/modex/README.TXT create mode 100755 16/xw__/modex/SINCOS.INC create mode 100755 16/xw__/modex/THREED.ASM create mode 100755 16/xw__/modex/THREED.H create mode 100755 16/xw__/modex/THREED.PAS create mode 100755 16/xw__/modex/demo01.c create mode 100755 16/xw__/mxbb.asm create mode 100755 16/xw__/mxcc.asm create mode 100755 16/xw__/mxcg.asm create mode 100755 16/xw__/mxcl.asm create mode 100755 16/xw__/mxcr.asm create mode 100755 16/xw__/mxel.asm create mode 100755 16/xw__/mxfb.asm create mode 100755 16/xw__/mxfp.asm create mode 100755 16/xw__/mxgc.asm create mode 100755 16/xw__/mxgi.asm create mode 100755 16/xw__/mxgm.asm create mode 100755 16/xw__/mxgp.asm create mode 100755 16/xw__/mxgv.asm create mode 100755 16/xw__/mxhl.asm create mode 100755 16/xw__/mxit.asm create mode 100755 16/xw__/mxll.asm create mode 100755 16/xw__/mxln.asm create mode 100755 16/xw__/mxot.asm create mode 100755 16/xw__/mxot_.asm create mode 100755 16/xw__/mxpb.asm create mode 100755 16/xw__/mxpf.asm create mode 100755 16/xw__/mxpg.asm create mode 100755 16/xw__/mxpi.asm create mode 100755 16/xw__/mxpn.asm create mode 100755 16/xw__/mxpp.asm create mode 100755 16/xw__/mxra.asm create mode 100755 16/xw__/mxrp.asm create mode 100755 16/xw__/mxsa.asm create mode 100755 16/xw__/mxsc.asm create mode 100755 16/xw__/mxsi.asm create mode 100755 16/xw__/mxsl.asm create mode 100755 16/xw__/mxsm.asm create mode 100755 16/xw__/mxsp.asm create mode 100755 16/xw__/mxss.asm create mode 100755 16/xw__/mxtl.asm create mode 100755 16/xw__/mxvs.asm create mode 100755 16/xw__/mxwd.asm create mode 100755 16/xw__/mxwm.asm create mode 100755 16/xw__/mxwp.asm create mode 100755 16/xw__/mxwr.asm create mode 100755 16/xw__/readme.txt create mode 100755 16/xw__/xw.bat create mode 100755 src/lib/modex/asm.bat create mode 100755 src/lib/modex/c_utils.asm create mode 100755 src/lib/modex/c_utils.h create mode 100755 src/lib/modex/c_utils.lst create mode 100755 src/lib/modex/c_utils.sbr create mode 100755 src/lib/modex/demos/basic7/chardemo.bas create mode 100755 src/lib/modex/demos/basic7/make-lib.bat create mode 100755 src/lib/modex/demos/basic7/modex.bi create mode 100755 src/lib/modex/demos/basic7/modex.qlb create mode 100755 src/lib/modex/demos/basic7/test6.bas create mode 100755 src/lib/modex/demos/basic7/uasm-bc7.bat create mode 100755 src/lib/modex/demos/basic7/utils.asm create mode 100755 src/lib/modex/demos/basic7/utils.bi create mode 100755 src/lib/modex/demos/c/c_utils.asm create mode 100755 src/lib/modex/demos/c/c_utils.h create mode 100755 src/lib/modex/demos/c/c_utils.lst create mode 100755 src/lib/modex/demos/c/c_utils.sbr create mode 100755 src/lib/modex/demos/c/makefile create mode 100755 src/lib/modex/demos/c/modex.asm create mode 100755 src/lib/modex/demos/c/modex.bi create mode 100755 src/lib/modex/demos/c/modex.h create mode 100755 src/lib/modex/demos/c/utls-asm.bat create mode 100755 src/lib/modex/demos/c/w.sh create mode 100755 src/lib/modex/demos/c/x-demo.c create mode 100755 src/lib/modex/demos/c/x-demo.dsk create mode 100755 src/lib/modex/demos/c/x-demo.exe create mode 100755 src/lib/modex/demos/c/x-demo.prj create mode 100755 src/lib/modex/demos/c/x.exe create mode 100755 src/lib/modex/demos/chardemo.exe create mode 100755 src/lib/modex/demos/pascal/test5.pas create mode 100755 src/lib/modex/demos/qb45/make-lib.bat create mode 100755 src/lib/modex/demos/qb45/modex.bi create mode 100755 src/lib/modex/demos/qb45/modex.qlb create mode 100755 src/lib/modex/demos/qb45/test6a.bas create mode 100755 src/lib/modex/demos/qb45/test6a.exe create mode 100755 src/lib/modex/demos/qb45/uasm-qb4.bat create mode 100755 src/lib/modex/demos/qb45/utils.asm create mode 100755 src/lib/modex/demos/qb45/utils.bi create mode 100755 src/lib/modex/demos/rom_8x8.fnt create mode 100755 src/lib/modex/demos/spaceage.fnt create mode 100755 src/lib/modex/demos/system.fnt create mode 100755 src/lib/modex/demos/test6.exe create mode 100755 src/lib/modex/fontedit/charsets.cs create mode 100755 src/lib/modex/fontedit/csedit.doc create mode 100755 src/lib/modex/fontedit/csedit.exe create mode 100755 src/lib/modex/fontedit/inverse.fnt create mode 100755 src/lib/modex/fontedit/mouseimg.cs create mode 100755 src/lib/modex/fontedit/palette.cs create mode 100755 src/lib/modex/fontedit/rom_8x8.fnt create mode 100755 src/lib/modex/fontedit/spaceage.fnt create mode 100755 src/lib/modex/fontedit/system.fnt create mode 100755 src/lib/modex/makefile create mode 100755 src/lib/modex/mode-x.txt create mode 100755 src/lib/modex/modex.asm create mode 100755 src/lib/modex/modex.bi create mode 100755 src/lib/modex/modex.h create mode 100755 src/lib/modex/modex.lst create mode 100755 src/lib/modex/modex.sbr create mode 100755 src/lib/modex/modex105.zip create mode 100755 src/lib/modex/packing.lst create mode 100755 src/lib/modex/paledit/bakapi.pal create mode 100755 src/lib/modex/paledit/charsets.cs create mode 100755 src/lib/modex/paledit/diagonal.pal create mode 100755 src/lib/modex/paledit/gamecolr.pal create mode 100755 src/lib/modex/paledit/mouseimg.cs create mode 100755 src/lib/modex/paledit/paledit.doc create mode 100755 src/lib/modex/paledit/paledit.exe create mode 100755 src/lib/modex/paledit/palview.exe create mode 100755 src/lib/modex/paledit/prime.pal create mode 100755 src/lib/modex/paledit/rgb.pal create mode 100755 src/lib/modex/paledit/scroll.pal create mode 100755 src/lib/modex/readme.doc create mode 100755 src/lib/modex/utls-asm.bat create mode 100755 src/lib/modex/w.sh create mode 100755 src/lib/modex/x.exe create mode 100755 src/lib/modex/x_demo.c create mode 100755 src/lib/modex/x_demo.dsk create mode 100755 src/lib/modex/x_demo.exe create mode 100755 src/lib/modex/x_demo.prj create mode 100755 x-demo.smp create mode 100755 x_demo.exe create mode 100755 x_demo.smp diff --git a/16.exe b/16.exe index 46a5d4c8687a1b65ab76eb48b8304ba6f68dcf98..b6f2dbe73359399267d4da03382884eb7bcbc8bf 100755 GIT binary patch literal 77504 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 + DB 078h, 084h, 004h, 008h, 010h, 000h, 010h, 000h ; ? + DB 07Ch, 082h, 0BAh, 0A6h, 0BEh, 080h, 07Ch, 000h ; @ + DB 078h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h ; A + DB 0F8h, 084h, 084h, 0F8h, 084h, 084h, 0F8h, 000h ; B + DB 078h, 084h, 080h, 080h, 080h, 084h, 078h, 000h ; C + DB 0F0h, 088h, 084h, 084h, 084h, 088h, 0F0h, 000h ; D + DB 0FCh, 080h, 080h, 0F0h, 080h, 080h, 0FCh, 000h ; E + DB 0FCh, 080h, 080h, 0F0h, 080h, 080h, 080h, 000h ; F + DB 078h, 084h, 080h, 09Ch, 084h, 084h, 078h, 000h ; G + DB 084h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h ; H + DB 038h, 010h, 010h, 010h, 010h, 010h, 038h, 000h ; I + DB 01Ch, 008h, 008h, 008h, 088h, 088h, 070h, 000h ; J + DB 084h, 088h, 090h, 0E0h, 090h, 088h, 084h, 000h ; K + DB 080h, 080h, 080h, 080h, 080h, 080h, 0FCh, 000h ; L + DB 0C6h, 0AAh, 092h, 082h, 082h, 082h, 082h, 000h ; M + DB 082h, 0C2h, 0A2h, 092h, 08Ah, 086h, 082h, 000h ; N + DB 078h, 084h, 084h, 084h, 084h, 084h, 078h, 000h ; O + DB 0F8h, 084h, 084h, 0F8h, 080h, 080h, 080h, 000h ; P + DB 078h, 084h, 084h, 084h, 094h, 088h, 076h, 000h ; Q + DB 0F8h, 084h, 084h, 0F8h, 090h, 088h, 084h, 000h ; R + DB 078h, 084h, 080h, 078h, 004h, 084h, 078h, 000h ; S + DB 0FEh, 010h, 010h, 010h, 010h, 010h, 010h, 000h ; T + DB 084h, 084h, 084h, 084h, 084h, 084h, 078h, 000h ; U + DB 084h, 084h, 084h, 084h, 084h, 048h, 030h, 000h ; V + DB 082h, 082h, 082h, 082h, 092h, 0AAh, 0C6h, 000h ; W + DB 082h, 044h, 028h, 010h, 028h, 044h, 082h, 000h ; X + DB 044h, 044h, 044h, 038h, 010h, 010h, 010h, 000h ; Y + DB 0FEh, 004h, 008h, 010h, 020h, 040h, 0FEh, 000h ; Z + DB 078h, 040h, 040h, 040h, 040h, 040h, 078h, 000h ; [ + DB 000h, 080h, 040h, 020h, 010h, 008h, 004h, 000h ; \ + DB 078h, 008h, 008h, 008h, 008h, 008h, 078h, 000h ; ] + DB 010h, 028h, 044h, 082h, 000h, 000h, 000h, 000h ; ^ + DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0FFh ; _ + DB 020h, 020h, 010h, 000h, 000h, 000h, 000h, 000h ; ` + DB 000h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; a + DB 000h, 040h, 040h, 078h, 044h, 044h, 078h, 000h ; b + DB 000h, 000h, 03Ch, 040h, 040h, 040h, 03Ch, 000h ; c + DB 000h, 004h, 004h, 03Ch, 044h, 044h, 03Ch, 000h ; d + DB 000h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; e + DB 000h, 00Ch, 010h, 03Ch, 010h, 010h, 010h, 000h ; f + DB 000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 038h ; g + DB 000h, 040h, 040h, 078h, 044h, 044h, 044h, 000h ; h + DB 000h, 010h, 000h, 010h, 010h, 010h, 010h, 000h ; i + DB 000h, 004h, 000h, 004h, 004h, 004h, 044h, 038h ; j + DB 000h, 040h, 040h, 050h, 060h, 050h, 048h, 000h ; k + DB 000h, 030h, 010h, 010h, 010h, 010h, 010h, 000h ; l + DB 000h, 000h, 068h, 054h, 054h, 044h, 044h, 000h ; m + DB 000h, 000h, 078h, 044h, 044h, 044h, 044h, 000h ; n + DB 000h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; o + DB 000h, 000h, 078h, 044h, 044h, 078h, 040h, 040h ; p + DB 000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 004h ; q + DB 000h, 000h, 05Ch, 060h, 040h, 040h, 040h, 000h ; r + DB 000h, 000h, 038h, 040h, 07Ch, 004h, 07Ch, 000h ; s + DB 000h, 010h, 038h, 010h, 010h, 010h, 018h, 000h ; t + DB 000h, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; u + DB 000h, 000h, 044h, 044h, 044h, 028h, 010h, 000h ; v + DB 000h, 000h, 044h, 044h, 054h, 054h, 06Ch, 000h ; w + DB 000h, 000h, 044h, 028h, 010h, 028h, 044h, 000h ; x + DB 000h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch ; y + DB 000h, 000h, 07Ch, 004h, 038h, 040h, 07Ch, 000h ; z + DB 000h, 008h, 010h, 010h, 030h, 010h, 010h, 008h ; { + DB 000h, 010h, 010h, 010h, 000h, 010h, 010h, 010h ; | + DB 000h, 020h, 010h, 010h, 018h, 010h, 010h, 020h ; } + DB 064h, 098h, 000h, 000h, 000h, 000h, 000h, 000h ; ~ + DB 000h, 010h, 028h, 044h, 082h, 082h, 0FEh, 000h ;  + DB 07Ch, 080h, 080h, 080h, 080h, 07Ch, 004h, 07Ch ; #128 + DB 000h, 028h, 000h, 044h, 044h, 044h, 038h, 000h ; #129 + DB 03Ch, 000h, 07Ch, 044h, 07Ch, 040h, 07Ch, 000h ; #130 + DB 07Eh, 081h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #131 + DB 024h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #132 + DB 078h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #133 + DB 018h, 018h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #134 + DB 000h, 000h, 078h, 080h, 080h, 078h, 008h, 038h ; #135 + DB 07Ch, 082h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #136 + DB 048h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #137 + DB 078h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #138 + DB 000h, 028h, 000h, 010h, 010h, 010h, 010h, 000h ; #139 + DB 010h, 028h, 000h, 010h, 010h, 010h, 010h, 000h ; #140 + DB 000h, 030h, 000h, 010h, 010h, 010h, 010h, 000h ; #141 + DB 048h, 000h, 078h, 084h, 0FCh, 084h, 084h, 000h ; #142 + DB 030h, 030h, 078h, 084h, 0FCh, 084h, 084h, 000h ; #143 + DB 038h, 000h, 0FCh, 080h, 0F0h, 080h, 0FCh, 000h ; #144 + DB 000h, 000h, 07Eh, 008h, 07Eh, 048h, 07Eh, 000h ; #145 + DB 07Eh, 090h, 090h, 0FCh, 090h, 090h, 09Eh, 000h ; #146 + DB 07Ch, 082h, 038h, 044h, 044h, 044h, 038h, 000h ; #147 + DB 028h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #148 + DB 070h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #149 + DB 038h, 044h, 000h, 044h, 044h, 044h, 038h, 000h ; #150 + DB 070h, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; #151 + DB 028h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch ; #152 + DB 048h, 000h, 078h, 084h, 084h, 084h, 078h, 000h ; #153 + DB 048h, 000h, 084h, 084h, 084h, 084h, 078h, 000h ; #154 + DB 000h, 010h, 038h, 040h, 040h, 040h, 038h, 010h ; #155 + DB 038h, 044h, 040h, 0E0h, 040h, 040h, 082h, 0FCh ; #156 + DB 044h, 07Ch, 010h, 07Ch, 010h, 07Ch, 010h, 000h ; #157 + DB 0F0h, 088h, 08Ah, 0F7h, 082h, 082h, 082h, 000h ; #158 + DB 00Ch, 012h, 010h, 018h, 030h, 010h, 090h, 060h ; #159 + DB 03Ch, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #160 + DB 000h, 018h, 000h, 010h, 010h, 010h, 010h, 000h ; #161 + DB 01Ch, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #162 + DB 01Ch, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; #163 + DB 07Ch, 000h, 078h, 044h, 044h, 044h, 044h, 000h ; #164 + DB 07Ch, 000h, 044h, 064h, 054h, 04Ch, 044h, 000h ; #165 + DB 018h, 024h, 024h, 01Eh, 000h, 03Eh, 000h, 000h ; #166 + DB 01Ch, 022h, 022h, 01Ch, 000h, 03Eh, 000h, 000h ; #167 + DB 010h, 000h, 010h, 020h, 040h, 042h, 03Ch, 000h ; #168 + DB 000h, 000h, 000h, 0FCh, 080h, 080h, 000h, 000h ; #169 + DB 000h, 000h, 000h, 0FCh, 004h, 004h, 000h, 000h ; #170 + DB 040h, 044h, 048h, 057h, 021h, 047h, 004h, 007h ; #171 + DB 040h, 044h, 048h, 052h, 026h, 04Ah, 01Fh, 002h ; #172 + DB 010h, 000h, 010h, 010h, 010h, 010h, 010h, 000h ; #173 + DB 000h, 024h, 048h, 090h, 048h, 024h, 000h, 000h ; #174 + DB 000h, 048h, 024h, 012h, 024h, 048h, 000h, 000h ; #175 + DB 022h, 088h, 022h, 088h, 022h, 088h, 022h, 088h ; #176 + DB 055h, 0AAh, 055h, 0AAh, 055h, 0AAh, 055h, 0AAh ; #177 + DB 0DBh, 077h, 0DBh, 0EEh, 0DBh, 077h, 0DBh, 0EEh ; #178 + DB 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h ; #179 + DB 018h, 018h, 018h, 018h, 0F8h, 018h, 018h, 018h ; #180 + DB 018h, 018h, 0F8h, 018h, 0F8h, 018h, 018h, 018h ; #181 + DB 036h, 036h, 036h, 036h, 0F6h, 036h, 036h, 036h ; #182 + DB 000h, 000h, 000h, 000h, 0FEh, 036h, 036h, 036h ; #183 + DB 000h, 000h, 0F8h, 018h, 0F8h, 018h, 018h, 018h ; #184 + DB 036h, 036h, 0F6h, 006h, 0F6h, 036h, 036h, 036h ; #185 + DB 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h ; #186 + DB 000h, 000h, 0FEh, 006h, 0F6h, 036h, 036h, 036h ; #187 + DB 036h, 036h, 0F6h, 006h, 0FEh, 000h, 000h, 000h ; #188 + DB 036h, 036h, 036h, 036h, 0FEh, 000h, 000h, 000h ; #189 + DB 018h, 018h, 0F8h, 018h, 0F8h, 000h, 000h, 000h ; #190 + DB 000h, 000h, 000h, 000h, 0F8h, 018h, 018h, 018h ; #191 + DB 018h, 018h, 018h, 018h, 01Fh, 000h, 000h, 000h ; #192 + DB 018h, 018h, 018h, 018h, 0FFh, 000h, 000h, 000h ; #193 + DB 000h, 000h, 000h, 000h, 0FFh, 018h, 018h, 018h ; #194 + DB 018h, 018h, 018h, 018h, 01Fh, 018h, 018h, 018h ; #195 + DB 000h, 000h, 000h, 000h, 0FFh, 000h, 000h, 000h ; #196 + DB 018h, 018h, 018h, 018h, 0FFh, 018h, 018h, 018h ; #197 + DB 018h, 018h, 01Fh, 018h, 01Fh, 018h, 018h, 018h ; #198 + DB 036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h ; #199 + DB 036h, 036h, 037h, 030h, 03Fh, 000h, 000h, 000h ; #200 + DB 000h, 000h, 03Fh, 030h, 037h, 036h, 036h, 036h ; #201 + DB 036h, 036h, 0F7h, 000h, 0FFh, 000h, 000h, 000h ; #202 + DB 000h, 000h, 0FFh, 000h, 0F7h, 036h, 036h, 036h ; #203 + DB 036h, 036h, 037h, 030h, 037h, 036h, 036h, 036h ; #204 + DB 000h, 000h, 0FFh, 000h, 0FFh, 000h, 000h, 000h ; #205 + DB 036h, 036h, 0F7h, 000h, 0F7h, 036h, 036h, 036h ; #206 + DB 018h, 018h, 0FFh, 000h, 0FFh, 000h, 000h, 000h ; #207 + DB 036h, 036h, 036h, 036h, 0FFh, 000h, 000h, 000h ; #208 + DB 000h, 000h, 0FFh, 000h, 0FFh, 018h, 018h, 018h ; #209 + DB 000h, 000h, 000h, 000h, 0FFh, 036h, 036h, 036h ; #210 + DB 036h, 036h, 036h, 036h, 03Fh, 000h, 000h, 000h ; #211 + DB 018h, 018h, 01Fh, 018h, 01Fh, 000h, 000h, 000h ; #212 + DB 000h, 000h, 01Fh, 018h, 01Fh, 018h, 018h, 018h ; #213 + DB 000h, 000h, 000h, 000h, 03Fh, 036h, 036h, 036h ; #214 + DB 036h, 036h, 036h, 036h, 0FFh, 036h, 036h, 036h ; #215 + DB 018h, 018h, 0FFh, 018h, 0FFh, 018h, 018h, 018h ; #216 + DB 018h, 018h, 018h, 018h, 0F8h, 000h, 000h, 000h ; #217 + DB 000h, 000h, 000h, 000h, 01Fh, 018h, 018h, 018h ; #218 + DB 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh ; #219 + DB 000h, 000h, 000h, 000h, 0FFh, 0FFh, 0FFh, 0FFh ; #220 + DB 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h ; #221 + DB 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh ; #222 + DB 0FFh, 0FFh, 0FFh, 0FFh, 000h, 000h, 000h, 000h ; #223 + DB 000h, 000h, 062h, 094h, 088h, 094h, 062h, 000h ; #224 + DB 000h, 0F0h, 088h, 0F0h, 088h, 088h, 0F0h, 080h ; #225 + DB 000h, 0F8h, 088h, 080h, 080h, 080h, 080h, 000h ; #226 + DB 000h, 0FCh, 048h, 048h, 048h, 048h, 048h, 000h ; #227 + DB 0FCh, 084h, 040h, 020h, 040h, 084h, 0FCh, 000h ; #228 + DB 03Ch, 040h, 038h, 044h, 044h, 044h, 038h, 000h ; #229 + DB 000h, 000h, 044h, 044h, 044h, 078h, 040h, 040h ; #230 + DB 000h, 036h, 048h, 008h, 008h, 008h, 008h, 000h ; #231 + DB 038h, 010h, 038h, 044h, 044h, 038h, 010h, 038h ; #232 + DB 078h, 084h, 084h, 0FCh, 084h, 084h, 078h, 000h ; #233 + DB 078h, 084h, 084h, 084h, 048h, 048h, 0CCh, 000h ; #234 + DB 078h, 004h, 038h, 044h, 044h, 044h, 038h, 000h ; #235 + DB 000h, 000h, 06Ch, 092h, 092h, 06Ch, 000h, 000h ; #236 + DB 000h, 000h, 03Ah, 044h, 05Ah, 022h, 05Ch, 000h ; #237 + DB 018h, 020h, 040h, 078h, 040h, 020h, 018h, 000h ; #238 + DB 078h, 084h, 084h, 084h, 084h, 084h, 084h, 000h ; #239 + DB 000h, 0FCh, 000h, 0FCh, 000h, 0FCh, 000h, 000h ; #240 + DB 020h, 020h, 0F8h, 020h, 020h, 000h, 0F8h, 000h ; #241 + DB 020h, 010h, 008h, 010h, 020h, 000h, 07Ch, 000h ; #242 + DB 008h, 010h, 020h, 010h, 008h, 000h, 07Ch, 000h ; #243 + DB 00Ch, 012h, 010h, 010h, 010h, 010h, 010h, 010h ; #244 + DB 010h, 010h, 010h, 010h, 010h, 010h, 090h, 060h ; #245 + DB 000h, 010h, 000h, 07Ch, 000h, 010h, 000h, 000h ; #246 + DB 000h, 032h, 04Ch, 000h, 032h, 04Ch, 000h, 000h ; #247 + DB 038h, 044h, 044h, 038h, 000h, 000h, 000h, 000h ; #248 + DB 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h ; #249 + DB 000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h ; #250 + DB 00Eh, 008h, 008h, 008h, 048h, 028h, 018h, 008h ; #251 + DB 038h, 024h, 024h, 024h, 024h, 000h, 000h, 000h ; #252 + DB 03Ch, 004h, 03Ch, 020h, 03Ch, 000h, 000h, 000h ; #253 + DB 000h, 000h, 03Ch, 03Ch, 03Ch, 03Ch, 000h, 000h ; #254 + DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; #255 diff --git a/16/x/makefile b/16/x/makefile new file mode 100755 index 00000000..8ad2f244 --- /dev/null +++ b/16/x/makefile @@ -0,0 +1,81 @@ +# +# MODEX library makefile (for Borland MAKE) +# Copyright (c) 1993,1994 by Alessandro Scotti +# +LIBINCS = MODEX.DEF + +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 + +# +# ASM compiler +# +ASMC = tasm +ASMO = /m5 /p + +# +# PAS compiler +# +PASC = tpc +PASO = /m -$D- -$L- -$S- + +# +# LIB maker, uses response file +# +LIBC = tlib + +.asm.obj: + $(ASMC) $(ASMO) $< + +target: modex.lib +# modex.tpu modex.tpp + +#modex.tpu: $(LIBOBJS) modex.pas +# $(PASC) $(PASO) modex +# copy modex.tpu .. +# copy modex.pas .. + +#modex.tpp: $(LIBOBJS) modex.pas +# $(PASC) /cp $(PASO) modex +# copy modex.tpp .. + +modex.lib: modex.lbr $(LIBOBJS) + $(LIBC) modex.lib @modex.lbr + +$(LIBOBJS): modex.def diff --git a/16/x/modex.def b/16/x/modex.def new file mode 100755 index 00000000..45bd900f --- /dev/null +++ b/16/x/modex.def @@ -0,0 +1,163 @@ +;------------------------------------------------------------ +; +; MODEX.DEF - Include file +; Copyright (c) 1993-1994 by Alessandro Scotti +; +JUMPS +LOCALS + +TRUE EQU 1 ; Boolean constants +FALSE EQU 0 + +USE286 = FALSE ; TRUE enables 80286 instructions +USE386 = FALSE ; TRUE enables 80386 (and 80286) instructions + +IF USE286 EQ TRUE + P286 +ENDIF + +IF USE386 EQ TRUE + P386 + USE286 = TRUE +ENDIF + +MXVERSION EQU 0128h ; Library version (1.40) + +;------------------------------------------------------------ +; +; VGA definitions +; +MISC EQU 3C2h ; Miscellaneous output +TS EQU 3C4h ; Timing Sequencer index register +GDC EQU 3CEh ; Graphics Data Controller index register +CRTC EQU 3D4h ; CRTC index register +STATUS EQU 3DAh ; Input Status register one + +;------------------------------------------------------------ +; +; Raster operators +; +OP_SET EQU 0 +OP_MOVE EQU 0 ; Same as OP_SET +OP_AND EQU 1 +OP_OR EQU 2 +OP_XOR EQU 3 +OP_TRANS EQU 4 +OP_ADD EQU 5 ; Must be last op + +;------------------------------------------------------------ +; +; Polygon fill functions +; +POLYSCANBUFSIZE EQU 4*1024 + +;------------------------------------------------------------ +; Macro to push registers, variables or flags onto the stack +; Usage: .push "loc16"[,"loc16"...] +; where "loc16" is a 16-bit register, a word-sized variable or the +; keyword "FLAGS". +; Exmpl: .push ax, flags, var1 +; .pop ax, flags, var1 +; +.push MACRO r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10 + IFNB + .ERROR <.PUSH has more than 10 arguments> + ENDIF + IRP $reg, + IFB <$reg> ;; Is argument blank? + EXITM ;; Yes, exit + ELSEIFIDNI <$reg>, ;; Is argument the keyword "FLAGS"? + pushf ;; Yes, push flags + ELSE + push $reg ;; Push argument + ENDIF + ENDM +ENDM + +;------------------------------------------------------------ +; Macro to pop registers, variables or flags from the stack +; Usage: .pop "loc16"[,"loc16"...] +; where "loc16" is a 16-bit register, a word-sized variable or the +; keyword "FLAGS". +; Exmpl: .push ax, flags, var1 +; .pop ax, flags, var1 +; +.pop MACRO r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10 + IFNB + .ERROR <.POP has more than 10 arguments> + ENDIF + IRP $reg, + IFNB <$reg> ;; Is argument non-blank? + IFIDNI <$reg>, ;; Yes, is it the keyword "FLAGS"? + popf ;; Yes, pop flags + ELSE + pop $reg ;; Pop argument + ENDIF + ENDIF + ENDM +ENDM + +;------------------------------------------------------------ +; +.enter MACRO localsize + IF USE286 EQ TRUE + enter localsize, 0 + ELSE + push bp + mov bp, sp + sub sp, localsize + ENDIF +ENDM + +;------------------------------------------------------------ +; +.leave MACRO argsize + IF USE286 EQ TRUE + leave + ELSE + mov sp, bp + pop bp + ENDIF + IFNB + ret argsize + ELSE + ret + ENDIF +ENDM + +;------------------------------------------------------------ +; +.shr MACRO arg, count + IF USE286 EQ TRUE + shr arg, count + ELSE + $temp = count + WHILE $temp GT 0 + shr arg, 1 + $temp = $temp-1 + ENDM + ENDIF +ENDM + +;------------------------------------------------------------ +; +.shl MACRO arg, count + IF USE286 EQ TRUE + shl arg, count + ELSE + $temp = count + WHILE $temp GT 0 + shl arg, 1 + $temp = $temp-1 + ENDM + ENDIF +ENDM + +;------------------------------------------------------------ +; +.chk386 MACRO name, jump + IF USE386 EQ FALSE + .OUT "Warning: ", , " needs a 386 or better to run!" + jmp @@jump + ENDIF +ENDM diff --git a/16/x/modex.h b/16/x/modex.h new file mode 100755 index 00000000..2c1f1ebe --- /dev/null +++ b/16/x/modex.h @@ -0,0 +1,153 @@ +/* + MODEX.H - C/C++ include file for the MODEX library + Copyright (c) 1994 Alessandro Scotti +*/ + +#ifndef _MODEX_H_ // Avoid nested inclusions +#define _MODEX_H_ + +// +// Video modes +// +#define MX_TEXT 0 // 80x25 text +#define MX_320x175 1 // 320x175x256 +#define MX_320x200 2 // 320x200x256, 4 pages, aspect 6:5 +#define MX_320x240 3 // 320x240x256, 3 pages, aspect 1:1 +#define MX_320x350 4 // 320x350x256 +#define MX_320x400 5 // 320x400x256, 2 pages +#define MX_320x480 6 // 320x480x256, 1 page +#define MX_360x175 7 // 360x175x256 +#define MX_360x200 8 // 360x200x256, 3 pages +#define MX_360x240 9 // 360x240x256, 2 pages +#define MX_360x350 10 // 360x350x256 +#define MX_360x400 11 // 360x400x256, 1 page +#define MX_360x480 12 // 360x480x256, 1 page +#define MX_400x600 13 // 400x600x256, 1 page + +// +// Fade effects +// +#define MX_FADEIN 0 +#define MX_FADEOUT 1 + +// +// Raster ops +// +#define OP_SET 0 // No operator +#define OP_AND 1 // And +#define OP_OR 2 // Or +#define OP_XOR 3 // Xor +#define OP_TRANS 4 // Transparent +#define OP_ADD 5 // Additive +#define OP_MOVE 0 // Alias for OP_SET + +// +// Temporary definitions +// +#define MXBYTE unsigned char +#define MXBOOL short int +#define MXSINT short int +#define MXUINT unsigned short int +#define MXAPI far pascal +#define MXPTR void far * + +// Functions + +#ifdef __cplusplus // Avoid C++ name mangling +extern "C" { +#endif + +// +// Initialization +// +MXSINT MXAPI mxInit( void ); // Returns 0 if successful +void MXAPI mxTerm( void ); +MXUINT MXAPI mxGetVersion( void ); +// +// Mode setting +// +void MXAPI mxChangeMode( MXUINT mode ); +void MXAPI mxSetMode( MXUINT mode ); +void MXAPI mxGetAspect( MXUINT far *aspectx, MXUINT far *aspecty ); +void MXAPI mxGetScreenSize( MXUINT far *width, MXUINT far *height ); +// +// Hardware support +// +void MXAPI mxWriteMode( MXBYTE wm ); +void MXAPI mxSplitScreen( MXUINT line ); +void MXAPI mxStartAddress( MXUINT sa ); +void MXAPI mxStartLine( MXUINT sl ); +void MXAPI mxWaitDisplay( void ); +void MXAPI mxWaitRetrace( void ); +void MXAPI mxWritePlane( MXBYTE wp ); +void MXAPI mxReadPlane( MXBYTE rp ); +void MXAPI mxRowAddress( MXBYTE ra ); +// +// Virtual screen +// +void MXAPI mxGetVirtualScreen( MXUINT far *width, MXUINT far *height ); +void MXAPI mxSetVirtualScreen( MXUINT width, MXUINT height ); +void MXAPI mxPan( MXUINT x, MXUINT y ); +// +// Clipping +// +MXBOOL MXAPI mxGetClip( void ); +MXBOOL MXAPI mxGetClipRegion( MXSINT far *x, MXSINT far *y, MXSINT far *w, MXSINT far *h ); +MXBOOL MXAPI mxSetClip( MXBOOL ); +void MXAPI mxSetClipRegion( MXUINT x, MXUINT y, MXUINT width, MXUINT height ); +// +// Graphics +// +void MXAPI mxBitBlt( MXSINT sx, MXSINT sy, MXUINT width, MXUINT height, MXSINT dx, MXSINT dy ); +void MXAPI mxFillBox( MXSINT x, MXSINT y, MXUINT width, MXUINT height, MXUINT color, MXUINT op ); +MXBYTE MXAPI mxGetPixel( MXSINT x, MXSINT y ); +void MXAPI mxPutPixel( MXSINT x, MXSINT y, MXBYTE color ); +void MXAPI mxLine( MXSINT x1, MXSINT y1, MXSINT x2, MXSINT y2, MXUINT color, MXUINT op ); +void MXAPI mxGetImage( MXPTR img, MXSINT x, MXSINT y, MXUINT width, MXUINT height ); +void MXAPI mxPutImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT op ); +void MXAPI mxPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT width, MXUINT height ); +void MXAPI mxTransPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT w, MXUINT h ); +void MXAPI mxCircle( MXSINT x, MXSINT y, MXUINT radius, MXBYTE color ); +void MXAPI mxStretchImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT neww, MXUINT newh, MXUINT op ); +// +// Palette +// +void MXAPI mxColorToGray( MXPTR source, MXPTR dest, MXUINT count ); +void MXAPI mxGammaCorrect( MXPTR source, MXPTR dest, MXUINT count ); +void MXAPI mxGetColor( MXUINT index, MXSINT far *r, MXSINT far *g, MXSINT far *b ); +void MXAPI mxSetColor( MXUINT index, MXSINT red, MXSINT green, MXSINT blue ); +void MXAPI mxGetPalette( MXPTR palette, MXUINT index, MXUINT count ); +void MXAPI mxSetPalette( MXPTR palette, MXUINT index, MXUINT count ); +void MXAPI mxFadePalette( MXPTR, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT ); +void MXAPI mxRotatePalette( MXPTR palette, MXUINT count, MXSINT step ); +// +// Text +// +MXSINT MXAPI mxSetFont( MXPTR font, MXUINT charwidth, MXUINT charheight ); +void MXAPI mxSetTextColor( MXUINT color, MXUINT op ); +void MXAPI mxGetTextStep( MXSINT far *deltax, MXSINT far *deltay ); +void MXAPI mxSetTextStep( MXSINT deltax, MXSINT deltay ); +void MXAPI mxOutChar( MXSINT x, MXSINT y, char c ); +void MXAPI mxOutText( MXSINT x, MXSINT y, char far *sz ); +// +// Convex polygons +// +void MXAPI mxFillPoly( MXUINT, MXPTR, MXPTR, MXUINT, MXUINT ); +void MXAPI mxGouraudPoly( MXUINT, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT ); +void MXAPI mxTexturePoly( MXUINT, MXPTR, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT ); + +#ifdef __cplusplus +} +#endif + +// +// Remove temporary defines +// +#undef MXBYTE +#undef MXBOOL +#undef MXSINT +#undef MXUINT +#undef MXPTR +#undef MXAPI + +#endif // _MODEX_H_ diff --git a/16/x/modex.lbr b/16/x/modex.lbr new file mode 100755 index 00000000..b1ec26b6 --- /dev/null +++ b/16/x/modex.lbr @@ -0,0 +1,38 @@ ++-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 diff --git a/16/x/modex.pas b/16/x/modex.pas new file mode 100755 index 00000000..7d9d26ed --- /dev/null +++ b/16/x/modex.pas @@ -0,0 +1,194 @@ +(* + Turbo Pascal interface to the MODEX library + Copyright (c) 1993,1994 by Alessandro Scotti +*) +unit ModeX; +interface + +const + (* Video modes *) + MX_TEXT = 0; + MX_320x175 = 1; + MX_320x200 = 2; + MX_320x240 = 3; + MX_320x350 = 4; + MX_320x400 = 5; + MX_320x480 = 6; + MX_360x175 = 7; + MX_360x200 = 8; + MX_360x240 = 9; + MX_360x350 = 10; + MX_360x400 = 11; + MX_360x480 = 12; + MX_400x600 = 13; + + (* Fade effects *) + MX_FADEIN = 0; + MX_FADEOUT = 1; + + (* Raster ops *) + OP_SET = 0; + OP_AND = 1; + OP_OR = 2; + OP_XOR = 3; + OP_TRANS = 4; + OP_ADD = 5; + OP_MOVE = 0; (* Alias for OP_SET *) + +procedure mxBitBlt( SX, SY: integer; Width, Height: word; DX, DY: integer ); +procedure mxCircle( CX, CY: integer; Radius: word; Color: byte ); +procedure mxChangeMode( Mode: word ); +procedure mxColorToGray( ColorPalette, GrayPalette: pointer; Count: word ); +procedure mxFadePalette( Palette: pointer; Cmd, Start, Count, R, G, B: word ); +procedure mxFillBox( X, Y: integer; Width, Height: word; Color: byte; Op: word ); +procedure mxGammaCorrect( ColorPalette, GammaPalette: pointer; Count: word ); +procedure mxGetAspect( var AspectX, AspectY: word ); +function mxGetClipRegion( var X1, Y1, Width, Height: word ): boolean; +function mxGetClip: boolean; +procedure mxGetImage( Image: pointer; X, Y: integer; Width, Height: word ); +procedure mxGetPalette( Palette: pointer; Start, Count: word ); +function mxGetPixel( X, Y: word ): byte; +procedure mxGetScreenSize( var Width, Height: word ); +procedure mxGetTextStep( var DeltaX, DeltaY: integer ); +function mxGetVersion: word; +procedure mxGetVirtualScreen( var Width, Height: word ); +procedure mxInit; +procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word ); +procedure mxOutChar( X, Y: integer; C: char ); +procedure mxOutText( X, Y: integer; S: pointer ); +procedure mxPan( X, Y: word ); +procedure mxPutImage( Image: pointer; X, Y: integer; Width, Height, Op: word ); +procedure mxPutPixel( X, Y: word; C: byte ); +procedure mxPutTile( Tile: pointer; X, Y: integer; Width, Height: word ); +procedure mxReadPlane( Plane: byte ); +procedure mxRotatePalette( Palette: pointer; Count: word; Step: integer ); +procedure mxRowAddress( RowAddress: byte ); +function mxSetClip( Clip: boolean ): boolean; +procedure mxSetClipRegion( X1, Y1, Width, Height: word ); +procedure mxSetColor( Index, R, G, B: word ); +procedure mxSetFont( Font: pointer; Width, Height: word ); +procedure mxSetMode( Mode: word ); +procedure mxSetPalette( Palette: pointer; Start, Count: word ); +procedure mxSetTextColor( Color, Op: word ); +procedure mxSetTextStep( DeltaX, DeltaY: integer ); +procedure mxSetVirtualScreen( Width, Height: word ); +procedure mxStretchImage( Image: pointer; X, Y: integer; Width, Height, NewWidth, NewHeight, Op: word ); +procedure mxSplitScreen( Line: word ); +procedure mxStartAddress( StartAddress: word ); +procedure mxStartLine( Line: word ); +procedure mxTerm; +procedure mxTransPutTile( Tile: pointer; X, Y: integer; Width, Height: word ); +procedure mxWaitDisplay; +procedure mxWaitRetrace; +procedure mxWriteMode( Mode: byte ); +procedure mxWritePlane( Plane: byte ); + +procedure mxFillPoly( Count: word; var Map, Points; Color: word ); +procedure mxGouraudPoly( Count: word; var Map, Points, Colors; BaseColor: word ); +procedure mxTexturePoly( Count: word; var Map, Points, ImgPoints, Texture; Width: word ); + +procedure mxOutStr( X, Y: integer; S: string ); + +implementation + +procedure mxBitBlt; external; +procedure mxChangeMode( Mode: word ); external; +procedure mxCircle; external; +procedure mxColorToGray; external; +procedure mxFadePalette; external; +procedure mxFillBox; external; +procedure mxGammaCorrect; external; +procedure mxGetAspect( var AspectX, AspectY: word ); external; +function mxGetClipRegion; external; +function mxGetClip: boolean; external; +procedure mxGetImage; external; +procedure mxGetPalette( Palette: pointer; Start, Count: word ); external; +function mxGetPixel( X, Y: word ): byte; external; +procedure mxGetScreenSize( var Width, Height: word ); external; +procedure mxGetTextStep( var DeltaX, DeltaY: integer ); external; +function mxGetVersion: word; external; +procedure mxGetVirtualScreen( var Width, Height: word ); external; +procedure mxInit; external; +procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word ); external; +procedure mxOutChar( X, Y: integer; C: char ); external; +procedure mxOutText( X, Y: integer; S: pointer ); external; +procedure mxPan( X, Y: word ); external; +procedure mxPutImage; external; +procedure mxPutPixel( X, Y: word; C: byte ); external; +procedure mxPutTile; external; +procedure mxReadPlane( Plane: byte ); external; +procedure mxRotatePalette; external; +procedure mxRowAddress( RowAddress: byte ); external; +function mxSetClip( Clip: boolean ): boolean; external; +procedure mxSetClipRegion( X1, Y1, Width, Height: word ); external; +procedure mxSetColor( Index, R, G, B: word ); external; +procedure mxSetFont( Font: pointer; Width, Height: word ); external; +procedure mxSetMode( Mode: word ); external; +procedure mxSetPalette( Palette: pointer; Start, Count: word ); external; +procedure mxSetTextColor( Color, Op: word ); external; +procedure mxSetTextStep( DeltaX, DeltaY: integer ); external; +procedure mxSetVirtualScreen( Width, Height: word ); external; +procedure mxSplitScreen( Line: word ); external; +procedure mxStartAddress( StartAddress: word ); external; +procedure mxStartLine; external; +procedure mxStretchImage; external; +procedure mxTerm; external; +procedure mxTransPutTile; external; +procedure mxWaitDisplay; external; +procedure mxWaitRetrace; external; +procedure mxWriteMode( Mode: byte ); external; +procedure mxWritePlane( Plane: byte ); external; + +procedure mxFillPoly; external; +procedure mxGouraudPoly; external; +procedure mxTexturePoly; external; +{$L MXPB} +{$L MXPF} +{$L MXPG} +{$L MXPT} + +{$L MXBB} +{$L MXCC} +{$L MXCG} +{$L MXCL} +{$L MXCR} +{$L MXFB} +{$L MXFP} +{$L MXGI} +{$L MXGM} +{$L MXGP} +{$L MXGV} +{$L MXHL} +{$L MXIT} +{$L MXLN} +{$L MXOT} +{$L MXPI} +{$L MXPN} +{$L MXPP} +{$L MXRA} +{$L MXRP} +{$L MXSA} +{$L MXSC} +{$L MXSI} +{$L MXSL} +{$L MXSM} +{$L MXSP} +{$L MXSS} +{$L MXTL} +{$L MXVS} +{$L MXWD} +{$L MXWM} +{$L MXWP} +{$L MXWR} + +(* + Prints a Turbo Pascal string. + Note: BP 7.0 supports ASCIIZ strings (PChar type). +*) +procedure mxOutStr; +begin + S := S + #0; + mxOutText( X, Y, @S[1] ); +end; + +end. diff --git a/16/x/modex/DEMO01.EXE b/16/x/modex/DEMO01.EXE new file mode 100755 index 0000000000000000000000000000000000000000..28caff88c58a0b8ce5a4d23c6544c00cda8482fc GIT binary patch literal 10208 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 320 ) then begin + S.X := 320; + S.DX := -S.DX; + end; + if( S.X < -16 ) then begin + S.X := -16; + S.DX := -S.DX; + end; + if( S.Y > 240 ) then begin + S.Y := 240; + S.DY := -S.DY; + end; + if( S.Y < -16 ) then begin + S.Y := -16; + S.DY := -S.DY; + end; + (* Draw the sprite, note the Page offset added to the *) + (* Y coordinate of the image *) + mxPutImage( @S.Image, S.X, Page+S.Y, S.W, S.H, OP_TRANS ); +end; + +begin + (* Initialize library *) + mxInit; + + (* Enter graphics mode *) + mxSetMode( MX_320x240 ); + + (* Print initialization message *) + mxSetTextColor( 15, OP_TRANS ); + mxOutStr( 4, 4, 'Initializing...' ); + + (* Initialize sprites *) + for I:=1 to MAX_SPRITE do sxInit( S[I] ); + + (* Draw background *) + for I:=1 to 192 do begin + mxCircle( 160, 480+120, I, I+63 ); + mxCircle( 161, 480+120, I, I+63 ); + end; + + (* Compute and set palette *) + for I:=1 to 192 do with Palette[I+63] do begin + R := 0; + G := 0; + B := 0; + if( I < 64 ) then + R := I shr 1+31 + else if( I < 128 ) then + G := (I-64) shr 1+31 + else + B := (I-128) shr 1+31; + end; + mxSetPalette( @Palette[64], 64, 192 ); + + (* Main loop *) + Page := 240; + while( not KeyPressed ) do begin + (* Set clip region to current page *) + mxSetClipRegion( 0, Page, 320, 240 ); + mxSetClip( TRUE ); + (* Restore background *) + mxBitBlt( 0, 480, 320, 240, 0, Page ); + (* Draw sprites *) + for I:=1 to MAX_SPRITE do sxMove( S[I] ); + (* Print message *) + mxOutStr( 4, Page+4, 'Some sprites moving...' ); + (* Flip page *) + mxStartLine( Page ); + Page := 240-Page; + (* Animate palette *) + mxSetPalette( @Palette[64], 64, 192 ); + mxRotatePalette( @Palette[64], 192, 3 ); + end; + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/x/modex/DEMO02.EXE b/16/x/modex/DEMO02.EXE new file mode 100755 index 0000000000000000000000000000000000000000..14e7dc72b16e421ae94767feaa07cb3988f49db1 GIT binary patch literal 24688 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 L6~S)>H$VReFZ-F@ literal 0 HcmV?d00001 diff --git a/16/x/modex/DEMO02.PAS b/16/x/modex/DEMO02.PAS new file mode 100755 index 00000000..6b4fb6f9 --- /dev/null +++ b/16/x/modex/DEMO02.PAS @@ -0,0 +1,125 @@ +(* + DEMO02 - Texture mapping and palette rotation + (c) 1994 by Alessandro Scotti +*) +uses Crt, Modex, Plasma, Threed; + +const + LSIZE = 85; + Trans : TPoint = ( X:0; Y:0; Z:0 ); +type + T2DPoint = record + X, Y: integer; + end; + TTexture = record + Desc : array[ 0..3 ] of T2DPoint; + Width : word; + Data : array[ 1..64*64 ] of byte; + end; + TQuad = record + VtxCnt : word; + Vtx : array[ 0..3 ] of word; + Texture: word; + end; +var + Vtx : array[ 0..7 ] of TPoint; + XVtx : array[ 0..7 ] of TPoint; + VVtx : array[ 0..7 ] of T2DPoint; + Face : array[ 0..5 ] of TQuad; + Txts : array[ 0..5 ] of TTexture; + Nrm : array[ 0..5 ] of TPoint; + XNrm : array[ 0..5 ] of TPoint; + Page : word; + Palette: array[ byte ] of record R, G, B: byte; end; + +(* Make a 64x64 plasma to be used as texture *) +procedure MakeTexture( Idx: word ); +var + I: word; +begin + mxFillBox( 0, 0, 64, 64, 0, OP_SET ); + MakePlasma( 0, 0, 64, 64, 96, Random(192)+1, Random(192)+1, Random(192)+1 ); + mxGetImage( @Txts[Idx].Data, 0, 0, 64, 64 ); + (* Texture vertexes are 8:8 fixed, add $80 (0.5) for best results *) + with Txts[Idx] do begin + Desc[0].X := $80; Desc[0].Y := $80; + Desc[1].X := $80; Desc[1].Y := $3F80; + Desc[2].X := $3F80; Desc[2].Y := $3F80; + Desc[3].X := $3F80; Desc[3].Y := $80; + Width := 64; + end; +end; + +procedure Init; +var + I: integer; +begin + (* Build vertexes for a cube *) + with Vtx[0] do begin X:=-LSIZE; Y:=-LSIZE; Z:=-LSIZE; end; + with Vtx[1] do begin X:=+LSIZE; Y:=-LSIZE; Z:=-LSIZE; end; + with Vtx[2] do begin X:=-LSIZE; Y:=+LSIZE; Z:=-LSIZE; end; + with Vtx[3] do begin X:=+LSIZE; Y:=+LSIZE; Z:=-LSIZE; end; + with Vtx[4] do begin X:=-LSIZE; Y:=-LSIZE; Z:=+LSIZE; end; + with Vtx[5] do begin X:=+LSIZE; Y:=-LSIZE; Z:=+LSIZE; end; + with Vtx[6] do begin X:=-LSIZE; Y:=+LSIZE; Z:=+LSIZE; end; + with Vtx[7] do begin X:=+LSIZE; Y:=+LSIZE; Z:=+LSIZE; end; + for I:=0 to 7 do begin (* Make points 16:16 fixed *) + Vtx[I].X := Vtx[I].X*$10000; + Vtx[I].Y := Vtx[I].Y*$10000; + Vtx[I].Z := Vtx[I].Z*$10000; + end; + (* Build faces *) + with Face[0] do begin Vtx[0]:=0; Vtx[1]:=2; Vtx[2]:=3; Vtx[3]:=1; end; + with Face[1] do begin Vtx[0]:=4; Vtx[1]:=5; Vtx[2]:=7; Vtx[3]:=6; end; + with Face[2] do begin Vtx[0]:=0; Vtx[1]:=1; Vtx[2]:=5; Vtx[3]:=4; end; + with Face[3] do begin Vtx[0]:=1; Vtx[1]:=3; Vtx[2]:=7; Vtx[3]:=5; end; + with Face[4] do begin Vtx[0]:=2; Vtx[1]:=0; Vtx[2]:=4; Vtx[3]:=6; end; + with Face[5] do begin Vtx[0]:=7; Vtx[1]:=3; Vtx[2]:=2; Vtx[3]:=6; end; + for I:=0 to 5 do Face[I].Texture := I; + (* Build textures and palette *) + Randomize; + FillChar( Palette, SizeOf(Palette), 0 ); + MakePlasmaPalette( Palette, PAL_RGB ); + mxSetPalette( @Palette, 0, 193 ); + for I:=0 to 5 do MakeTexture( I ); +end; + +var + AX, AY, AZ: byte; + I: word; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; (* Start with hidden page *) + + AX := 0; + AY := 0; + AZ := 0; + (* Init 3D transforms, perspective is intentionally exaggerated *) + tdSetTranslation( Trans ); + tdSetPerspective( 400*$10000, $10000, $10000 ); + (* Main loop, all magic here! *) + while( not KeyPressed ) do begin + tdSetRotation( AX, AY, AZ ); (* Set new angles *) + tdTransform( Vtx, XVtx, 8 ); (* 3D transform points *) + tdTransformToImage( XVtx, VVtx, 8, 160, 120+Page ); + Inc( AX, 1 ); (* Bump angles *) + Inc( AY, 1 ); + Inc( AZ, 2 ); + mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *) + mxSetClip( TRUE ); + mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *) + mxRotatePalette( @Palette[1], 192, 3 ); (* Rotate palette *) + (* Draw cube: backface culling is straighforward in this case, so *) + (* it can be handled by the polygon filling procedure *) + for I:=0 to 5 do + mxTexturePoly( 4, Face[I].Vtx, VVtx, Txts[I].Desc, Txts[I].Data, Txts[I].Width ); + mxStartLine( Page ); (* Flip pages *) + mxSetPalette( @Palette[1], 1, 192 ); (* Set new palette *) + Page := 240-Page; + end; + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/x/modex/DEMO03.EXE b/16/x/modex/DEMO03.EXE new file mode 100755 index 0000000000000000000000000000000000000000..c646c4b0283db932174d915432747c2176034195 GIT binary patch literal 14256 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 RADIUS*RADIUS ) then goto Retry; + Z := Toggle( Round( Sqrt( Abs( RADIUS*RADIUS-X*X-Y*Y ) ) ) ); + case Random(3) of + 0: Swap( X, Z ); + 1: Swap( Y, Z ); + end; + X := X * $10000; Y := Y * $10000; Z := Z * $10000; + end; + end; + (* Initialize morphing *) + Move( CubeVtx^, Vtx^, SizeOf(Vtx^) ); + Status := 0; + Count := WAITCOUNT; +end; + +procedure Morph; +var + I: integer; +begin + (* Fully unoptimized, slowest loop I could think of! *) + for I:=0 to MAXVTX-1 do begin + Vtx^[I].X := ((CubeVtx^[I].X * Morph1)+(SphereVtx^[I].X * Morph2)) div MS; + Vtx^[I].Y := ((CubeVtx^[I].Y * Morph1)+(SphereVtx^[I].Y * Morph2)) div MS; + Vtx^[I].Z := ((CubeVtx^[I].Z * Morph1)+(SphereVtx^[I].Z * Morph2)) div MS; + end; +end; + +var + AX, AY, AZ: byte; + I: word; + C: char; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; (* Start with hidden page *) + + AX := 0; + AY := 0; + AZ := 0; + (* Init 3D transforms, perspective is intentionally exaggerated *) + tdSetTranslation( Trans ); + tdSetPerspective( 400*$10000, $10000, $10000 ); + C := #0; + repeat + tdSetRotation( AX, AY, AZ ); (* Set new angles *) + tdTransform( Vtx^, XVtx^, MAXVTX ); (* 3D transform points *) + tdTransformToImage( XVtx^, VVtx, MAXVTX, 160, 120+Page ); + Inc( AX, 1 ); (* Bump angles *) + Inc( AY, 1 ); + Inc( AZ, 2 ); + mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *) + mxSetClip( TRUE ); + mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *) + (* Draw points *) + for I:=0 to MAXVTX-1 do + mxPutPixel( VVtx[I].X, VVtx[I].Y, 128 + XVtx^[I].Z shr 18 ); + mxStartLine( Page ); (* Flip pages *) + Page := 240-Page; + (* Morph *) + if( Odd(Status) ) then begin + Morph; + Inc( Morph1, Delta1 ); + Inc( Morph2, Delta2 ); + if( Morph1 < 0 )or( Morph2 < 0 ) then Inc( Status ); + if( Status = 4 ) then Status := 0; + end + else begin + Dec( Count ); + if( Count < 0 ) then begin + Inc( Status ); + Count := WAITCOUNT; + Morph1 := InitMorph1[Status]; + Morph2 := InitMorph2[Status]; + Delta1 := InitDelta1[Status]; + Delta2 := InitDelta2[Status]; + end; + end; + until( KeyPressed ); + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/x/modex/DEMO04.DAT b/16/x/modex/DEMO04.DAT new file mode 100755 index 0000000000000000000000000000000000000000..72aaad08ac55e4d161e7868374296a4e42554684 GIT binary patch literal 37662 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%0D)*4A2IO9KMZYD#oU43C^WOCfTg8_%RD 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�-ncKj8QX2BIutynAlnfJ{;J0ue86t5F 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 XG;Ye`)EVP3#M6mPm!(a=?*#mR$DZhs literal 0 HcmV?d00001 diff --git a/16/x/modex/DEMO04.EXE b/16/x/modex/DEMO04.EXE new file mode 100755 index 0000000000000000000000000000000000000000..1fec5e8aa383353d986ca1e4420838b09e61eef4 GIT binary patch literal 24384 zcmeHve?U~#zVDj7_w3n>FrXk>+JGff;{@@;L*@W+RK~I-G6A)~I@Z+rWnG+sbIw(m z;+oEEq+XrVDQ?e8-8mC6QB`_c;#~)xXNxMa8x^)am%Rw30@3Zy{2-WSqciw;R zGP-83wZ1>rcYVI!wf36LUTg7+OjRPuAd`rZH@-PRAen^B<_Vcj2nj(-Lb?aZiu5ef zpo)-}7(#R`A$p|wND&+%F-S9!(vjvNEk!CoT8H!u(k7%AkR+trp+602A<}(F%aHzn z^hcyukUl`#k0c?5Xb72zWJ2171Pe(t(ln$vB%YL$+mKeN%E?PeJDGA4&X$vTNN*v% z$d!}YL_hj6kDG~fJCa#7k5iGY+%(lzZjE{?r`B%eVv$mja*@!@kx#DkD>p}~62Vq} zj&p|+pP@HS9C*5o57BF!rTz-bkZ1`N^K?o3cB@F$Zec6eQtCH2)dpuSBU%J8Py0Pe z76%e9S~xL}|2|0oNh|Zcan5rE&7ov$Pu0TMgF4laW$ z%1ei)*xN^mXLD|_SceoIgLAO}4z>L&3i?z9bnURmwJoKbbD*Lbz&rDX+|iH{sP|9C zQSV=>unbVOSEyB2sNcoOqUB0wPiId{=_Pi+;GA4;@iRY0$Ym&{yz~ldZvn5NEi2+_ zQhke2jGkqLb0;AXqNqJQ(JshZd|%@1gatoeO5@>KRtd(Z&ppc~HP-aT?YS{dpYLvz zbCe{I9Cv0g4ahl3jlutJ70HqQb`=t{;sSBB=V2<>4>_75ATyj$z9z>&uH@<-hUoLF z9>n-^$AS|H991`C+|dzX^#=z;{N`;PgWCB-u0;1E*=|} zbZ*jtGa>}hL7TR__Pjofm>)e)45G#1dRXbXdjYa@kSJ#V>fiLyS~)s@&ohiJzv?Q# zl?#+9v1*QHD_8X`H(UpbKRVw{Sc*eG!3h0(ba0cDew7-xCxPaZ zuDapDJ$jmtyIOrK;w!;ebECl-J=1{j^3aHyIvng%uMH7*1|1*b00r@lLQHsK5MQT7 za^{_Fv-nkn2EBinQCwdb$6EXi;P1W0ZO%KpR#Rp)TckBJf0{F(x4hJ^vA-i)Br)%- zGQvAgJLmT~ALxhkl(KXEXK@&;jEz0BOul9=$WF^Sd}pRJq%0GoRWVL1^>>~YKm07N z^E9sW`$Q-zJ$J3j{6K%1X6*#?{JvsL$bP7R0gSy>w45_rhHSHxCPg%fAs!G!e#8!p zbfq$AlL|JiktwKE1UHweFx+XzPT*DBaU*iG2%H_sej+9M+jxVapX}umjrdBUU&%&t zZLB3VHY{V7AQ&1{WaI+n<)lhr=W#+KT3oH#oM=ounX@@b`A(+a%D~)%8&v)tIt=C1 z-nc3eV^=Bd(a#7}xi^!XYJ)-jJJ|CU?wUg|!vQOpAy|Q6l2Z)^ccu#S0~k^h{G<-S zyDQ#LzDKJIOa`vo&?RMtnQioPGC$iWX3REro~CYp1E^ur#7q^uWnvymRk%`(bS5^W z8Zk#=z7(^BnmIo$}>`p zYWu&J!wecPzn0P4bVBUm2aRNO5Hufbv-KY#PlAOJ=7ig60L)=21C^% z4BIo$;wBXEUX=`A!r4iURnb^RjI0;hk<+{HS66mhMT^c_Q!n7EwbpE-SKeAvC&cXA zA4(LqynKaGEab&vK`hlaonV?yF-@l#Ypzw?u$r^_w&BYey&AF`R+Hgk5sLqYV$*e~*QC|Sk*L8yrg7+NR_Zs1AdOQ!z=ncK0kc3A`)I-9NJPUY&ibB^-&S+CQ#ejt>Q5h z7tk_VX4|ciN?AY|O|wnb$Rk#?1a9)2}>tiEn*N|!Z!YjcFPsVBnf z8?<8T396@F8?7F08>1ec3#bq3Mo)aJ{ehOSXbEbe-Wsh1?iiy5{urYLFpScY#g*?3 zEpH2zv-$A#8acdrrG{duCGA)`kHsdUr8Lxvc^&cVpoj=ov&CNu7g+o#F<2zRDCBso z^nd}QDCXpBt-TYG4Z8utuzuZ-`|9;!Uu_xo)te)}qQhpyS3RwYtE|+DM|}xz0s{;u z#54SaGQ`<#Yb44_5o%cv!uwG+`dwjtR~eJig@xC`g|HC)w(lCY3caSSSkcUw7#bA` zN+^wr1eC`_g5oO0ASEaED?#W>81Z#b!HBPe3dZ`{mjIIkULRI4;^v@&5jO`FjCJ!U z1$(VcQUuGRl*W}BD|Ik}e+;1A!Qc-D)&FtiD@H029~d$t{R|G7k$x%x<4YLZ zPs2YM#b|JJ+}=GpZqY4eLiMfYY0vlV7l<{_nr~$rt>s-HHCy476dB>@!UCynMiH=3^>#-7B8JU1M{P~%(OPv;KIt_r+P%eP?qOsNirxgsKs zWf}kzm6b*`QIT_Fnfze-*6O>)Ge8T$!Gb|b3v{SR`-h;WrF4?Q|H_ydjCxJ93|PNk zi%FJ_^B+`W2-A>@7!`7rg}^bQ(y9ewOj8ddc6au$-E3hf${a2CqukFHhg!u@t0~+n zF2(&OpEHQ+u|(8rtfCE<5=_u%Y0o!c)bFKv1;Mp~SSUQ&rjg}xi@>m@QFOq&h6j8E zf@SIY{4S{}Hv6@Dpk&IjFY4qtDB|-x~hGJ|w)>8vemUz#@FpL4x<%>ASJ7SbdkR zP3?GzR-znQeAzhD-gV2qM^6x=x!6m+)|bF6;M&w7u-yr*(IgfUT~_vpb;BojuZ;lrzFYNvH-LM30DxQ7t2_=5OJYhjc~va{D;`aLTaPj#Z|pqPl4 zezEVR^UKa&*EiVr$h8(muou~GX{jGF=Hfnk8@5L>vb=|flK!9)i^W_#wU|k{{?SSZ!RyHeaWS)gANJAWg=E*q$tRO9i5JAeP^H;4zqbcX{S?b}VEG7LvYZvO zPnp^iME&M?Q+H{Ese|cakA`v8eV$`2J$srY+x624T*I|GqGZ^-<5sV@g-X~v8!jJWvFTO zSw`g6H~#Jh7>b6X6MP135({7kT-KpFrlEyBFa3G&uw|$`?<`TaWDM93(v1rArSYi$ z`i7!xU{GMHu8SA-JL5%NeY_a`e!QcUSJ}d=-$v!TsN9CizsA>Wj(6&}#5;9cb{m-4j6{h1Q^b zi?#+9SOnG*dRGnXuwWaE_O6=uvql=Azuypxu(sYV?zbft#AO`mcpLCk>v+SWyx224jw7m01+72lU) zzj!pEdP_Wrh>5ncl!c}%rh#<~dlWUB+`hmg;io)xDLY=Fp^UTHC&d!VPdNyj~YSa zW48hDG`8frG-8|F*u%Pd>ez;Z*uiJH@-(HF+=f`wp0rItwAC@^F?`hPqYvCRq0xRFwnSER z97rm<5xY^bt9LiqjKXB>&#ElEQlU&I{+f3ZAxkHwA!UGdq%?M18)6}uQDn*qoT>2h zz?H02-N)px&u~lCj>ucU_iNR1W(8Zx6{=m4@i<#yk0vIfeB$~^1(R1rHw4SCPOO~t z+~k*{ccC1n$%r^Rv0~B}lTSy(bYfGjVjgAx%srw06aTEHKjh)?q=*M6Zkm)InH)tX zKOF6#t*_#Vnq;cl$@HXqlcI3GL<)OC1r#$?{iu2lu5PA=0+p%y8;nQ` z8Zo9SV8mOLDSo4N1=Xt%7|*MgF~31;&oQ%-Ur2f*DLvVp)RB~v{CUzhNvo2% zQJCtiNRErNi=>XGwPFDY1TivOmuq z3E4s#)*OExTg%TkG_%|KXqm9*v2nF-V&A-TGt2t6*YHW(YXl@FsZ;8dYP865N#f_= z5pSPAfBhw!uzh`_?c#awfSk%C$+zpIt}9dzh6}w7q{zFll4!hGJFGO+(U;O#%_IdT zab{%a&nTNqegUh7Ypb!dlhqp|WJ;2It zdg&IjC)=pc*GaLglBsIL(II=XXVI!KR3TIK4^$O&)Q3wStJ5?#Z5mt5BM_uqBK?Kb z3(2zdA8J?2%(5+uj9W5|DUDmq#x3_4x7=&Y+%nf#$zKun{Dv4@HyGyLU>n5MeNui! zN@IM7eO1klX_4BUIPn9rlSr9r$CX+3XoEwyfv6Bxy9h7cs;-~(UaSEHBLY8FMqF56|?M+Bja8pv8z0^OzKq!qHTOVIS}prwysdRfvuY_O=Tq=d&W5= zewHdO9_J`1t#3*QR&Lprn*XmRM&lcs_RK^ZfD8ObH6LOX=wlNVulX>Zraek zxw^ZIC6Pl1<|f>2EScbphB>+gM(O7)g2YXDS4O5$)Xl>&38+lvM9`%;wnMregDODW z@1mq>T!&kw@v?3epCesmmQgtuo^hzLLwbjC?VZKXr+KPlA@_E_jhh)B>Tnn` zjZX=DrZL#zh1^Wd4z8<*);|}lr+Ht8Lzih3Is)iWCE|VDiAWj@DKes_+G0%UlGLR4 z5){R&Nck~Rq^2Qt(L;Gxa_;|}-7txmkF2@ghjr}9N8V=bLMVIck-GO!&3AcD&2zP# zng`L7kIeL+dZfdVaSuEvP@mNi8&jw1*nAIsj!JE#eNytt1JSr@HyZ9SYERk`fKucT zY|^K;mT_3y*Bx!k;v8htdIxc4g;o^ka2(3xY{lY9d$STr46q5Zy8puNUdM?YPp@Nk z9JOg7x$~&|UQXGItyp}$bMf?w#d<8pAeSqiqf09>ms_;RAld~(%ev5% zU9LyVIuGZcbC#Zc5{Ax2Iiiv!sRD?n{d;I%Ga(>o9Co z&6i##=Ff{8#f#qmm~h!kZs-pIKq*usYPdqb3JRuYI5Pc$o*Kj<0SOM|p{ z>d?Xammu87jF2eRishbqHd#KSRn;@Nuqu6}{)!+*=a3lu%<#c(*fRt6+)8bMO?NB| z8jvQfCQ`Mmw0EoY3j*yLozzTLEcZ^A9w3TEk+3LSvJmO_vR5Nz5X!tz^ohrM-;@%G z(v%ZTx%OT%EF#I5*k&C361|Gl>H56H)jAK~i|WE@zG+@xjK}P=t-60nzMdBknGPz# zt~NzbW<5ARXn=~AH}j5+yNM>InuOTd>LJ0UPdCy&^D&i;e(iBv^fp)bxwlpJ!7KQ- z4T_%H!QOLT-gSCgZLePwvl4*h<>>A~ZO+z(X2vTEVdjzE4Q`T6#w-Z6;!iI+E<* zjz|?(`9x^rdxTF&g|1iFlWqFw4rW&* zdETF}t^Q{RW;k!CpwEc7-t%;}55-iC*}frC<-Untj}!MydgWB^JLz4(jhj-AKF7U^ z(c!ns4o)YT)Nb62uGPJUy6I}H7+-zRaXS2g*Ir%j_^RJ=wcn=8bR6mrmTjucElh|9 zfya=+@)mws`RSOa+g>6L{~c@CJ+ho%zx2Qi@th+&TD9!K#hS9nbNKB3$j;nbZKoceP@i~gig(Fk>sxYL{zYEB6?7Xu^1PV1|b<(`MW>bN0_tZ=Z9= zTyt7_#+~*h_SLpu{`Rrh$BK%cEQ%$ukJw^KLYS81JXvJ><&&$|#Lj>6soxj<^6@8Z zvA3);#wOh{C*{^Vl4IvRS@fGnRzHfV5Wk|NMp973!h7xxa^|U_KxIp|P~nmOMMWt* zasPvy$)k5zOh*3d!$NI!mr#3cdTL2`W*inO_%6Yj(T(dd0kqwI#(VqI%_PFBW*2Zp z-?2;i*4Y)u&0pC2J-er~-f8Bgd`Vc5+Pr{U!{bqfI6^<=ss0%A#V3M^KP*g(?h@j{ ziC)a;5?WKc1^Gw}hDx)z-|=OCd2cw|ggyQp2#%7PDw9;E+Jp8#t!xqxRd@_7=@om; zsa=9?rNNxbmv|8+<}9w{1dr#j1~JSa7BIFHnq7<;wg8VRrX4H)GMsH=KjHeJb!NCY zP}yvFPHlKDi^1bz9MV>Rd7{FzQe$w2p};I#F@U&##WPC846}=bk~lN}u}~7j=Zlvs zJvD~~CwhTj^LUhn6B%-3eUCt8<JC{NlH%l?xa+g~3@%Q3kWRD4cp|tx$&H3=gR~-22FxuLj*m$(b(()r2Vu zGqtP<@pYT|exV4|{p3vBU_(k5T?4d~38}3m9BzNL?z*G3ZU?DFwzhUtmaVn|b%#T0 z-CH@-?b4BpwY%;k6T0jn+vc_xbFTIi!Zr*|_TAorYnu-;QbTuT>{6k1&A!6u=& z!h2b|;d^tI7U!ij>^SNb8g?G_vJLMY9bQyqG3i)^OiJH*)E1UrchrU-au)aFW-}L3pPtg?<=rF=$6qNJ2^1UPd_BFs7sLp7&(2W*zn837 zW^k-aB(_QVO}UADOv*k?=WBRC{CFYT??UIQ^)}iP#gn>@BwFe>hElLlz7$knGKHxEY?b&$@XdbC9Qc_gDUux6{(gh+F-~l6%?ov%fF%cJ zERQLQ!E=3|9Vbol70nZl+Ati|-sxtG);7hdqrHXZ5gH9bb-{k!utkex`waZZ4QQoc zKs~!(JPh4#GB4P}0t^pF1{1;*O~W5DA_6CsG<``kpW>XOGs=k}9e5atN0K>9#J#=~ zIDWAWk0;w#EMt$bo%lUKg>U|$u&prgXC)lxqnw)*zO^HwBRA#i30=PzvV7f`ihakh zw$Awdgsd#zroq;~oBrw_iMxa=i2FH9}BX)?&LR*i1ptNqrmLB?)k(bhyvJdJQcrD&Rf5EK*0TU%)3OaMspB!YDg9PS*H5isD$IacgSO@B^ zx3TlR7sMl`!@FcTsD-MdpL_k_<0x~G;J;GjON03s zN8lf&IgqY`Mw5f!IUj?kri5^K2uPp$sR@r72HzUgv-svfrH=?Xb;7rFe`56M&AO@uw!N+xygBg|h8ko3i!B+CH^|+C%N4_E9^jz0_`MKkWzY5A7H2AMGdYFYPz&KgEIKL2;q@P@E`U6gP?= z#gXDkai#cDoGIQEcZxst1N8^>3-u566ZIGM8}%RcBlRcsEA=n+Gxaz1JN?vta9Ljb z)J6G=SzpV`rBm|GcY5S6o;)TWHGeEWuRACYN^Nr3KbqwC-Mi(}fBU;!x$|%GOHJ>{ z-v6wT?ZWHww0SSfjp7Tkf_!ME zN#6d!&GM;V&y)v$K0|(Du3mmCcba_5AE(O8FHM%Wtc{d^aq~oZ;F3<>ZST=JG4F8E^VLMLG7V-QTwQ!)Lv>gwV(Eb_J{V1_K)_H_LugX_MhTF@u0X+ zd?-#7FNzz*kK#!2q_|RiDb5sciaW)h`hog``i1(3`ic6B`i=UJ`jPsR`jz^Z`kDHh z`W^irkN@%bSH{DC)A;}Ie*dGlfPeafzs+Kefln;`8vBuz+w0i6pD0CS60#Y;*xUrG Im202>1y)VB#{d8T literal 0 HcmV?d00001 diff --git a/16/x/modex/DEMO04.PAS b/16/x/modex/DEMO04.PAS new file mode 100755 index 00000000..1a946315 --- /dev/null +++ b/16/x/modex/DEMO04.PAS @@ -0,0 +1,198 @@ +(* + DEMO04 - Multiple textures and triple buffering (3 pages) + (c) 1994 by Alessandro Scotti +*) +uses Crt, Modex, Threed; + +const + MAXVTX = 256; + MAXCUB = 2; + MAXTXT = 2; + Trans : TPoint = ( X:0; Y:0; Z:0 ); + TxtSunDial: array[ 0..7 ] of word = ( + $7F80,$0080, $0080,$0080, $0080,$7E80, $7F80,$7E80 ); + TxtSapphire : array[ 0..7 ] of word = ( + $0080,$0080, $0080,$1F80, $1F80,$1F80, $1F80,$0080 ); + TxtMarble: array[ 0..7 ] of word = ( + $0080,$8080, $0080,$FD80, $7F80,$FD80, $7F80,$8080 ); +type + T2DPoint = record + X, Y: integer; + end; + TTexture = record + Desc : array[ 0..3 ] of record X, Y: word end; + Width : word; + Data : pointer; + end; + TQuad = record + Vtx : array[ 0..3 ] of word; + Texture: word; + end; + TCube = record + Face : array[ 0..5 ] of TQuad; + Base : integer; + end; +var + Vtx, XVtx: array[ 0..MAXVTX ] of TPoint; + VVtx : array[ 0..MAXVTX ] of T2DPoint; + Cube : array[ 0..MAXCUB ] of TCube; + ZList : array[ 0..MAXCUB ] of integer; + VtxCnt : word; + Txts : array[ 0..MAXTXT ] of TTexture; + Page : word; + Palette : array[ byte ] of record R, G, B: byte; end; + TxtDat1, TxtDat2: pointer; + +(* Add a new entry to the vertex array *) +procedure AddVtx( PX, PY, PZ: longint ); +begin + with Vtx[VtxCnt] do begin X:=PX*$10000; Y:=PY*$10000; Z:=PZ*$10000; end; + Inc( VtxCnt ); +end; + +procedure MakeCube( var C: TCube; X1,Y1,Z1, X2,Y2,Z2, TX,TY,TZ, Texture: integer ); +const + FaceIdx: array[ 0..23 ] of integer = ( + 0,1,2,3, 0,4,5,1, 1,5,6,2, 2,6,7,3, 3,7,4,0, 6,5,4,7 ); +var + I, VC: integer; +begin + VC := VtxCnt; + C.Base := VC; + AddVtx( X1+TX, Y1+TY, Z1+TZ ); + AddVtx( X2+TX, Y1+TY, Z1+TZ ); + AddVtx( X2+TX, Y2+TY, Z1+TZ ); + AddVtx( X1+TX, Y2+TY, Z1+TZ ); + AddVtx( X1+TX, Y1+TY, Z2+TZ ); + AddVtx( X2+TX, Y1+TY, Z2+TZ ); + AddVtx( X2+TX, Y2+TY, Z2+TZ ); + AddVtx( X1+TX, Y2+TY, Z2+TZ ); + for I:=0 to 23 do C.Face[I shr 2].Vtx[I and 3] := VC+FaceIdx[I]; + for I:=0 to 5 do C.Face[I].Texture := Texture; +end; + +procedure MakeTexture( Idx: integer; var VtxData ); +var + P: ^word; + I: integer; +begin + P := @VtxData; + with Txts[Idx] do begin + for I:=0 to 3 do begin + Desc[I].X := P^; Inc( P ); + Desc[I].Y := P^; Inc( P ); + end; + Width := 129; + Data := TxtDat1; + end; +end; + +procedure Init; +var + I: integer; + V: integer; + F: file; + P: array[ 1..768 ] of byte; +begin + (* Initialize objects *) + VtxCnt := 0; + MakeCube( Cube[0], -64,-64,8, 64,64,-8, 0,0,0, 1 ); (* Sundial *) + Cube[0].Face[0].Texture := 0; + V := VtxCnt; + MakeCube( Cube[1], -16,-16,16, 16,16,-16, 0,0,0, 2 ); (* Sapphire *) + tdSetTranslation( Trans ); + tdSetRotation( 32, 32, 00 ); + tdRotate( Vtx[V], XVtx[V], 8 ); (* Got to rotate this cube *) + for I:=V to V+7 do begin + Vtx[I].X := XVtx[I].X; + Vtx[I].Y := XVtx[I].Y; + Vtx[I].Z := XVtx[I].Z + 100*$10000; + end; + MakeCube( Cube[2], -64,-4,48, 64,4,-48, 0,68,56, 1 ); (* Marble *) + (* Load texture and palette *) + Assign( F, 'DEMO04.DAT' ); + Reset( F, 1 ); + BlockRead( F, P, SizeOf(P) ); + mxSetPalette( @P, 0, 256 ); + GetMem( TxtDat1, 63*1024 ); + BlockRead( F, TxtDat1^, 129*286 ); + Close( F ); + TxtDat2 := Ptr( Seg(TxtDat1^), Ofs(TxtDat1^)+129*254 ); + (* Init textures *) + MakeTexture( 0, TxtSundial ); + MakeTexture( 1, TxtMarble ); + MakeTexture( 2, TxtSapphire ); + Txts[2].Data := TxtDat2; +end; + +(* Sort procedure, not worth optimizing with only a few objects *) +procedure SortObjects; +var + I, J, K: integer; + ZMax: array[ 0..MAXCUB ] of longint; + ZI: integer; + L: longint; +begin + for I:=0 to MAXCUB do begin + L := XVtx[Cube[I].Base].Z; + for J:=1 to 7 do + if( L > XVtx[Cube[I].Base+J].Z ) then L := XVtx[Cube[I].Base+J].Z; + ZMax[I] := L; + ZList[I] := I; + end; + for I:=0 to MAXCUB-1 do begin + ZI := I; + for J:=I+1 to MAXCUB do + if( ZMax[ZList[J]] > ZMax[ZList[ZI]] ) then ZI := J; + if( ZI <> I ) then begin + K := ZList[I]; + ZList[I] := ZList[ZI]; + ZList[ZI] := K; + end; + end; +end; + +var + AX, AY, AZ: byte; + I, J, K: word; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; (* Start with hidden page *) + + (* Init 3D transforms, perspective is intentionally exaggerated *) + AX := 0; AY := 0; AZ := 0; + tdSetTranslation( Trans ); + tdSetPerspective( 600*$10000, $10000, $10000 ); + (* Main loop, all magic here! *) + while( not KeyPressed ) do begin + tdSetRotation( AX, AY, AZ ); (* Set new angles *) + tdTransform( Vtx, XVtx, VtxCnt ); (* 3D transform points *) + tdTransformToImage( XVtx, VVtx, VtxCnt, 160, 120+Page ); + Inc( AX, 1 ); (* Bump angles *) + Inc( AY, 2 ); + Inc( AZ, 1 ); + mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *) + mxSetClip( TRUE ); + mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *) + (* Draw objects *) + SortObjects; + for I:=0 to MAXCUB do with Cube[ZList[I]] do begin + for J:=0 to 5 do begin + K := Face[J].Texture; + mxTexturePoly( 4, Face[J].Vtx, VVtx, Txts[K].Desc, Txts[K].Data^, Txts[K].Width ); + end; + end; + (* Flip page: at 320x240 the Start Address Register Low is always zero *) + case Page of + 0 : begin PortW[$3D4] := $000C; Page := 240; end; + 240: begin PortW[$3D4] := $4B0C; Page := 480; end; + 480: begin PortW[$3D4] := $960C; Page := 0; end; + end; + mxWaitRetrace; (* If the frame rate seems low, try to remove this line *) + end; + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/x/modex/DEMO05.EXE b/16/x/modex/DEMO05.EXE new file mode 100755 index 0000000000000000000000000000000000000000..21a7c207f7134ed187a08530637509b96b37b19e GIT binary patch literal 22528 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 CoI~RP literal 0 HcmV?d00001 diff --git a/16/x/modex/DEMO05.PAS b/16/x/modex/DEMO05.PAS new file mode 100755 index 00000000..819c5cf3 --- /dev/null +++ b/16/x/modex/DEMO05.PAS @@ -0,0 +1,131 @@ +(* + DEMO05 - A Gouraud-shaded rotating torus + (c) 1994 Alessandro Scotti +*) +uses Crt, Modex, Threed; + +(* Define ALTPAL for alternate palette *) +{$define ALTPAL} + +const + MAXVTX1 = 15; RADIUS1 = 70; (* MAXVTX1+1 must be multiple of 4 *) + MAXVTX2 = 15; RADIUS2 = 30; + MAXVTX = (MAXVTX1+1)*(MAXVTX2+1)-1; + MAXFACE = MAXVTX; + Trans : TPoint = ( X:0; Y:0; Z:0 ); (* Object translation *) + Light : TPoint = ( X:0; Y:0; Z:-63*$10000 ); (* Light direction *) +type + TQuad = record + QVtx : array[ 0..3 ] of integer; + end; +var + Vtx, XVtx : array[ 0..MAXVTX ] of TPoint; (* Points *) + VVtx : array[ 0..MAXVTX ] of record X, Y: integer end; + Face : array[ 0..MAXFACE ] of TQuad; (* Polys *) + Culled : array[ 0..MAXFACE ] of integer; + GNrm,XGNrm: array[ 0..MAXVTX ] of TVector; (* Gouraud normals *) + VtxLight : array[ 0..MAXVTX ] of integer; (* Points brightness *) + Page : word; + +function GetVtx( I1, I2: integer ): integer; +begin + GetVtx := (I1 mod (MAXVTX1+1))*(MAXVTX2+1) + I2 mod (MAXVTX2+1); +end; + +procedure Init; +var + R, N, X, Y, Z: real; + I, J, K, V: integer; +begin + (* Build vertexes *) + for I:=0 to MAXVTX1 do begin + K := (I + (MAXVTX1+1) shr 2) mod (MAXVTX1+1); + R := RADIUS1 + RADIUS2*Cos( 2*K*Pi / (MAXVTX1+1) ); + for J:=0 to MAXVTX2 do begin + V := I*(MAXVTX2+1)+J; (* Index of current vertex *) + (* Compute coordinates of current vertex *) + X := R*Cos(2*J*Pi / (MAXVTX2+1)); (* Get coordinates *) + Y := R*Sin(2*J*Pi / (MAXVTX2+1)); + Z := RADIUS2*Sin(2*K*Pi / (MAXVTX1+1)); + Vtx[V].X := Round( X )*$10000; (* Save coordinates *) + Vtx[V].Y := Round( Y )*$10000; + Vtx[V].Z := Round( Z )*$10000; + (* Compute direction of Gouraud normal thru current vertex *) + X := X - RADIUS1*Cos(2*J*Pi / (MAXVTX2+1)); + Y := Y - RADIUS1*Sin(2*J*Pi / (MAXVTX2+1)); + N := Sqrt( X*X + Y*Y + Z*Z ); (* Get vector length *) + GNrm[V].X := Trunc( X*$10000/N ); (* Save normal vector *) + GNrm[V].Y := Trunc( Y*$10000/N ); + GNrm[V].Z := Trunc( Z*$10000/N ); + end; + end; + (* Generate faces so that depth-sorting is not needed: there are still *) + (* some *very* little errors, but this is the best I could devise *) + J := 0; + K := 0; + for I:=0 to MAXFACE do with Face[I] do begin + QVtx[0] := GetVtx( J, K ); + QVtx[1] := GetVtx( J, K+1 ); + QVtx[2] := GetVtx( J+1, K+1 ); + QVtx[3] := GetVtx( J+1, K ); + Inc( K ); + if( K > MAXVTX2 ) then begin + K := 0; + Inc( J ); + end; + end; +{$ifndef ALTPAL} + for I:=0 to 63 do mxSetColor( I+64, 0, 0, I ); (* Blue palette *) +{$else} + for I:=0 to 31 do mxSetColor(I+64, 0, I shl 1, 0); (* Green neon palette *) + for I:=32 to 63 do mxSetColor ( I+64, (I-32) shl 1, 63, (I-32) shl 1 ); +{$endif} +end; + +var + AX, AY, AZ: byte; + I: word; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; (* Start with hidden page *) + + AX := 0; + AY := 0; + AZ := 0; + (* Init 3D transforms, perspective is intentionally exaggerated *) + tdSetTranslation( Trans ); + tdSetLight( Light ); + tdSetPerspective( 400*$10000, $10000, $10000 ); + (* Main loop, all magic here! *) + while( not KeyPressed ) do begin + tdSetRotation( AX, AY, AZ ); (* Set new angles *) + tdTransform( Vtx, XVtx, MAXVTX+1 ); (* 3D transform points *) + tdTransformToImage( XVtx, VVtx, MAXVTX+1, 160, 120+Page ); + tdRotate( GNrm, XGNrm, MAXVTX+1 ); (* Rotate Gouraud normals *) + tdTransformLight( XGNrm, VtxLight, MAXVTX+1 ); + (* Backplane culling is not really needed here! *) + FillChar( Culled, SizeOf(Culled), 0 ); + tdBackPlaneCull( Face, XVtx, Culled, MAXFACE+1, SizeOf(TQuad) ); + Inc( AX, 1 ); (* Bump angles *) + Inc( AY, 2 ); + Inc( AZ, 3 ); + mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *) + mxSetClip( TRUE ); + mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *) + (* Draw polygons *) + for I:=0 to MAXFACE do with Face[I] do + if( Culled[I] >= 0 ) then mxGouraudPoly( 4, QVtx, VVtx, VtxLight, 64 ); + (* Flip page: at 320x240 the Start Address Register Low is always zero *) + case Page of + 0 : begin PortW[$3D4] := $000C; Page := 240; end; + 240: begin PortW[$3D4] := $4B0C; Page := 480; end; + 480: begin PortW[$3D4] := $960C; Page := 0; end; + end; + mxWaitRetrace; (* Uncomment this instruction if screen flickers *) + end; + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/x/modex/DEMO06.DAT b/16/x/modex/DEMO06.DAT new file mode 100755 index 0000000000000000000000000000000000000000..1ac2c2bb8f8c79a7cf1f3c968f75e8e5ac8cd705 GIT binary patch literal 77568 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 P3zel81wBCVexm$;I2yv& literal 0 HcmV?d00001 diff --git a/16/x/modex/DEMO06.EXE b/16/x/modex/DEMO06.EXE new file mode 100755 index 0000000000000000000000000000000000000000..f1308e8a536aa9d3d4574566fd018d698d5ef784 GIT binary patch literal 10864 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 G@BaZ%)XT^K literal 0 HcmV?d00001 diff --git a/16/x/modex/DEMO06.PAS b/16/x/modex/DEMO06.PAS new file mode 100755 index 00000000..f26af067 --- /dev/null +++ b/16/x/modex/DEMO06.PAS @@ -0,0 +1,135 @@ +(* + DEMO06 - Magnifying glass + (c) 1994 Alessandro Scotti +*) +uses Crt, Modex; + +const + R = 40; (* Lens radius *) + K : real = 1.8; (* Magnifying factor, less makes a stronger lens *) +type + TLine = array[ 0..319 ] of byte; + PLine = ^TLine; + TScreen = array[ 0..239 ] of PLine; +var + VScreen: TScreen; (* Virtual screen *) + BallX : array[ 0..R, 0..R ] of integer; + BallY : array[ 0..R, 0..R ] of integer; + Sprite : array[ -R..R, -R..R ] of byte; + Page : word; + +(* Returns "lens-view" coordinates of X,Y *) +procedure GetCoords( var X, Y: integer ); +var + LR, Z, SinA, SinB, TgB, Q: real; +begin + LR := Sqrt( X*X + Y*Y ); + if( LR = 0 ) then Exit; + if( LR < R ) then begin + Z := Sqrt( R*R - LR*LR ); + SinA := LR / R; + SinB := SinA / K; + TgB := SinB / Sqrt( 1-SinB*SinB ); + Q := LR - TgB*Z; + X := Round( X * ( Q/LR ) ); + Y := Round( Y * ( Q/LR ) ); + end; +end; + +procedure Init; +var + F : file; + Palette: array[ 0..767 ] of record R, G, B: byte; end; + X, Y, + X2, Y2 : integer; +begin + (* Load background image *) + Assign( F, 'demo06.dat' ); + Reset( F, 1 ); + BlockRead( F, Palette, 768 ); + mxSetPalette( @Palette, 0, 256 ); + for Y:=0 to 239 do begin + New( VScreen[Y] ); + BlockRead( F, VScreen[Y]^, 320 ); + mxPutImage( VScreen[Y], 0, 480+Y, 320, 1, OP_MOVE ); + end; + Close( F ); + (* Build lens *) + for X:=0 to R do begin + for Y:=0 to R do begin + X2 := X; + Y2 := Y; + GetCoords( X2, Y2 ); + BallX[X, Y] := X2; + BallY[X, Y] := Y2; + end; + end; +end; + +procedure PutLens( OX, OY: integer ); +var + X, Y: integer; +begin + for X:=0 to R do begin + for Y:=0 to R do begin + Sprite[Y][X] := VScreen[ OY+BallY[X,Y] ]^[ OX+BallX[X,Y] ]; + Sprite[Y][-X] := VScreen[ OY+BallY[X,Y] ]^[ OX-BallX[X,Y] ]; + Sprite[-Y][X] := VScreen[ OY-BallY[X,Y] ]^[ OX+BallX[X,Y] ]; + Sprite[-Y][-X] := VScreen[ OY-BallY[X,Y] ]^[ OX-BallX[X,Y] ]; + end; + end; + (* Draw the sprite *) + mxPutImage( @Sprite, OX-R, OY-R+Page, 2*R+1, 2*R+1, OP_MOVE ); +end; + +function Delta: integer; +begin + Delta := Random(3)+2; +end; + +procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer ); +begin + if( Cond ) then begin + Coord := NewCoord; + DeltaC := Sign*Delta; + end; +end; + +var + X, Y, DX, DY: integer; + C: char; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; + X := R; + Y := R; + Randomize; + DX := Delta; + DY := Delta; + + (* Main loop *) + repeat + (* Update video *) + mxBitBlt( 0, 480, 320, 240, 0, Page ); + PutLens( X, Y ); + mxCircle( X, Page+Y, R, 0 ); + (* Update lens coordinates *) + Inc( X, DX ); + Check( X+R >= 319, X, DX, 319-R, -1 ); + Check( X <= R, X, DX, R, +1 ); + Inc( Y, DY ); + Check( Y+R >= 239, Y, DY, 239-R, -1 ); + Check( Y <= R, Y, DY, R, +1 ); + (* Flip pages: double buffering, avoid wait for display *) + case Page of + 0 : begin PortW[$3D4] := $000C; Page := 240; end; + 240: begin PortW[$3D4] := $4B0C; Page := 0; end; + end; + mxWaitRetrace; (* Wait for hidden page to show *) + until( KeyPressed ); + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/x/modex/DEMO07.EXE b/16/x/modex/DEMO07.EXE new file mode 100755 index 0000000000000000000000000000000000000000..8a401169bba312a0d668452c9df6086505c394a8 GIT binary patch literal 7440 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 639, X, DX, 319, -1 ); + Check( X < 0, X, DX, 0, +1 ); + Inc( Y, DY ); + Check( Y+200 >= 399, Y, DY, 199, -1 ); + Check( Y < 0, Y, DY, 0, +1 ); + mxPan( X, Y ); + mxWaitRetrace; + end; + + (* Shutdown *) + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/x/modex/MATH.INC b/16/x/modex/MATH.INC new file mode 100755 index 00000000..742af410 --- /dev/null +++ b/16/x/modex/MATH.INC @@ -0,0 +1,34 @@ +; +; MATH.INC - Include file for THREED.ASM +; + +; 3-dimensional point, coordinates in fixed format (16:16) +; +TPOINT STRUC + X DD ? + Y DD ? + Z DD ? +TPOINT ENDS + +; 2-dimensional point, coordinates in integer format +; +TIMAGEPOINT STRUC + IX DW ? + IY DW ? +TIMAGEPOINT ENDS + +; Fixed-point divide: EAX = EAX / arg +; +.xdiv MACRO arg + xor edx, edx + shld edx, eax, 16 + shl eax, 16 + idiv arg +ENDM + +; Fixed-point multiply: EAX = EAX * arg +; +.xmul MACRO arg + imul arg + shrd eax, edx, 16 +ENDM diff --git a/16/x/modex/PLASMA.PAS b/16/x/modex/PLASMA.PAS new file mode 100755 index 00000000..237e292a --- /dev/null +++ b/16/x/modex/PLASMA.PAS @@ -0,0 +1,103 @@ +unit Plasma; +interface + +const + PAL_RGB = 0; + PAL_CLOUDS = 1; + PAL_LANDSCAPE = 2; + +procedure MakePlasma( X, Y: integer; W, H: word; C1, C2, C3, C4: byte ); +procedure MakePlasmaPalette( var Palette; What: word ); + +implementation uses Modex; + +procedure NewColor( XA, YA, X, Y, XB, YB: integer ); +var + Color: longint; +begin + Color := Abs( XA-XB )+Abs( YA-YB ); + Color := Random( Color shl 1 )-Color; + Color := (Color+mxGetPixel( XA, YA )+mxGetPixel( XB, YB )+1) shr 1; + if( Color < 1 ) then Color := 1; + if( Color > 192 ) then Color := 192; + if( mxGetPixel( X, Y ) = 0 ) then + mxPutPixel( X, Y, Lo(Color) ); +end; + +procedure Divide( X1, Y1, X2, Y2: integer ); +var + X, Y, Color: integer; +begin + if not( (X2-X1<2)and(Y2-Y1<2) ) then begin + X := (X1+X2) shr 1; + Y := (Y1+Y2) shr 1; + NewColor( X1, Y1, X, Y1, X2, Y1 ); + NewColor( X2, Y1, X2, Y, X2, Y2 ); + NewColor( X1, Y2, X, Y2, X2, Y2 ); + NewColor( X1, Y1, X1, Y, X1, Y2 ); + Color := (mxGetPixel( X1, Y1 )+mxGetPixel( X2, Y1 )+ + mxGetPixel( X2, Y2 )+mxGetPixel( X1, Y2 )) shr 2; + mxPutPixel( X, Y, Color ); + Divide( X1, Y1, X, Y ); + Divide( X, Y1, X2, Y ); + Divide( X, Y, X2, Y2 ); + Divide( X1, Y, X, Y2 ); + end; +end; + +procedure MakePlasma; +begin + Dec( W ); + Dec( H ); + mxPutPixel( X, Y, C1 ); + mxPutPixel( X, Y+H, C2 ); + mxPutPixel( X+W, Y+H, C3 ); + mxPutPixel( X+W, Y, C4 ); + Divide( X, Y, X+W, Y+H ); +end; + +procedure MakePlasmaPalette; +type + TPal = array[ byte ] of record R, G, B: byte end; +var + I: word; +begin + FillChar( TPal(Palette)[1], 192*3, 0 ); + case What of + PAL_CLOUDS: + for I:=1 to 192 do begin + TPal(Palette)[I].R := Abs( I-96 )*63 div 96; + TPal(Palette)[I].G := Abs( I-96 )*63 div 96; + TPal(Palette)[I].B := 63; + end; + PAL_LANDSCAPE: + begin + for I:=0 to 31 do begin + TPal(Palette)[I+1].R := I; + TPal(Palette)[I+1].G := I; + TPal(Palette)[I+1].B := I + I shr 1+15; + end; + for I:=32 to 63 do begin + TPal(Palette)[I+1].R := 0; + TPal(Palette)[I+1].G := I; + TPal(Palette)[I+1].B := 0; + end; + for I:=64 to 191 do begin + TPal(Palette)[I+1].R := (I-64) div 3 + 15; + TPal(Palette)[I+1].G := (I-64) div 3 + 15; + TPal(Palette)[I+1].B := (I-64) div 3 + 15; + end; + end; + else + for I:=1 to 64 do begin + TPal(Palette)[I].G := I-1; + TPal(Palette)[I].B := 64-I; + TPal(Palette)[I+64].R := I-1; + TPal(Palette)[I+64].G := 64-I; + TPal(Palette)[I+128].B := I-1; + TPal(Palette)[I+128].R := 64-I; + end; + end; +end; + +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 index 0000000000000000000000000000000000000000..a10d7db5a0a62654c70c632d8ce6b078a520613c GIT binary patch literal 10336 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 DJ^3nG literal 0 HcmV?d00001 diff --git a/16/x/modex/QIX2.PAS b/16/x/modex/QIX2.PAS new file mode 100755 index 00000000..d1b59791 --- /dev/null +++ b/16/x/modex/QIX2.PAS @@ -0,0 +1,210 @@ +{$E-,N+} +uses Crt, Modex; + +const + DEFVERT = 12; (* Vertex count *) + DEFREPL = 3; (* Repetition count *) + DEFQIXS = 2; (* Qixs *) + FADESPEED = 48; +type + TPoint = record + X, Y : integer; + end; + TRGB = record + R, G, B: byte; + end; + TQix = record + Color: integer; + Vert : array[ 0..DEFVERT-1, 0..DEFREPL-1 ] of TPoint; + Delta: array[ 0..DEFVERT-1 ] of TPoint; + end; +var + Page : integer; + MaxX, + MaxY : word; + Qix : array[ 0..DEFQIXS-1 ] of TQix; + Pal : array[ byte ] of TRGB; + +type + TReal = double; + TRPoint = record + X, Y: TReal; + end; + TMatrix = array[ 0..3, 0..3 ] of TReal; +var + M: TMatrix; + G: array[ 0..DEFVERT-1 ] of TRPoint; + C: array[ 0..DEFVERT-1 ] of TRPoint; + +procedure BumpPal( Idx, DR, DG, DB, Steps: integer ); +var + I: integer; +begin + for I:=1 to Steps do begin + Pal[Idx+1].R := Pal[Idx].R + DR; + Pal[Idx+1].G := Pal[Idx].G + DG; + Pal[Idx+1].B := Pal[Idx].B + DB; + Inc( Idx ); + end; +end; + +procedure InitPalette; +begin + with Pal[0] do begin R:=0; G:=0; B:=0; end; + with Pal[1] do begin R:=0; G:=0; B:=62; end; + BumpPal( 1, 0, 2, -2, 31 ); + BumpPal( 32, 2, -2, 0, 31 ); + BumpPal( 63, -2, 2, 2, 31 ); + BumpPal( 94, 2, 0, -2, 31 ); + BumpPal( 125, -2, -2, 2, 31 ); +end; + +procedure Init( var Qix: TQix; Color: integer ); +var + I: integer; +begin + FillChar( Qix.Vert, SizeOf(Qix.Vert), 0 ); + for I:=0 to DEFVERT-1 do begin + Qix.Vert[I, DEFREPL-1].X := Random( MaxX ); + Qix.Vert[I, DEFREPL-1].Y := Random( MaxY ); + Qix.Delta[I].X := Random(5)+1; + Qix.Delta[I].Y := Random(5)+1; + end; + Qix.Color := Color; + + (* Initialize matrix (Catmull-Rom) *) + M[0,0] := -1/2; M[0,1] := 3/2; M[0,2] := -3/2; M[0,3] := 1/2; + M[1,0] := 1; M[1,1] := -5/2; M[1,2] := 2; M[1,3] := -1/2; + M[2,0] := -1/2; M[2,1] := 0; M[2,2] := 1/2; M[2,3] := 0; + M[3,0] := 0; M[3,1] := 1; M[3,2] := 0; M[3,3] := 0; +end; + +procedure mxBezier( var Qix: TQix; I0, Idx, N: integer ); +var + I, J: integer; + T, T2, T3: TReal; + X0, Y0, X, Y: TReal; + Delta: TReal; +begin + (* Compute coefficients *) + for I:=0 to 3 do begin + C[I].X := 0; + for J:=0 to 3 do C[I].X := C[I].X + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].X; + C[I].Y := 0; + for J:=0 to 3 do C[I].Y := C[I].Y + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].Y; + end; + X0 := C[3].X; + Y0 := C[3].Y; + Delta := 1 / N; + T := 0; + for I:=1 to N do begin + T := T + Delta; + T2 := T*T; + T3 := T*T2; + X := C[0].X*T3 + C[1].X*T2 + C[2].X*T + C[3].X; + Y := C[0].Y*T3 + C[1].Y*T2 + C[2].Y*T + C[3].Y; + mxLine( Round(X0), Page+Round(Y0), Round(X), Page+Round(Y), Qix.Color, OP_SET ); + X0 := X; + Y0 := Y; + end; +end; + +procedure Plot( var Qix: TQix; Idx: integer ); +var + I, J: integer; +begin + for I:=0 to DEFVERT-1 do begin + mxBezier( Qix, I, Idx, 12 ); + end; +end; + +procedure Update( var Qix: TQix; Idx: integer ); +var + I: integer; +begin + for I:=0 to DEFVERT-1 do with Qix do begin + Inc( Vert[I,Idx].X, Delta[I].X ); + if( Vert[I,Idx].X < 0 ) then begin + Vert[I,Idx].X := 0; + Delta[I].X := Random( 5 )+1; + end; + if( Vert[I,Idx].X > MaxX ) then begin + Vert[I,Idx].X := MaxX; + Delta[I].X := -Random( 5 )-1; + end; + Inc( Vert[I,Idx].Y, Delta[I].Y ); + if( Vert[I,Idx].Y < 0 ) then begin + Vert[I,Idx].Y := 0; + Delta[I].Y := Random( 5 )+1; + end; + if( Vert[I,Idx].Y > MaxY ) then begin + Vert[I,Idx].Y := MaxY; + Delta[I].Y := -Random( 5 )-1; + end; + end; +end; + +procedure Copy( var Qix: TQix; Dest, Src: integer ); +var + I: integer; +begin + for I:=0 to DEFVERT-1 do with Qix do begin + Vert[I,Dest].X := Vert[I,Src].X; + Vert[I,Dest].Y := Vert[I,Src].Y; + end; +end; + +procedure AnimateQix; +var + Q, Idx, I, J, P, Count: integer; +begin + Count := 0; + P := DEFREPL-1; + I := 0; + J := 1; + repeat + mxSetClipRegion( 0, Page, MaxX+1, MaxY+1 ); + mxSetClip( TRUE ); + mxFillBox( 0, Page, MaxX+1, MaxY+1, 0, OP_SET ); + for Q:=0 to DEFQIXS-1 do begin + Copy( Qix[Q], I, P ); + Update( Qix[Q], I ); + for Idx:=0 to DEFREPL-1 do begin + Plot( Qix[Q], Idx ); + end; + end; + I := (I+1) mod DEFREPL; + J := (J+1) mod DEFREPL; + P := (P+1) mod DEFREPL; + Inc( Count ); + mxStartLine( Page ); + if( Count >= FADESPEED ) then begin + for Q:=0 to DEFQIXS-1 do begin + Inc( Qix[Q].Color ); + if( Qix[Q].Color > 156 ) then + Qix[Q].Color := 1; + end; + Count := 0; + end; + Page := 240-Page; + until( KeyPressed ); +end; + +var + I: integer; +begin + Randomize; + mxInit; + mxSetMode( MX_320x240 ); + mxGetScreenSize( MaxX, MaxY ); + for I:=0 to DEFQIXS-1 do + Init( Qix[I], (I*(155 div DEFQIXS)) mod 155 + 1 ); + InitPalette; + mxSetPalette( @Pal, 0, 157 ); + Page := 240; + Dec( MaxX ); + Dec( MaxY ); + AnimateQix; + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/x/modex/README.TXT b/16/x/modex/README.TXT new file mode 100755 index 00000000..306e8b9a --- /dev/null +++ b/16/x/modex/README.TXT @@ -0,0 +1,8 @@ +ModeX - A graphical library for DOS programs +Copyright (c) 1993-1994 Alessandro Scotti +http://www.ascotti.org/ + +Please look at the above site in the "Art of..." and +then in the "Old programs" section for more information. + + diff --git a/16/x/modex/SINCOS.INC b/16/x/modex/SINCOS.INC new file mode 100755 index 00000000..6986eeeb --- /dev/null +++ b/16/x/modex/SINCOS.INC @@ -0,0 +1,518 @@ +; +; SINCOS.INC - Sin/cos tables for THREED.ASM +; + +tblSin LABEL DWORD + DD 0 + DD 411733 + DD 823219 + DD 1234209 + DD 1644455 + DD 2053710 + DD 2461729 + DD 2868265 + DD 3273072 + DD 3675909 + DD 4076531 + DD 4474698 + DD 4870169 + DD 5262706 + DD 5652074 + DD 6038037 + DD 6420363 + DD 6798821 + DD 7173184 + DD 7543226 + DD 7908725 + DD 8269459 + DD 8625213 + DD 8975771 + DD 9320922 + DD 9660458 + DD 9994176 + DD 10321873 + DD 10643353 + DD 10958422 + DD 11266890 + DD 11568571 + DD 11863283 + DD 12150850 + DD 12431097 + DD 12703856 + DD 12968963 + DD 13226258 + DD 13475586 + DD 13716797 + DD 13949745 + DD 14174291 + DD 14390298 + DD 14597637 + DD 14796184 + DD 14985817 + DD 15166424 + DD 15337895 + DD 15500126 + DD 15653022 + DD 15796488 + DD 15930439 + DD 16054795 + DD 16169479 + DD 16274424 + DD 16369565 + DD 16454846 + DD 16530216 + DD 16595628 + DD 16651044 + DD 16696429 + DD 16731757 + DD 16757007 + DD 16772163 + DD 16777216 + DD 16772163 + DD 16757007 + DD 16731757 + DD 16696429 + DD 16651044 + DD 16595628 + DD 16530216 + DD 16454846 + DD 16369565 + DD 16274424 + DD 16169479 + DD 16054795 + DD 15930439 + DD 15796488 + DD 15653022 + DD 15500126 + DD 15337895 + DD 15166424 + DD 14985817 + DD 14796184 + DD 14597637 + DD 14390298 + DD 14174291 + DD 13949745 + DD 13716797 + DD 13475586 + DD 13226258 + DD 12968963 + DD 12703856 + DD 12431097 + DD 12150850 + DD 11863283 + DD 11568571 + DD 11266890 + DD 10958422 + DD 10643353 + DD 10321873 + DD 9994176 + DD 9660458 + DD 9320922 + DD 8975771 + DD 8625213 + DD 8269459 + DD 7908725 + DD 7543226 + DD 7173184 + DD 6798821 + DD 6420363 + DD 6038037 + DD 5652074 + DD 5262706 + DD 4870169 + DD 4474698 + DD 4076531 + DD 3675909 + DD 3273072 + DD 2868265 + DD 2461729 + DD 2053710 + DD 1644455 + DD 1234209 + DD 823219 + DD 411733 + DD 0 + DD -411733 + DD -823219 + DD -1234209 + DD -1644455 + DD -2053710 + DD -2461729 + DD -2868265 + DD -3273072 + DD -3675909 + DD -4076531 + DD -4474698 + DD -4870169 + DD -5262706 + DD -5652074 + DD -6038037 + DD -6420363 + DD -6798821 + DD -7173184 + DD -7543226 + DD -7908725 + DD -8269459 + DD -8625213 + DD -8975771 + DD -9320922 + DD -9660458 + DD -9994176 + DD -10321873 + DD -10643353 + DD -10958422 + DD -11266890 + DD -11568571 + DD -11863283 + DD -12150850 + DD -12431097 + DD -12703856 + DD -12968963 + DD -13226258 + DD -13475586 + DD -13716797 + DD -13949745 + DD -14174291 + DD -14390298 + DD -14597637 + DD -14796184 + DD -14985817 + DD -15166424 + DD -15337895 + DD -15500126 + DD -15653022 + DD -15796488 + DD -15930439 + DD -16054795 + DD -16169479 + DD -16274424 + DD -16369565 + DD -16454846 + DD -16530216 + DD -16595628 + DD -16651044 + DD -16696429 + DD -16731757 + DD -16757007 + DD -16772163 + DD -16777216 + DD -16772163 + DD -16757007 + DD -16731757 + DD -16696429 + DD -16651044 + DD -16595628 + DD -16530216 + DD -16454846 + DD -16369565 + DD -16274424 + DD -16169479 + DD -16054795 + DD -15930439 + DD -15796488 + DD -15653022 + DD -15500126 + DD -15337895 + DD -15166424 + DD -14985817 + DD -14796184 + DD -14597637 + DD -14390298 + DD -14174291 + DD -13949745 + DD -13716797 + DD -13475586 + DD -13226258 + DD -12968963 + DD -12703856 + DD -12431097 + DD -12150850 + DD -11863283 + DD -11568571 + DD -11266890 + DD -10958422 + DD -10643353 + DD -10321873 + DD -9994176 + DD -9660458 + DD -9320922 + DD -8975771 + DD -8625213 + DD -8269459 + DD -7908725 + DD -7543226 + DD -7173184 + DD -6798821 + DD -6420363 + DD -6038037 + DD -5652074 + DD -5262706 + DD -4870169 + DD -4474698 + DD -4076531 + DD -3675909 + DD -3273072 + DD -2868265 + DD -2461729 + DD -2053710 + DD -1644455 + DD -1234209 + DD -823219 + DD -411733 +tblCos LABEL DWORD + DD 16777216 + DD 16772163 + DD 16757007 + DD 16731757 + DD 16696429 + DD 16651044 + DD 16595628 + DD 16530216 + DD 16454846 + DD 16369565 + DD 16274424 + DD 16169479 + DD 16054795 + DD 15930439 + DD 15796488 + DD 15653022 + DD 15500126 + DD 15337895 + DD 15166424 + DD 14985817 + DD 14796184 + DD 14597637 + DD 14390298 + DD 14174291 + DD 13949745 + DD 13716797 + DD 13475586 + DD 13226258 + DD 12968963 + DD 12703856 + DD 12431097 + DD 12150850 + DD 11863283 + DD 11568571 + DD 11266890 + DD 10958422 + DD 10643353 + DD 10321873 + DD 9994176 + DD 9660458 + DD 9320922 + DD 8975771 + DD 8625213 + DD 8269459 + DD 7908725 + DD 7543226 + DD 7173184 + DD 6798821 + DD 6420363 + DD 6038037 + DD 5652074 + DD 5262706 + DD 4870169 + DD 4474698 + DD 4076531 + DD 3675909 + DD 3273072 + DD 2868265 + DD 2461729 + DD 2053710 + DD 1644455 + DD 1234209 + DD 823219 + DD 411733 + DD 0 + DD -411733 + DD -823219 + DD -1234209 + DD -1644455 + DD -2053710 + DD -2461729 + DD -2868265 + DD -3273072 + DD -3675909 + DD -4076531 + DD -4474698 + DD -4870169 + DD -5262706 + DD -5652074 + DD -6038037 + DD -6420363 + DD -6798821 + DD -7173184 + DD -7543226 + DD -7908725 + DD -8269459 + DD -8625213 + DD -8975771 + DD -9320922 + DD -9660458 + DD -9994176 + DD -10321873 + DD -10643353 + DD -10958422 + DD -11266890 + DD -11568571 + DD -11863283 + DD -12150850 + DD -12431097 + DD -12703856 + DD -12968963 + DD -13226258 + DD -13475586 + DD -13716797 + DD -13949745 + DD -14174291 + DD -14390298 + DD -14597637 + DD -14796184 + DD -14985817 + DD -15166424 + DD -15337895 + DD -15500126 + DD -15653022 + DD -15796488 + DD -15930439 + DD -16054795 + DD -16169479 + DD -16274424 + DD -16369565 + DD -16454846 + DD -16530216 + DD -16595628 + DD -16651044 + DD -16696429 + DD -16731757 + DD -16757007 + DD -16772163 + DD -16777216 + DD -16772163 + DD -16757007 + DD -16731757 + DD -16696429 + DD -16651044 + DD -16595628 + DD -16530216 + DD -16454846 + DD -16369565 + DD -16274424 + DD -16169479 + DD -16054795 + DD -15930439 + DD -15796488 + DD -15653022 + DD -15500126 + DD -15337895 + DD -15166424 + DD -14985817 + DD -14796184 + DD -14597637 + DD -14390298 + DD -14174291 + DD -13949745 + DD -13716797 + DD -13475586 + DD -13226258 + DD -12968963 + DD -12703856 + DD -12431097 + DD -12150850 + DD -11863283 + DD -11568571 + DD -11266890 + DD -10958422 + DD -10643353 + DD -10321873 + DD -9994176 + DD -9660458 + DD -9320922 + DD -8975771 + DD -8625213 + DD -8269459 + DD -7908725 + DD -7543226 + DD -7173184 + DD -6798821 + DD -6420363 + DD -6038037 + DD -5652074 + DD -5262706 + DD -4870169 + DD -4474698 + DD -4076531 + DD -3675909 + DD -3273072 + DD -2868265 + DD -2461729 + DD -2053710 + DD -1644455 + DD -1234209 + DD -823219 + DD -411733 + DD 0 + DD 411733 + DD 823219 + DD 1234209 + DD 1644455 + DD 2053710 + DD 2461729 + DD 2868265 + DD 3273072 + DD 3675909 + DD 4076531 + DD 4474698 + DD 4870169 + DD 5262706 + DD 5652074 + DD 6038037 + DD 6420363 + DD 6798821 + DD 7173184 + DD 7543226 + DD 7908725 + DD 8269459 + DD 8625213 + DD 8975771 + DD 9320922 + DD 9660458 + DD 9994176 + DD 10321873 + DD 10643353 + DD 10958422 + DD 11266890 + DD 11568571 + DD 11863283 + DD 12150850 + DD 12431097 + DD 12703856 + DD 12968963 + DD 13226258 + DD 13475586 + DD 13716797 + DD 13949745 + DD 14174291 + DD 14390298 + DD 14597637 + DD 14796184 + DD 14985817 + DD 15166424 + DD 15337895 + DD 15500126 + DD 15653022 + DD 15796488 + DD 15930439 + DD 16054795 + DD 16169479 + DD 16274424 + DD 16369565 + DD 16454846 + DD 16530216 + DD 16595628 + DD 16651044 + DD 16696429 + DD 16731757 + DD 16757007 + DD 16772163 diff --git a/16/x/modex/THREED.ASM b/16/x/modex/THREED.ASM new file mode 100755 index 00000000..5ecd3ba3 --- /dev/null +++ b/16/x/modex/THREED.ASM @@ -0,0 +1,872 @@ +COMMENT / + Fixed-point math functions and 3D transforms + Copyright (c) 1993,94 by Alessandro Scotti +/ +WARN PRO +P386 +JUMPS +LOCALS + +INCLUDE MATH.INC + +PUBLIC tdFixedMul +PUBLIC tdGetNormal +PUBLIC tdRotate +PUBLIC tdGetSurfaceLight +PUBLIC tdSetLight +PUBLIC tdSetRotation +PUBLIC tdSetTranslation +PUBLIC tdTransform +PUBLIC tdTransformToImage +PUBLIC tdTransformLight +PUBLIC tdBackPlaneCull +PUBLIC tdSetPerspective + +;----------------------------------------------------------- +; +; Data segment +; +MATH_DATA SEGMENT USE16 PARA PUBLIC 'DATA' + ASSUME ds:MATH_DATA + +INCLUDE SINCOS.INC ; Fixed 8:24 sin/cos table + +XRotation TPOINT <> ; 3x3 rotation matrix +YRotation TPOINT <> +ZRotation TPOINT <> + +Translation TPOINT <> ; Translation vector + +Light TPOINT <> ; Light vector +AmbientLight DW 00 ; Ambient light + +XScale DD 10000h ; Scaling factor for X coordinate +YScale DD 10000h ; Scaling factor for Y coordinate +PerspectiveDistance DD 20000000h + +MATH_DATA ENDS + +;----------------------------------------------------------- +; +; Code segment +; +MATH_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MATH_TEXT, es:NOTHING, fs:NOTHING + +tdSetPerspective PROC PASCAL FAR + ARG Perspective:DWORD, \ + ScaleX:DWORD, \ + ScaleY:DWORD + USES ds + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + mov eax, [Perspective] + mov [PerspectiveDistance], eax + mov eax, [ScaleX] + mov [XScale], eax + mov eax, [ScaleY] + mov [YScale], eax + + ret +tdSetPerspective ENDP + + +;----------------------------------------------------------- +; +; Sets the rotation matrix. +; +; Input: +; RX = X-axis rotation angle +; RY = X-axis rotation angle +; RZ = X-axis rotation angle +; Output: +; none +; +tdSetRotation PROC PASCAL FAR + ARG RX:WORD, \ + RY:WORD, \ + RZ:WORD + USES ds, si, di + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + mov bx, [RZ] + mov si, [RY] + mov di, [RX] + shl bx, 2 + shl si, 2 + shl di, 2 + + push ebp ; We use EBP as a scratch register + +; Set X rotation + mov eax, tblCos[bx] + imul tblCos[si] + mov [XRotation.X], edx + + mov eax, tblSin[bx] + imul tblCos[si] + mov [XRotation.Y], edx + + mov eax, tblSin[si] + sar eax, 8 ; Convert fixed 8:24 to fixed 16:16 + mov [XRotation.Z], eax + +; Set Y rotation + mov eax, tblCos[bx] + imul tblSin[si] ; EDX:EAX = fixed 16:48 + shrd eax, edx, 24 ; EAX = fixed 8:24 + imul tblSin[di] ; EDX:EAX = fixed 16:48 + mov ebp, eax + mov ecx, edx + mov eax, tblSin[bx] + imul tblCos[di] + add eax, ebp + adc edx, ecx ; EDX:EAX = fixed 16:48 + neg edx + mov [YRotation.X], edx + + mov eax, tblSin[bx] + imul tblSin[si] + shrd eax, edx, 24 + imul tblSin[di] + mov ebp, eax + mov ecx, edx + mov eax, tblCos[bx] + imul tblCos[di] + sub eax, ebp + sbb edx, ecx + mov [YRotation.Y], edx + + mov eax, tblCos[si] + imul tblSin[di] + mov [YRotation.Z], edx + +; Set Z rotation + mov eax, tblCos[bx] + imul tblSin[si] + shrd eax, edx, 24 + imul tblCos[di] + mov ebp, eax + mov ecx, edx + mov eax, tblSin[bx] + imul tblSin[di] + sub eax, ebp + sbb edx, ecx + mov [ZRotation.X], edx + + mov eax, tblSin[bx] + imul tblSin[si] + shrd eax, edx, 24 + imul tblCos[di] + mov ebp, eax + mov ecx, edx + mov eax, tblCos[bx] + imul tblSin[di] + add eax, ebp + add edx, ecx + neg edx + mov [ZRotation.Y], edx + + mov eax, tblCos[si] + imul tblCos[di] + mov [ZRotation.Z], edx + + pop ebp ; Restore EBP + + ret +tdSetRotation ENDP + +;----------------------------------------------------------- +; +; Sets the translation vector. +; +; Input: +; TV = pointer to translation vector +; Output: +; none +; +tdSetTranslation PROC PASCAL FAR + ARG TV:DWORD + USES ds, es, di + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + les di, [TV] + mov eax, es:[di].X + mov [Translation.X], eax + mov eax, es:[di].Y + mov [Translation.Y], eax + mov eax, es:[di].Z + mov [Translation.Z], eax + + ret +tdSetTranslation ENDP + +;----------------------------------------------------------- +; +; Transforms an array of TPOINT. +; +; Input: +; Source = pointer to source array of TPOINT +; Dest = pointer to destination array of TPOINT +; Count = number of entries to transform +; Output: +; none +; +tdTransform PROC PASCAL FAR + ARG Source:DWORD, \ + Dest:DWORD, \ + Count:WORD + LOCAL Adjust:DWORD + USES ds, si, es, di, fs + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + lfs si, [Source] + les di, [Dest] + + ALIGN DWORD +@@Loop: +; Transform Z coordinate + mov eax, fs:[si].X + imul [ZRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [ZRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [ZRotation.Z] + add eax, ecx + adc edx, ebx + mov ebx, eax + shrd eax, edx, 16 + add eax, [Translation.Z] ; EAX = new Z coord (fixed 16:16) + mov es:[di].Z, eax +; Get perspective factor + mov ebx, [PerspectiveDistance] + sub eax, ebx + neg eax ; EAX = PD - Z + xor edx, edx + shld edx, eax, 16 + shl eax, 16 + idiv ebx ; EAX = fixed 16:16 result + mov [Adjust], eax + +; Transform X coordinate + mov eax, fs:[si].X + imul [XRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [XRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [XRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + add eax, [Translation.X] + imul [Adjust] + shrd eax, edx, 16 + mov es:[di].X, eax + +; Transform Y coordinate + mov eax, fs:[si].X + imul [YRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [YRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [YRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + add eax, [Translation.Y] + imul [Adjust] + shrd eax, edx, 16 + mov es:[di].Y, eax + + add si, SIZE TPOINT + add di, SIZE TPOINT + dec [Count] + jnz @@Loop + + ret +tdTransform ENDP + +;----------------------------------------------------------- +; +; Transforms an array of TPOINT into an array of TIMAGEPOINT. +; +; Input: +; Source = pointer to source array of TPOINT +; Dest = pointer to destination array of TIMAGEPOINT +; Count = number of entries to transform +; DeltaX = translation distance for the X coordinate +; DeltaY = translation distance for the Y coordinate +; Output: +; the maximum Z value +; +tdTransformToImage PROC PASCAL FAR + ARG Source:DWORD, \ + Dest:DWORD, \ + Count:WORD, \ + DeltaX:WORD, \ + DeltaY:WORD + LOCAL Adjust:DWORD, \ + Max:DWORD + USES ds, si, es, di, fs + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + lfs si, [Source] + les di, [Dest] + mov [Max], 80000000h + +@@Loop: +; Check max Z + mov eax, fs:[si].Z + cmp eax, [Max] + jle @@1 + mov [Max], eax +@@1: + +; Transform X coordinate + mov ax, WORD PTR fs:[si].X[2] + add ax, [DeltaX] + mov es:[di].IX, ax + +; Transform Y coordinate + mov ax, WORD PTR fs:[si].Y[2] + add ax, [DeltaY] + mov es:[di].IY, ax + + add si, SIZE TPOINT + add di, SIZE TIMAGEPOINT + dec [Count] + jnz @@Loop + + mov eax, [Max] + shld edx, eax, 16 + ret +tdTransformToImage ENDP + +;----------------------------------------------------------- +; +; Sets the light source. +; +; Input: +; Light = pointer to light vector +; Output: +; none +; +tdSetLight PROC PASCAL FAR + ARG L:DWORD + USES ds, es, di + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + les di, [L] + mov eax, es:[di].X + mov [Light.X], eax + mov eax, es:[di].Y + mov [Light.Y], eax + mov eax, es:[di].Z + mov [Light.Z], eax + + ret +tdSetLight ENDP + +;----------------------------------------------------------- +; +; Computes light intensity for an array of surfaces. +; +; Input: +; Normals = pointer to an array of surface normals +; Lights = pointer to an array of integer to be filled with +; light intensity +; Count = number of elements to transform +; Output: +; none +; +tdTransformLight PROC PASCAL FAR + ARG Normals:DWORD, \ + Lights:DWORD, \ + Count:WORD + USES ds, si, es, di, fs + + mov ax, SEG MATH_DATA + mov fs, ax + ASSUME fs:MATH_DATA + + lds si, [Normals] + les di, [Lights] + ASSUME ds:NOTHING + +; Intensity is given by the dot product between the Light vector and +; the surface normal +@@Loop: + mov eax, ds:[si].Z + imul [Light.Z] + mov ebx, eax + mov ecx, edx + mov eax, ds:[si].Y + imul [Light.Y] + add ebx, eax + adc ecx, edx + mov eax, ds:[si].X + imul [Light.X] + add eax, ebx + adc edx, ecx ; EDX:EAX = fixed 32:32 intensity + add dx, [AmbientLight] + test dx, dx + jg @@1 + xor dx, dx ; Return 0 for no light +@@1: + mov es:[di], dx + inc di + inc di + add si, SIZE TPOINT + dec [Count] + jnz @@Loop + + ASSUME fs:NOTHING + ret +tdTransformLight ENDP + +;----------------------------------------------------------- +; +; Returns the light value given the normal to a surface. +; +; Input: +; Normal = pointer to TPOINT surface normal vector +; Output: +; AX = light intensity (>=0) +; Notes: +; the normal is rotated according to the current setting. +; +tdGetSurfaceLight PROC PASCAL FAR + ARG Normal:DWORD + USES ds, esi, es, di + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + les di, [Normal] + +; Transform Z coordinate + mov eax, es:[di].X + imul [ZRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, es:[di].Y + imul [ZRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, es:[di].Z + imul [ZRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + imul [Light.Z] + shrd eax, edx, 16 + mov esi, eax + +; Transform X coordinate + mov eax, es:[di].X + imul [XRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, es:[di].Y + imul [XRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, es:[di].Z + imul [XRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + imul [Light.X] + shrd eax, edx, 16 + add esi, eax + +; Transform Y coordinate + mov eax, es:[di].X + imul [YRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, es:[di].Y + imul [YRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, es:[di].Z + imul [YRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + imul [Light.X] + shrd eax, edx, 16 + add eax, esi + shr eax, 16 + +; Add ambient light + add ax, [AmbientLight] + test ax, ax + jge @@Exit + xor ax, ax + +@@Exit: + ret +tdGetSurfaceLight ENDP + +;----------------------------------------------------------- +; +; Rotates an array of TPOINT. +; +; Input: +; Source = pointer to source array of TPOINT +; Dest = pointer to destination array of TPOINT +; Count = number of entries to transform +; Output: +; none +; +tdRotate PROC PASCAL FAR + ARG Source:DWORD, \ + Dest:DWORD, \ + Count:WORD + USES ds, si, es, di, fs + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + lfs si, [Source] + les di, [Dest] + +@@Loop: +; Transform Z coordinate + mov eax, fs:[si].X + imul [ZRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [ZRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [ZRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + mov es:[di].Z, eax + +; Transform X coordinate + mov eax, fs:[si].X + imul [XRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [XRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [XRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + mov es:[di].X, eax + +; Transform Y coordinate + mov eax, fs:[si].X + imul [YRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [YRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [YRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + mov es:[di].Y, eax + + add si, SIZE TPOINT + add di, SIZE TPOINT + dec [Count] + jnz @@Loop + + ret +tdRotate ENDP + +tdFixedMul PROC PASCAL FAR + ARG F1:DWORD, \ + F2:DWORD + + mov eax, [F1] + imul [F2] + shr eax, 16 + + ret +tdFixedMul ENDP + +;----------------------------------------------------------- +; +; Returns in EAX the square root of EDX:EAX. +; +subSqrt PROC NEAR + push esi + push edi + + add eax, eax + adc edx, 0 + mov eax, edx ; Just discard the low bits + + mov esi, eax + xor edi, edi + shld edi, esi, 16 + shl esi, 16 +@@Loop: + mov ebx, eax + mul eax + add eax, esi + adc edx, edi + shrd eax, edx, 1 + shr edx, 1 + div ebx + cmp eax, ebx + jne @@Loop + +; Adjust EAX + shl eax, 8 + + pop edi + pop esi + ret +subSqrt ENDP + +;----------------------------------------------------------- +; +; Finds the unitary normal to a given surface. +; +; Input: +; Dest = pointer to TPOINT (vector) result +; P1, P2, P3 = pointer to TPOINT points on surface +; Output: +; none +; Notes: +; the normal is given by the cross-product between (P3-P1) and +; (P2-P1), so its orientation depends on the parameters order. +; +tdGetNormal PROC PASCAL FAR + ARG Dest:DWORD, \ + P1:DWORD, \ + P2:DWORD, \ + P3:DWORD + LOCAL V1:TPOINT, \ + V2:TPOINT, \ + N:TPOINT + USES ds, si, es, di + +; Get vector V1 + lds si, [P1] + les di, [P3] + mov eax, es:[di].X + sub eax, ds:[si].X + mov [V1.X], eax + mov eax, es:[di].Y + sub eax, ds:[si].Y + mov [V1.Y], eax + mov eax, es:[di].Z + sub eax, ds:[si].Z + mov [V1.Z], eax + +; Get vector V2 + les di, [P2] + mov eax, es:[di].X + sub eax, ds:[si].X + mov [V2.X], eax + mov eax, es:[di].Y + sub eax, ds:[si].Y + mov [V2.Y], eax + mov eax, es:[di].Z + sub eax, ds:[si].Z + mov [V2.Z], eax + +; Get normal vector (V1 x V2) + mov eax, [V1.Z] + imul [V2.Y] + mov ebx, eax + mov ecx, edx + mov eax, [V1.Y] + imul [V2.Z] + sub eax, ebx + sbb edx, ecx + shrd eax, edx, 16 + mov [N.X], eax + + mov eax, [V1.X] + imul [V2.Z] + mov ebx, eax + mov ecx, edx + mov eax, [V1.Z] + imul [V2.X] + sub eax, ebx + sbb edx, ecx + shrd eax, edx, 16 + mov [N.Y], eax + + mov eax, [V1.Y] + imul [V2.X] + mov ebx, eax + mov ecx, edx + mov eax, [V1.X] + imul [V2.Y] + sub eax, ebx + sbb edx, ecx + shrd eax, edx, 16 + mov [N.Z], eax + +; Get normal length + mov eax, [N.X] + imul eax + mov ebx, eax + mov ecx, edx + mov eax, [N.Y] + imul eax + add ebx, eax + adc ecx, edx + mov eax, [N.Z] + imul eax + add eax, ebx + adc edx, ecx ; EDX:EAX = N.X*N.X + N.Y*N.Y + N.Z*N.Z + call subSqrt ; EAX = normal length + mov ebx, eax + +; Adjust vector and save it + les di, [Dest] + mov eax, [N.X] + cdq + shld edx, eax, 16 + shl eax, 16 + idiv ebx + mov es:[di].X, eax + mov eax, [N.Y] + cdq + shld edx, eax, 16 + shl eax, 16 + idiv ebx + mov es:[di].Y, eax + mov eax, [N.Z] + cdq + shld edx, eax, 16 + shl eax, 16 + idiv ebx + mov es:[di].Z, eax + + ret +tdGetNormal ENDP + +TPOLY STRUC + Vtx DW 4 DUP(?) +TPOLY ENDS + +;----------------------------------------------------------- +; +; Performs surface removal on an array of polygons. +; +; Input: +; Poly = pointer to an array of TPOLY +; Vertex = pointer to an array of TPOINT +; Dest = pointer to an array of integer +; Count = number of polygons to check +; Step = size of TPOLY structure +; Output: +; if the n-th polygon is invisible the n-th entry of the +; Dest array is set to -1, other entries are not modified +; (so it's possible to use the Light array for Dest, because +; the light intensity is always >= 0) +; +tdBackPlaneCull PROC PASCAL FAR + ARG Step:WORD, \ + Poly:DWORD, \ + Vertex:DWORD, \ + Dest:DWORD, \ + Count:WORD + USES ds, si, es, di, fs + ASSUME ds:NOTHING + + mov ds, WORD PTR Vertex[2] + les di, [Poly] + mov fs, WORD PTR Dest[2] + +@@Loop: + mov ax, es:[di].Vtx[2] ; Index of 2nd vertex + shl ax, 2 + mov bx, ax + shl ax, 1 + add bx, ax ; BX = index*SIZE TPOINT + add bx, WORD PTR [Vertex] ; BX = offset of 2nd vertex + mov ax, es:[di].Vtx[4] ; Index of 3rd vertex + shl ax, 2 + mov si, ax + shl ax, 1 + add si, ax + add si, WORD PTR [Vertex] ; SI = offset of 3rd vertex + mov ecx, ds:[si].X + sub ecx, ds:[bx].X ; ECX = V3.X-V2.X + mov edx, ds:[si].Y + sub edx, ds:[bx].Y ; EDX = V3.Y-V2.Y + mov ax, es:[di].Vtx[0] ; Index of 1st vertex + shl ax, 2 + mov si, ax + shl ax, 1 + add si, ax + add si, WORD PTR [Vertex] ; SI = offset of 1st vertex + mov eax, ds:[si].X + sub eax, ds:[bx].X ; EAX = V1.X-V2.X + mov esi, ds:[si].Y + sub esi, ds:[bx].Y ; ESI = V1.Y-V2.Y + imul edx + mov ebx, eax + xchg ecx, edx ; ECX:EBX = (V1.X-V2.X)*(V3.Y-V2.Y) + mov eax, esi + imul edx ; EDX:EAX = (V1.Y-V2.Y)*(V3.X-V2.X) + sub eax, ebx + sbb edx, ecx + jl @@Next ; Polygon is visible + mov bx, WORD PTR [Dest] ; FS:BX -> current Dest entry + mov WORD PTR fs:[bx], -1 ; Remove polygon +@@Next: + add WORD PTR [Dest], 2 ; Next entry for dest + add di, [Step] ; Next polygon + dec [Count] + jnz @@Loop + + ret +tdBackPlaneCull ENDP + +MATH_TEXT ENDS +END diff --git a/16/x/modex/THREED.H b/16/x/modex/THREED.H new file mode 100755 index 00000000..b993ef86 --- /dev/null +++ b/16/x/modex/THREED.H @@ -0,0 +1,32 @@ +typedef struct { + long x, y, z; +} TVECTOR; + +#define PVECTOR TVECTOR far * + +#define TPOINT TVECTOR +#define PPOINT PVECTOR + +#define VPTR void far * + +#ifdef __cplusplus +extern "C" { +#endif + +long far pascal tdFixedMul( long, long ); +int far pascal tdGetSurfaceLight( PPOINT ); +long far pascal tdTransformToImage( VPTR, VPTR, short, short, short ); + +void far pascal tdBackPlaneCull( VPTR, VPTR, VPTR, short, short ); +void far pascal tdGetNormal( VPTR, PPOINT, PPOINT, PPOINT ); +void far pascal tdRotate( VPTR, VPTR, short ); +void far pascal tdSetLight( PVECTOR ); +void far pascal tdSetRotation( short, short, short ); +void far pascal tdSetTranslation( PVECTOR ); +void far pascal tdSetPerspective( long, long, long ); +void far pascal tdTransform( VPTR, VPTR, short ); +void far pascal tdTransformLight( VPTR, VPTR, short ); + +#ifdef __cplusplus +} +#endif diff --git a/16/x/modex/THREED.PAS b/16/x/modex/THREED.PAS new file mode 100755 index 00000000..8b712c9d --- /dev/null +++ b/16/x/modex/THREED.PAS @@ -0,0 +1,40 @@ +unit ThreeD; +interface + +type + TVector = record + X, Y, Z : longint; + end; + TPoint = TVector; + +function tdFixedMul( F1, F2: longint ): longint; +function tdGetSurfaceLight( var Normal: TPoint ): integer; +function tdTransformToImage( var Source, Dest; Count, DeltaX, DeltaY: integer ): longint; + +procedure tdBackPlaneCull( var Poly, Vertex, Dest; Count, Step: word ); +procedure tdGetNormal( var Dest, P1, P2, P3: TVector ); +procedure tdRotate( var Source, Dest; Count: word ); +procedure tdSetLight( var Light: TVector ); +procedure tdSetRotation( RX, RY, RZ: word ); +procedure tdSetTranslation( var TV: TVector ); +procedure tdSetPerspective( PD, XF, YF: longint ); +procedure tdTransform( var Source, Dest; Count: word ); +procedure tdTransformLight( var Source, Dest; Count: word ); + +implementation + +function tdGetSurfaceLight; external; +procedure tdSetRotation( RX, RY, RZ: word ); external; +procedure tdGetNormal; external; +procedure tdSetTranslation( var TV: TVector ); external; +procedure tdTransform( var Source, Dest; Count: word ); external; +procedure tdRotate; external; +function tdTransformToImage; external; +procedure tdSetLight( var Light: TVector ); external; +procedure tdSetPerspective; external; +procedure tdTransformLight; external; +function tdFixedMul( F1, F2: longint ): longint; external; +procedure tdBackPlaneCull; external; +{$L THREED} + +end. diff --git a/16/x/mxbb.asm b/16/x/mxbb.asm new file mode 100755 index 00000000..ac6668ce --- /dev/null +++ b/16/x/mxbb.asm @@ -0,0 +1,278 @@ +;----------------------------------------------------------- +; +; MXBB.ASM - Bit block transfer +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxBitBlt + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN subHorizontalLineInfo : NEAR + +EXTRN mx_VideoSegment : WORD +EXTRN mx_BytesPerLine : WORD + +;----------------------------------------------------------- +; +; Moves a block of video memory. +; +; Input: +; SX, SY = source coordinates +; Width = source width +; Height = source height +; DX, DY = destination coordinates +; Output: +; none +; +; Note: overlapping regions are not allowed. +; +mxBitBlt PROC FAR + ARG DestY:WORD, \ + DestX:WORD, \ + Height:WORD, \ + Width:WORD, \ + SY:WORD, \ + SX:WORD = ARG_SIZE + LOCAL PlaneWidth:WORD:4, \ + SourceOffset:WORD, \ + DestOffset:WORD, \ + Count:BYTE, \ + ReadPlane:BYTE, \ + WritePlane:BYTE, \ + LeftMask:BYTE, \ + RightMask:BYTE = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, es, di + +; Exit now if null width + cmp [Width], 0 + je @@Exit + +; Calls the proper procedure to handle transfer + mov ax, [SX] + and al, 03h ; AL = source plane + mov dx, [DestX] + and dl, 03h ; DL = destination plane + mov bx, OFFSET subPlaneBlt + cmp al, dl ; Same source and destination plane? + jne @@BitBlt ; No, use slow procedure + mov bx, OFFSET subMoveBlt +@@BitBlt: + call bx + +@@Exit: + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE + +;----------------------------------------------------------- +; Uses write mode 1 for maximum speed. Only works if source +; and destination are plane-aligned. +; +subMoveBlt PROC NEAR +; Get horizontal line info and address of destination + mov bx, [DestX] + mov ax, [DestY] + mov cx, [Width] + call subHorizontalLineInfo + mov [LeftMask], al + mov [RightMask], ah + mov [Width], cx + +; Setup segments + mov ax, [mx_VideoSegment] + mov ds, ax + mov es, ax + +; Get address of source pixel + mov ax, [SY] + mul [mx_BytesPerLine] + mov si, [SX] + .shr si, 2 + add si, ax + +; Set write mode 1 + mov dx, GDC + mov ax, 4105h + out dx, ax + cld + +; Move left block +@@L0: + mov ah, [LeftMask] + or ah, ah + jz @@C0 + mov dx, TS + mov al, 02h + out dx, ax ; Set write plane mask + mov ax, [mx_BytesPerLine] + dec ax + mov cx, [Height] + .push si, di +@@L1: + movsb + add si, ax + add di, ax + dec cx + jnz @@L1 + .pop si, di + inc si + inc di + +; Move center block +@@C0: + mov bx, [Width] + test bx, bx + jz @@R0 + mov dx, TS + mov ax, 0F02h + out dx, ax ; Enable all planes + mov ax, [mx_BytesPerLine] + sub ax, bx + mov dx, [Height] + .push si, di +@@C1: + mov cx, bx ; CX = image width + rep movsb ; Cannot use "movsw" here! + add si, ax ; Next scan line + add di, ax ; Next scan line + dec dx ; All lines processed? + jnz @@C1 ; No, continue + .pop si, di + add si, bx + add di, bx + +; Move right block +@@R0: + mov ah, [RightMask] + or ah, ah + jz @@Done + mov dx, TS + mov al, 02h + out dx, ax ; Set write plane mask + mov ax, [mx_BytesPerLine] + dec ax + mov cx, [Height] +@@R1: + movsb + add si, ax + add di, ax + dec cx + jnz @@R1 + +@@Done: + mov dx, GDC + mov ax, 4005h + out dx, ax ; Restore write mode 0 + +@@Exit: + ret +subMoveBlt ENDP + +;----------------------------------------------------------- +; Moves one plane at a time. +; +subPlaneBlt PROC NEAR +; Compute extra bytes and width count for each plane + mov cx, [Width] + mov bx, cx + shr bx, 1 + shr bx, 1 ; Width for each plane + and cl, 03h + mov al, 00001000b + shr al, cl + mov si, 3 SHL 1 +@@PatchLoop: + mov PlaneWidth[si], bx + shr al, 1 + adc bx, 0 + dec si + dec si + jge @@PatchLoop + +; Get pixel addresses + mov ax, [mx_VideoSegment] + mov ds, ax + mov es, ax + mov ax, [SY] + mul [mx_BytesPerLine] + mov si, [SX] + shr si, 1 + shr si, 1 + add si, ax ; DS:SI points to source + mov [SourceOffset], si + mov ax, [DestY] + mul [mx_BytesPerLine] + mov di, [DestX] + shr di, 1 + shr di, 1 + add di, ax ; ES:DI points to destination + mov [DestOffset], di + +; Adjust plane for output to VGA registers + mov ax, [SX] + and al, 03h + mov [ReadPlane], al + mov cx, [DestX] + and cl, 03h + mov al, 00010001b + shl al, cl + mov [WritePlane], al + +; Ready to move now + cld + mov [Count], 4 ; Four planes + lea bx, PlaneWidth ; SS:[BX] = width in bytes for plane +@@PlaneLoop: + cmp WORD PTR ss:[bx], 0 + je @@Done + mov ah, [WritePlane] + and ah, 0Fh + mov al, 02h + mov dx, TS + out dx, ax ; Select write plane + mov ah, [ReadPlane] + mov al, 04h + mov dx, GDC + out dx, ax ; Select read plane + mov dx, [Height] + mov ax, [mx_BytesPerLine] + sub ax, ss:[bx] ; AX = extra bytes per line +@@Loop: + mov cx, ss:[bx] + shr cx, 1 + rep movsw + rcl cx, 1 + rep movsb + add si, ax + add di, ax + dec dx + jnz @@Loop ; Repeat for all lines + inc bx + inc bx ; Select width for next plane + inc [ReadPlane] + and [ReadPlane], 03h ; Should be faster on 386 using + jnz @@ReadPlaneOk ; BTR and ADC... + inc [SourceOffset] +@@ReadPlaneOk: + rol [WritePlane], 1 + adc [DestOffset], 0 + mov si, [SourceOffset] + mov di, [DestOffset] + dec [Count] + jnz @@PlaneLoop ; Repeat for all planes + +@@Done: + ret +subPlaneBlt ENDP + +mxBitBlt ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxcc.asm b/16/x/mxcc.asm new file mode 100755 index 00000000..4f78adb9 --- /dev/null +++ b/16/x/mxcc.asm @@ -0,0 +1,644 @@ +;----------------------------------------------------------- +; +; MXCC.ASM - Fast clip line function +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC xsubClipLine + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD +EXTRN mx_VideoSegment : WORD + +EXTRN mx_ClipX1 : WORD +EXTRN mx_ClipY1 : WORD +EXTRN mx_ClipX2 : WORD +EXTRN mx_ClipY2 : WORD + +tblGroups LABEL WORD + DW 10, tbl00 + DW 10, tbl10 + DW 9, tbl20 + DW -1, 0 + DW 10, tbl40 + DW 10, tbl50 + DW 9, tbl60 + DW -1, 0 + DW 6, tbl80 + DW 6, tbl90 + DW 5, tblA0 + DW -1, 0 + DW -1, 0 + DW -1, 0 + DW -1, 0 + DW -1, 0 +tbl00 DW cc00, cc01, cc02, ccFF, cc04, cc05, cc06, ccFF, cc08, cc09, cc0A +tbl10 DW cc10, ccFF, cc12, ccFF, cc14, ccFF, cc16, ccFF, cc18, ccFF, cc1A +tbl20 DW cc20, cc21, ccFF, ccFF, cc24, cc25, ccFF, ccFF, cc28, cc29 +tbl40 DW cc40, cc41, cc42, ccFF, ccFF, ccFF, ccFF, ccFF, cc48, cc49, cc4A +tbl50 DW cc50, ccFF, cc52, ccFF, ccFF, ccFF, ccFF, ccFF, cc58, ccFF, cc5A +tbl60 DW cc60, cc61, ccFF, ccFF, ccFF, ccFF, ccFF, ccFF, cc68, cc69 +tbl80 DW cc80, cc81, cc82, ccFF, cc84, cc85, cc86 +tbl90 DW cc90, ccFF, cc92, ccFF, cc94, ccFF, cc96 +tblA0 DW ccA0, ccA1, ccFF, ccFF, ccA4, ccA5 + +ccTT: clc + ret +ccFF: stc + ret + +; Group 00 ------------------------------------------------- +; +cc00: + clc + ret +cc01: + jmp ClipQLeft +cc02: + jmp ClipQRight +cc04: + jmp ClipQTop +cc05: + call ClipQLeft + cmp si, [mx_ClipY1] + jge ccTT + jmp ClipQTop +cc06: + call ClipQRight + cmp si, [mx_ClipY1] + jge ccTT + jmp ClipQTop +cc08: + jmp ClipQBottom +cc09: + call ClipQLeft + cmp si, [mx_ClipY2] + jle ccTT + jmp ClipQBottom +cc0A: + call ClipQRight + cmp si, [mx_ClipY2] + jle ccTT + jmp ClipQBottom + +; Group 10 ------------------------------------------------- +; +cc10FF: + stc + ret +cc10TT: + clc + ret +cc10: + jmp ClipPLeft +cc12: + call ClipPLeft + jmp ClipQRight +cc14: + call ClipPLeft + cmp bx, [mx_ClipY1] + jl cc10FF + jmp ClipQTop +cc16: + call ClipPLeft + cmp bx, [mx_ClipY1] + jl cc10FF + call ClipQTop + cmp cx, [mx_ClipX2] + jle cc10TT + jmp ClipQRight +cc18: + call ClipPLeft + cmp bx, [mx_ClipY2] + jg cc10FF + jmp ClipQBottom +cc1A: + call ClipPLeft + cmp bx, [mx_ClipY2] + jg cc10FF + call ClipQBottom + cmp cx, [mx_ClipX2] + jle cc10TT + jmp ClipQRight + +; Group 20 ------------------------------------------------- +; +cc20TT: + clc + ret +cc20FF: + stc + ret +cc20: + jmp ClipPRight +cc21: + call ClipPRight + jmp ClipQLeft +cc24: + call ClipPRight + cmp bx, [mx_ClipY1] + jl cc20FF + jmp ClipQTop +cc25: + call ClipPRight + cmp bx, [mx_ClipY1] + jl cc20FF + call ClipQTop + cmp cx, [mx_ClipX1] + jge cc20TT + jmp ClipQLeft +cc28: + call ClipPRight + cmp bx, [mx_ClipY2] + jg cc20FF + jmp ClipQBottom +cc29: + call ClipPRight + cmp bx, [mx_ClipY2] + jg cc20FF + call ClipQBottom + cmp cx, [mx_ClipX1] + jge cc20TT + jmp ClipQLeft + +; Group 40 ------------------------------------------------- +; +cc40TT: + clc + ret +cc40FF: + stc + ret +cc40: + jmp ClipPTop +cc41: + call ClipPTop + cmp di, [mx_ClipX1] + jl cc40FF + call ClipQLeft + cmp si, [mx_ClipY1] + jge cc40TT + jmp ClipQTop +cc42: + call ClipPTop + cmp di, [mx_ClipX2] + jg cc40FF + jmp ClipQRight +cc48: + call ClipPTop + jmp ClipQBottom +cc49: + call ClipPTop + cmp di, [mx_ClipX1] + jl cc40FF + call ClipQLeft + cmp si, [mx_ClipY2] + jle cc40TT + jmp ClipQBottom +cc4A: + call ClipPTop + cmp di, [mx_ClipX2] + jg cc40FF + call ClipQRight + cmp si, [mx_ClipY2] + jle cc40TT + jmp ClipQBottom + + +; Group 50 ------------------------------------------------- +; +cc50TT: + clc + ret +cc50FF: + stc + ret +cc50: + call ClipPLeft + cmp bx, [mx_ClipY1] + jge cc50TT + jmp ClipPTop +cc52: + call ClipQRight + cmp si, [mx_ClipY1] + jl cc50FF + call ClipPTop + cmp di, [mx_ClipX1] + jge cc50TT + jmp ClipPLeft +cc58: + call ClipQBottom + cmp cx, [mx_ClipX1] + jl cc50FF + call ClipPTop + cmp di, [mx_ClipX1] + jge cc50TT + jmp ClipPLeft +cc5A: + call ClipPLeft + cmp bx, [mx_ClipY2] + jg cc50FF + call ClipQRight + cmp bx, [mx_ClipY1] + jl cc50FF + cmp si, [mx_ClipY2] + jle cc50TT + jmp ClipQBottom + +; Group 60 ------------------------------------------------- +; +cc60TT: + clc + ret +cc60FF: + stc + ret +cc60: + call ClipPRight + cmp bx, [mx_ClipY1] + jge cc60TT + jmp ClipPTop +cc61: + call ClipQLeft + cmp si, [mx_ClipY2] + jl cc60FF + call ClipPTop + cmp di, [mx_ClipX2] + jle cc60TT + jmp ClipPRight +cc68: + call ClipQBottom + cmp cx, [mx_ClipX2] + jg cc60FF + call ClipPRight + cmp bx, [mx_ClipY1] + jge cc60TT + jmp ClipPTop +cc69: + call ClipQLeft + cmp si, [mx_ClipY1] + jl cc60FF + call ClipPRight + cmp bx, [mx_ClipY2] + jg cc60FF + cmp si, [mx_ClipY2] + jle cc69_1 + call ClipQBottom +cc69_1: + cmp bx, [mx_ClipY1] + jge cc60TT + jmp ClipPTop + +; Group 80 ------------------------------------------------- +; +cc80TT: + clc + ret +cc80FF: + stc + ret +cc80: + jmp ClipPBottom +cc81: + call ClipPBottom + cmp di, [mx_ClipX1] + jl cc80FF + jmp ClipQLeft +cc82: + call ClipPBottom + cmp di, [mx_ClipX2] + jg cc80FF + jmp ClipQRight +cc84: + call ClipPBottom + jmp ClipQTop +cc85: + call ClipPBottom + cmp di, [mx_ClipX1] + jl cc80FF + call ClipQLeft + cmp si, [mx_ClipY1] + jge cc80FF + jmp ClipQTop +cc86: + call ClipPBottom + cmp di, [mx_ClipX2] + jg cc80FF + call ClipQRight + cmp si, [mx_ClipY1] + jge cc80TT + jmp ClipQTop + +; Group 90 ------------------------------------------------- +; +cc90TT: + clc + ret +cc90FF: + stc + ret +cc90: + call ClipPLeft + cmp bx, [mx_ClipY2] + jle cc90TT + jmp ClipPBottom +cc92: + call ClipQRight + cmp si, [mx_ClipY2] + jg cc90FF + call ClipPBottom + cmp di, [mx_ClipX1] + jge cc90TT + jmp ClipPLeft +cc94: + call ClipQTop + cmp cx, [mx_ClipX1] + jl cc90FF + call ClipPLeft + cmp bx, [mx_ClipY2] + jle cc90TT + jmp ClipPBottom +cc96: + call ClipPLeft + cmp bx, [mx_ClipY1] + jl cc90FF + call ClipQRight + cmp si, [mx_ClipY2] + jg cc90FF + cmp bx, [mx_ClipY2] + jle cc96_1 + call ClipPBottom +cc96_1: + cmp si, [mx_ClipY1] + jge cc90TT + jmp ClipQTop + +; Group A0 ------------------------------------------------- +; +ccA0TT: + clc + ret +ccA0FF: + stc + ret +ccA0: + call ClipPRight + cmp bx, [mx_ClipY2] + jle ccA0TT + jmp ClipPBottom +ccA1: + call ClipQLeft + cmp si, [mx_ClipY2] + jg ccA0FF + call ClipPBottom + cmp di, [mx_ClipX2] + jle ccA0TT + jmp ClipPRight +ccA4: + call ClipQTop + cmp cx, [mx_ClipX2] + jg ccA0FF + call ClipPRight + cmp bx, [mx_ClipY2] + jle ccA0TT + jmp ClipPBottom +ccA5: + call ClipQLeft + cmp si, [mx_ClipY2] + jg ccA0FF + call ClipPRight + cmp bx, [mx_ClipY1] + jl ccA0FF + cmp si, [mx_ClipY1] + jge ccA5_1 + call ClipQTop +ccA5_1: + cmp bx, [mx_ClipY2] + jle ccA0TT + jmp ClipPBottom + +; Y1 = (Y2-Y1)*(mx_ClipX1-X1)/(X2-X1)+Y1 = (SI-BX)*(mx_ClipX1-DI)/(CX-DI)+BX +; X1 = mx_ClipX1 +ClipPLeft: + mov ax, si + sub ax, bx + mov dx, [mx_ClipX1] + sub dx, di + imul dx + mov bp, cx + sub bp, di + idiv bp + add bx, ax + mov di, [mx_ClipX1] + clc + ret + +; Y1 = (Y2-Y1)*(mx_ClipX2-X1)/(X2-X1)+Y1 = (SI-BX)*(mx_ClipX2-DI)/(CX-DI)+BX +; X1 = mx_ClipX2 +ClipPRight: + mov ax, si + sub ax, bx + mov dx, [mx_ClipX2] + sub dx, di + imul dx + mov bp, cx + sub bp, di + idiv bp + add bx, ax + mov di, [mx_ClipX2] + clc + ret + +; X1 = (X2-X1)*(mx_ClipY2-Y1)/(Y2-Y1)+X1 = (CX-DI)*(mx_ClipY2-BX)/(SI-BX)+DI +; Y1 = mx_ClipY2 +ClipPBottom: + mov ax, cx + sub ax, di + mov dx, [mx_ClipY2] + sub dx, bx + imul dx + mov bp, si + sub bp, bx + idiv bp + add di, ax + mov bx, [mx_ClipY2] + clc + ret + +; X1 = (X2-X1)*(mx_ClipY1-Y1)/(Y2-Y1)+X1 = (CX-DI)*(mx_ClipY1-BX)/(SI-BX)+DI +; Y1 = mx_ClipY1 +ClipPTop: + mov ax, cx + sub ax, di + mov dx, [mx_ClipY1] + sub dx, bx + imul dx + mov bp, si + sub bp, bx + idiv bp + add di, ax + mov bx, [mx_ClipY1] + clc + ret + +; Y2 = (Y1-Y2)*(mx_ClipX1-X2)/(X1-X2)+Y2 = (BX-SI)*(mx_ClipX1-CX)/(DI-CX)+SI +; X2 = mx_ClipX1 +ClipQLeft: + mov ax, bx + sub ax, si + mov dx, [mx_ClipX1] + sub dx, cx + imul dx + mov bp, di + sub bp, cx + idiv bp + add si, ax + mov cx, [mx_ClipX1] + clc + ret + +; Y2 = (Y1-Y2)*(mx_ClipX2-X2)/(X1-X2)+Y2 = (BX-SI)*(mx_ClipX2-CX)/(DI-CX)+SI +; X2 = mx_ClipX1 +ClipQRight: + mov ax, bx + sub ax, si + mov dx, [mx_ClipX2] + sub dx, cx + imul dx + mov bp, di + sub bp, cx + idiv bp + add si, ax + mov cx, [mx_ClipX2] + clc + ret + +; X2 = (X1-X2)*(mx_ClipY2-Y2)/(Y1-Y2)+X2 = (DI-CX)*(mx_ClipY2-SI)/(BX-SI)+CX +; Y2 = mx_ClipY1 +ClipQBottom: + mov ax, di + sub ax, cx + mov dx, [mx_ClipY2] + sub dx, si + imul dx + mov bp, bx + sub bp, si + idiv bp + add cx, ax + mov si, [mx_ClipY2] + clc + ret + +; X2 = (X1-X2)*(mx_ClipY1-Y2)/(Y1-Y2)+X2 = (DI-CX)*(mx_ClipY1-SI)/(BX-SI)+CX +; Y2 = mx_ClipY1 +ClipQTop: + mov ax, di + sub ax, cx + mov dx, [mx_ClipY1] + sub dx, si + imul dx + mov bp, bx + sub bp, si + idiv bp + add cx, ax + mov si, [mx_ClipY1] + clc + ret + +;----------------------------------------------------------- +; +; Checks the coordinates of a line against the active +; clip region. +; Uses the Sobkow-Pospisil-Yang (SPY) algorithm: this was +; supposed to be twice as fast as Cohen-Sutherland, but my +; tests show only a very small increase in speed and a noticeable +; increase of the program size! Maybe this is caused by the +; slow speed of VGA cards, so probably a better test should +; be performed with lines drawn in RAM. +; +; Input: +; AX, BX = X1, Y1 +; CX, DX = X2, Y2 +; Output: +; CF = set if line is full clipped +; AX, BX = clipped X1, Y1 +; CX, DX = clipped X2, Y2 +; Note: +; destroys SI, DI +; +xsubClipLine PROC NEAR + push bp + xor si, si ; SPY code + + cmp dx, [mx_ClipY2] + jle @@1 + or si, 08h + jmp @@2 +@@1: + cmp dx, [mx_ClipY1] + jge @@2 + or si, 04h +@@2: + + cmp cx, [mx_ClipX2] + jle @@3 + or si, 02h + jmp @@4 +@@3: + cmp cx, [mx_ClipX1] + jge @@4 + or si, 01h +@@4: + + cmp bx, [mx_ClipY2] + jle @@5 + or si, 80h + jmp @@6 +@@5: + cmp bx, [mx_ClipY1] + jge @@6 + or si, 40h +@@6: + + cmp ax, [mx_ClipX2] + jle @@7 + or si, 20h + jmp @@8 +@@7: + cmp ax, [mx_ClipX1] + jge @@8 + or si, 10h +@@8: + + mov di, si + and di, 000Fh ; Index of procedure + and si, 00F0h + .shr si, 2 ; Index of group (times 4) + cmp di, cs:tblGroups[si] ; Is index within range? + jg @@Exit ; No, line is full clipped + mov si, cs:tblGroups[si+2] ; Get offset of group table + shl di, 1 ; We must index word elements + add si, di ; Make full offset + mov di, ax ; Move X1 to DI and free AX + mov si, cs:[si] ; Get subroutine address + xchg dx, si ; Move Y2 to SI and free DX + call dx ; Call the proper subroutine + mov ax, di ; Restore AX to X1 + mov dx, si ; Restore DX to Y2 + pop bp + ret + +@@Exit: + pop bp + stc + ret +xsubClipLine ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxcg.asm b/16/x/mxcg.asm new file mode 100755 index 00000000..42163d7a --- /dev/null +++ b/16/x/mxcg.asm @@ -0,0 +1,69 @@ +;----------------------------------------------------------- +; +; MXCG.ASM - Color to gray conversion +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxColorToGray + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Converts RGB colors to gray shades. +; +; Input: +; CPal = pointer to color palette +; GPal = pointer to destination (gray) palette +; Count = number of colors to convert +; Output: +; none +; +; Note: CPal and GPal may point to the same buffer. +; +mxColorToGray PROC FAR + ARG Count:WORD, \ + DPal:DWORD, \ + SPal:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si, es, di + + mov cx, [Count] + jcxz @@Exit + lds si, [SPal] + les di, [DPal] + cld +; We use the standard formula +; gray=(red*30 + green*59 + blue*11)/100 +; in the equivalent form +; gray=(red*77 + green*151 + blue*28)/256 +; which doesn't need the last divide. + mov bx, 77 SHL 8 + 151 +@@Loop: + lodsb ; Red + mul bh + mov dx, ax + lodsb ; Green + mul bl + add dx, ax + lodsb ; Blue + mov ah, 28 + mul ah + add ax, dx + mov al, ah + stosw ; Save new RGB + stosb + loop @@Loop + +@@Exit: + .pop ds, si, es, di + .leave ARG_SIZE +mxColorToGray ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxcl.asm b/16/x/mxcl.asm new file mode 100755 index 00000000..aaa0bac3 --- /dev/null +++ b/16/x/mxcl.asm @@ -0,0 +1,151 @@ +;----------------------------------------------------------- +; +; MXCL.ASM - Bresenham circle +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxCircle + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD +EXTRN mx_VideoSegment : WORD +EXTRN mx_ClipX1 : WORD +EXTRN mx_ClipY1 : WORD +EXTRN mx_ClipX2 : WORD +EXTRN mx_ClipY2 : WORD + +;----------------------------------------------------------- +; +; Draws a circle using the Bresenham algorithm. +; +; Input: +; XC, YC = center coordinates +; Radius = circle radius +; Color = circle color +; Output: +; none +; Note: +; computes only points in the first octant, all other +; points are obtained by symmetry. +; +mxCircle PROC FAR + ARG Color:BYTE:2, \ + Radius:WORD, \ + YC:WORD, \ + XC:WORD = ARG_SIZE + LOCAL Delta:WORD = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, di + + xor si, si ; X + mov di, [Radius] ; Y + mov ax, 3 + sub ax, di + sub ax, di + mov [Delta], ax ; Delta = 3-R*2 + + mov ds, [mx_VideoSegment] + +@@Loop: + cmp si, di ; + jg @@Done ; Exit when X > Y +; Draw points + mov ax, si + mov bx, di + call @@subPutPixel + mov ax, si + neg ax + mov bx, di + call @@subPutPixel + mov ax, si + mov bx, di + neg bx + call @@subPutPixel + mov ax, si + neg ax + mov bx, di + neg bx + call @@subPutPixel + mov ax, di + mov bx, si + call @@subPutPixel + mov ax, di + neg ax + mov bx, si + call @@subPutPixel + mov ax, di + mov bx, si + neg bx + call @@subPutPixel + mov ax, di + neg ax + mov bx, si + neg bx + call @@subPutPixel +; Moves coordinates to next point + mov ax, [Delta] + test ax, ax + jl @@Next + mov ax, di + .shl ax, 2 + sub ax, 4 + sub [Delta], ax + dec di +@@Next: + mov ax, si + .shl ax, 2 + add ax, 6 + add [Delta], ax + inc si + jmp @@Loop + +@@Done: + xor ax, ax + .pop ds, si, di + .leave ARG_SIZE + +;--------------------------------------- +; Put pixel function. +; Input: +; BX = X coordinate (relative to center) +; AX = Y coordinate (relative to center) +; DS = video segment +@@subPutPixel: + add bx, [XC] ; Get absolute coordinates + add ax, [YC] + + cmp bx, [mx_ClipX1] ; Clip pixel + jl @@subExit + cmp bx, [mx_ClipX2] + jg @@subExit + cmp ax, [mx_ClipY1] + jl @@subExit + cmp ax, [mx_ClipY2] + jg @@subExit + + mul [mx_BytesPerLine] ; Get pixel offset + mov cx, bx ; Save X coordinate + .shr bx, 2 + add bx, ax ; DS:BX = pixel offset + + and cl, 3 ; Set write plane + mov ax, 0102h + shl ah, cl + mov dx, TS + out dx, ax + + mov al, [Color] ; Write pixel + mov ds:[bx], al + +@@subExit: + retn +mxCircle ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxcr.asm b/16/x/mxcr.asm new file mode 100755 index 00000000..ca1fa7bb --- /dev/null +++ b/16/x/mxcr.asm @@ -0,0 +1,380 @@ +;----------------------------------------------------------- +; +; MXCR.ASM - Clip functions +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxSetSysClipRegion +PUBLIC mxGetClipRegion +PUBLIC mxSetClipRegion +PUBLIC mxSetClip +PUBLIC mxGetClip + +PUBLIC subClipBox +PUBLIC subClipImage + +PUBLIC mx_ClipX1 +PUBLIC mx_ClipY1 +PUBLIC mx_ClipX2 +PUBLIC mx_ClipY2 + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_CodeSegment : WORD + +mx_ClipX1 DW ? ; Clip coordinates +mx_ClipY1 DW ? +mx_ClipX2 DW ? +mx_ClipY2 DW ? + +mx_SysClipX1 DW ? ; System clip coordinates +mx_SysClipY1 DW ? ; (active when mx_ClipStatus is FALSE) +mx_SysClipX2 DW ? +mx_SysClipY2 DW ? + +mx_UserClipX1 DW ? ; User clip coordinates +mx_UserClipY1 DW ? ; (active when mx_ClipStatus is TRUE) +mx_UserClipX2 DW ? +mx_UserClipY2 DW ? + +mx_ClipStatus DB ? + +;----------------------------------------------------------- +; +; Toggles clipping between user and system regions. +; +; Input: +; ClipStatus = TRUE (FALSE) to enable (disable) clipping +; Output: +; AX = old clip status +; +mxSetClip PROC FAR + ARG ClipStatus:BYTE:2 = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, [mx_UserClipX1] + mov bx, [mx_UserClipY1] + mov cx, [mx_UserClipX2] + mov dx, [mx_UserClipY2] + cmp [ClipStatus], TRUE + je @@Done + mov ax, [mx_SysClipX1] + mov bx, [mx_SysClipY1] + mov cx, [mx_SysClipX2] + mov dx, [mx_SysClipY2] +@@Done: + mov [mx_ClipX1], ax + mov [mx_ClipY1], bx + mov [mx_ClipX2], cx + mov [mx_ClipY2], dx + + mov al, [ClipStatus] + xchg al, [mx_ClipStatus] + xor ah, ah + + .pop ds + .leave ARG_SIZE +mxSetClip ENDP + +;----------------------------------------------------------- +; +; Returns the current clipping status. +; +; Input: +; none +; Output: +; TRUE (FALSE) if clipping enabled (disabled) +; +mxGetClip PROC FAR + ASSUME ds:NOTHING + mov al, [mx_ClipStatus] + xor ah, ah + ret +mxGetClip ENDP + +;----------------------------------------------------------- +; +; Sets the system clip region and disables user clipping. +; +; Input: +; Width = width in pixels of clip region +; Height = height in pixels of clip region +; Output: +; old clip status. +; +mxSetSysClipRegion PROC FAR + ARG Height:WORD, \ + Width:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + xor ax, ax ; Sys clip region always starts at (0,0) + mov [mx_SysClipX1], ax + mov [mx_SysClipY1], ax + mov ax, [Width] + dec ax + mov [mx_SysClipX2], ax + mov ax, [Height] + dec ax + mov [mx_SysClipY2], ax + + IF USE286 EQ TRUE + push FALSE + ELSE + mov ax, FALSE + push ax + ENDIF + call mxSetClip + + .pop ds + .leave ARG_SIZE +mxSetSysClipRegion ENDP + +;----------------------------------------------------------- +; +; Sets the clip region. +; +; Input: +; X, Y = coordinates of top left corner of clip region +; Width = width in pixels of clip region +; Height = height in pixels of clip region +; Output: +; none (no checking on parameters) +; +mxSetClipRegion PROC FAR + ARG Height:WORD, \ + Width:WORD, \ + Y:WORD, \ + X:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, [X] + mov [mx_UserClipX1], ax + mov ax, [Y] + mov [mx_UserClipY1], ax + mov ax, [Width] + add ax, [X] + dec ax + mov [mx_UserClipX2], ax + mov ax, [Height] + add ax, [Y] + dec ax + mov [mx_UserClipY2], ax + + mov al, [mx_ClipStatus] + cmp al, TRUE + jne @@Exit + push ax + call mxSetClip + +@@Exit: + xor ax, ax + .pop ds + .leave ARG_SIZE +mxSetClipRegion ENDP + +;----------------------------------------------------------- +; +; Returns the current user clip region. +; +; Input: +; X, Y = pointers to integer coordinates of top left corner +; Width = pointer to word width of clip region +; Height = pointer to word height of clip region +; Output: +; AX = current clip status +; +mxGetClipRegion PROC FAR + ARG Height:DWORD, \ + Width:DWORD, \ + Y:DWORD, \ + X:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push es, di + + mov ax, [mx_UserClipX1] + les di, [X] + mov es:[di], ax + mov ax, [mx_UserClipY1] + les di, [Y] + mov es:[di], ax + + mov ax, [mx_UserClipX2] + sub ax, [mx_UserClipX1] + inc ax + les di, [Width] + mov es:[di], ax + mov ax, [mx_UserClipY2] + sub ax, [mx_UserClipY1] + inc ax + les di, [Height] + mov es:[di], ax + + mov al, [mx_ClipStatus] + xor ah, ah + .pop es, di + .leave ARG_SIZE +mxGetClipRegion ENDP + +;----------------------------------------------------------- +; +; Internal use: checks the coordinates of a rectangle against +; the active clip region. +; This function assumes that a "raw" image has to be clipped, +; so it returns in SI the number of "raw" bytes to skip if +; X, Y were clipped. +; +; Input: +; BX, AX = X, Y coordinates of rectangle (signed) +; CX = box width +; DX = box height +; Output: +; CF = set if rectangle is full clipped +; BX, AX = new X, Y coordinates of rectangle +; CX, DX = clipped width and height +; SI = number of bytes to skip before copying a buffer +; DI destroyed +; +subClipImage PROC NEAR + ASSUME ds:NOTHING + xor si, si + +; Check clip height + mov di, [mx_ClipY1] + cmp ax, di + jge @@CheckBottom + sub di, ax ; Number of lines to clip + sub dx, di ; New box height + jle @@Exit + mov ax, di + mov di, dx ; Save box height into DI + mul cx ; DX:AX = number of bytes to skip + mov si, ax + mov dx, di ; Restore box height + mov ax, [mx_ClipY1] +@@CheckBottom: + mov di, [mx_ClipY2] + cmp ax, di + jg @@Exit + inc di + sub di, dx + sub di, ax + jge @@DoneHeight ; None, continue + add dx, di ; Clip lines +@@DoneHeight: + +; Check clip width +@@CheckLeft: + mov di, [mx_ClipX1] + cmp bx, di + jge @@CheckRight + sub di, bx ; Number of columns to clip left + sub cx, di + jle @@Exit + add si, di ; Update skip count + mov bx, [mx_ClipX1] +@@CheckRight: + mov di, [mx_ClipX2] + cmp bx, di + jg @@Exit + inc di + sub di, bx + sub di, cx + jge @@DoneWidth ; None, exit + add cx, di ; New box width +@@DoneWidth: + +; Set return flag and exit +@@Done: + clc + ret +@@Exit: + stc + ret +subClipImage ENDP + +;----------------------------------------------------------- +; +; Internal use: checks the coordinates of a rectangle against +; the active clip region. +; +; Input: +; BX, AX = X, Y coordinates of rectangle (signed) +; CX = box width +; DX = box height +; Output: +; CF = set if rectangle is full clipped +; BX, AX = new X, Y coordinates of rectangle +; CX, DX = clipped width and height +; DI destroyed +; +subClipBox PROC NEAR + ASSUME ds:NOTHING + +; Check clip height + mov di, [mx_ClipY1] + cmp ax, di + jge @@CheckBottom + sub di, ax ; Number of lines to clip + sub dx, di ; New box height + jle @@Exit + mov ax, [mx_ClipY1] +@@CheckBottom: + mov di, [mx_ClipY2] + cmp ax, di + jg @@Exit + inc di + sub di, dx + sub di, ax ; Clipped some point? + jge @@DoneHeight ; No, continue + add dx, di ; Clip lines (DI is negative) +@@DoneHeight: + +; Check clip width +@@CheckLeft: + mov di, [mx_ClipX1] + cmp bx, di + jge @@CheckRight + sub di, bx ; Number of columns to clip left + sub cx, di + jle @@Exit + mov bx, [mx_ClipX1] +@@CheckRight: + mov di, [mx_ClipX2] + cmp bx, di + jg @@Exit + inc di + sub di, bx + sub di, cx ; Clipped some point? + jge @@DoneWidth ; No, exit + add cx, di ; New box width (DI is negative) +@@DoneWidth: + +; Set return flag and exit +@@Done: + clc + ret +@@Exit: + stc + ret +subClipBox ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxel.asm b/16/x/mxel.asm new file mode 100755 index 00000000..2c9dda2a --- /dev/null +++ b/16/x/mxel.asm @@ -0,0 +1,167 @@ +;----------------------------------------------------------- +; +; MXEL.ASM - Mid-point ellipse +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxEllipse + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD +EXTRN mx_VideoSegment : WORD +EXTRN mx_ClipX1 : WORD +EXTRN mx_ClipY1 : WORD +EXTRN mx_ClipX2 : WORD +EXTRN mx_ClipY2 : WORD + +;----------------------------------------------------------- +; +; Draws an ellipse using the mid-point algorithm. +; +; Input: +; XC, YC = center coordinates +; A = horizontal radius +; B = vertical radius +; Color = ellipse color +; Output: +; none +; Note: +; computes only points in the first quadrant, all other +; points are obtained by symmetry. +; +mxEllipse PROC FAR + ARG Color:BYTE:2, \ + B:WORD, \ + A:WORD, \ + YC:WORD, \ + XC:WORD = ARG_SIZE + LOCAL A2:DWORD, \ + B2:DWORD, \ + CC:DWORD, \ + DD:DWORD, \ + X:DWORD, \ + Y:DWORD = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, di + + .chk386 mxEllipse, @@Exit + +; Initialize variables + xor eax, eax + mov [X], ax ; X = 0 + mov ax, [A] + mul eax ; EAX = A*A + mov [DD], eax ; DD = A*A + shl eax, 1 + mov [CC], eax ; CC = 2*A*A + shl eax, 1 + mov [A2], eax ; A2 = 4*A*A + movzx edx, [B] + mov [Y], edx + mul edx ; EAX = 4*A*A*B + sub [DD], eax ; DD = A*A - 4*A*A*B + movzx eax, [B] + mul eax ; EAX = B*B + shl eax, 2 ; EAX = 4*B*B + mov [B2], eax ; B2 = 4*B*B + add [CC], eax ; CC = 2*A*A + 4*B*B + add [D1], eax ; DD = A*A - 4*A*A*B + 4*B*B + +; Draw initial points + call subPlot4 + +; First loop +@@Loop1: + mov eax, [X] ; Check slope + mul [B2] + mov ecx, eax + mov eax, [Y] + mul [A2] + sub eax, ecx + sub eax, [CC] ; EAX = Y*A2 - X*B2 - CC + jle @@Done1 ; Crossed critical point, jump to next loop + + mov ecx, [DD] ; Get error + test ecx, ecx ; Positive? + jl @@Draw1 ; No, use default step + + mov eax, 1 + sub eax, [Y] + mul [A2] + shl eax, 1 + add ecx, eax ; Bump error + dec WORD PTR [Y] ; Decrement Y coordinate + +@@Draw1: + mov eax, [X] + shl eax, 1 + add eax, 3 + mul [B2] + add ecx, eax ; Bump error + mov [DD], ecx ; Save error + inc WORD PTR [X] ; Increment X coordinate + + call subPlot4 ; Draw points + jmp @@Loop1 +@@Done1: + +; Initialize variables + shr [B2], 2 + mov eax, [X] + mul eax + add [X] + shl eax, 2 + inc eax + mul [B2] + mov [DD], eax + mov eax, [Y] + mul eax + add [Y] + dec eax + add [Y] + sub eax, [B2] + add [DD], eax + shl [B2], 3 + inc WORD PTR [X] + +; Second loop +@@Loop2: + cmp WORD PTR [Y], 0 + ja @@Done2 + + mov ecx, [DD] + test ecx, ecx + jge @@Draw2 + + mov eax, [X] + inc eax + mul [B2] + add ecx, eax + inc WORD PTR [X] + +@@Draw2: + mov eax, [Y] + shl eax, 1 + sub eax, 3 + neg eax + imul [A2] + add ecx, eax + dec WORD PTR [Y] + + call subPlot4 + jmp @@Loop2 +@@Done2: + +@@Exit: + xor ax, ax + .leave ARG_SIZE +mxEllipse ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxfb.asm b/16/x/mxfb.asm new file mode 100755 index 00000000..41ea5deb --- /dev/null +++ b/16/x/mxfb.asm @@ -0,0 +1,194 @@ +;----------------------------------------------------------- +; +; MXFB.ASM - Fill box function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxFillBox + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD +EXTRN mx_VideoSegment : WORD +EXTRN subClipBox : NEAR +EXTRN subHorizontalLineInfo : NEAR + +;----------------------------------------------------------- +; +; Raster op functions. Raster op is limited to OP_MOVE, +; OP_AND, OP_OR and OP_XOR. The VGA hardware is used to +; perform the selected logical functions on up to four +; pixel at a time. +; +subRepFill PROC NEAR + mov ah, al + shr cx, 1 + rep stosw + rcl cx, 1 + rep stosb + ret +subRepFill ENDP +; +subFill PROC NEAR +@@Loop: + mov ds:[bx], al + add bx, dx + loop @@Loop + ret +subFill ENDP +; +subRepMove PROC NEAR + mov si, di +@@Loop: + mov ah, ds:[si] ; Dummy read to latch the data + mov ds:[si], al + inc si + loop @@Loop + ret +subRepMove ENDP +; +subMove PROC NEAR +@@Loop: + mov ah, ds:[bx] ; Dummy read to latch the data + mov ds:[bx], al + add bx, dx + loop @@Loop + ret +subMove ENDP + +;----------------------------------------------------------- +; +; Fills a rectangle with a specified color. +; +; Input: +; X, Y = X, Y coordinates of rectangle +; Width = width of rectangle +; Height = height of rectangle +; Color = fill color +; Op = raster operator +; Output: +; none +; +; Note: raster op is limited to OP_MOVE, OP_AND, OP_OR and OP_XOR. +; +mxFillBox PROC FAR + ARG Op:WORD, \ + Color:BYTE:2, \ + Height:WORD, \ + Width:WORD, \ + Y:WORD, \ + X:WORD = ARG_SIZE + LOCAL LeftMask:BYTE, \ + RightMask:BYTE, \ + FillFunction:WORD, \ + RepFillFunction:WORD = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, es, di + ASSUME ds:NOTHING + +; Clip rectangle + mov bx, [X] + mov ax, [Y] + mov cx, [Width] + mov dx, [Height] + call subClipBox + jc @@Exit ; Full clipped + + mov [Height], dx ; Save clipped height + call subHorizontalLineInfo ; Get additional info, init DI + mov [Width], cx + mov [LeftMask], al + mov [RightMask], ah + +; Initialize segments + mov ax, [mx_VideoSegment] + mov es, ax ; ES:DI points to pixel + mov ds, ax + cld ; Clear direction flag + +; Select fill functions + mov [FillFunction], OFFSET subFill + mov [RepFillFunction], OFFSET subRepFill + mov ax, [Op] ; Get raster op + cmp al, OP_XOR + ja @@1 ; Assume it's a fill + cmp al, OP_MOVE + je @@1 + .shl al, 3 + mov ah, al + mov al, 03h + mov dx, GDC + out dx, ax ; Set GDC logical function + mov [FillFunction], OFFSET subMove + mov [RepFillFunction], OFFSET subRepMove +@@1: + +; Fill left block +@@L0: + mov ah, [LeftMask] + or ah, ah + jz @@C0 ; Nothing to do, go to center block + mov dx, TS + mov al, 02h + out dx, ax ; Set write plane mask + mov dx, [mx_BytesPerLine] + mov cx, [Height] + mov bx, di + mov al, [Color] + call [FillFunction] ; Fill this column + inc di ; Update starting video offset + +; Fill center block +@@C0: + mov cx, [Width] + jcxz @@R0 ; Nothing to do, go to right block + mov dx, TS + mov ax, 0F02h + out dx, ax ; Write to all planes + mov al, [Color] + mov bx, di + mov dx, [Height] + push di ; Save pixel address +@@C1: + mov di, bx ; Update video offset + call [RepFillFunction] ; Fill current scan line + mov cx, [Width] ; Restore byte count + add bx, [mx_BytesPerLine] ; Bump to next scan line + dec dx ; Done all lines? + jnz @@C1 ; No, continue + pop di ; Restore pixel address + add di, [Width] ; Go to right block + +; Fill right block +@@R0: + mov ah, [RightMask] + or ah, ah + jz @@Done ; Nothing to do, exit + mov dx, TS + mov al, 02h + out dx, ax ; Set write plane mask + mov dx, [mx_BytesPerLine] + mov cx, [Height] + mov bx, di + mov al, [Color] + call [FillFunction] ; Fill this column + +; Restore VGA registers +@@Done: + mov dx, GDC + mov ax, 0003h + out dx, ax ; Set logical function to "move" + +@@Exit: + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxFillBox ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxfp.asm b/16/x/mxfp.asm new file mode 100755 index 00000000..8eea25be --- /dev/null +++ b/16/x/mxfp.asm @@ -0,0 +1,326 @@ +;----------------------------------------------------------- +; +; MXFP.ASM - Fade palette function +; Copyright (c) 1992-1994 ARTIS s.r.l. +; Author: Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxFadePalette + +MAXCOLOR EQU 256 +FADE_IN EQU 0 +FADE_OUT EQU 1 + +; The actual speed of fading depends on the number of passes (FADE_SPEED) and +; the delay between two consecutive passes (FADE_DELAY). Below are the +; default values, used when no parameters are specified. +; +FADE_DELAY EQU 1 ; Vert. retraces between video updates +FADE_SPEED EQU 48 ; Speed of effect (max 127) + +; Bit field record for fade commands +; +FADE_COMMAND RECORD fpDELAY:8,fpSPEED:7,fpDIRECTION:1 + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +DB 'Copyright (c) 1992-1994 ARTIS s.r.l. All rights reserved.' + +;----------------------------------------------------------- +; +; Fades a VGA palette. +; +; Input: +; Buffer = pointer to source/destination palette +; Command = fading direction and optional parameters +; Start = index of first color to fade +; Count = number of color to fade +; Red = destination red +; Green = destination green +; Blue = destination blue +; Output: +; none +; Notes: +; - about 1.5 Kbytes of stack space are needed for internal buffers; +; - the Command argument usually is 0 to fade in and 1 to fade out, +; however additional parameters may be specified. To set the effect +; speed, i.e. the number of iterations needed to completely fade a +; palette, shift the value one bit left and "or" it with the +; direction bit (range is 0..127). To set the delay between two +; consecutive passes, shift it eight bits left (range is 0..255). +; +mxFadePalette PROC FAR + ARG bBlue:WORD, \ + bGreen:WORD, \ + bRed:WORD, \ + wCount:WORD, \ + wStartIdx:WORD, \ + wCommand:WORD, \ + vfpPalette:DWORD = ARG_SIZE + LOCAL bSPalette:BYTE:MAXCOLOR*3, \ + bDPalette:BYTE:MAXCOLOR*3, \ + bLoopIndex:BYTE, \ + bLoopStep:BYTE, \ + bLoopCount:BYTE, \ + wDelay:WORD, \ + wSpeed:WORD = AUTO_SIZE + ASSUME ds:NOTHING + .enter AUTO_SIZE + .push si, di, ds, es ; Save registers +; +; Check parameters and setup variables +; +@@GetDelay: + mov [wDelay], FADE_DELAY ; Set default delay + mov ax, [wCommand] ; Get command word + and ax, MASK fpDELAY ; Mask delay command + jz @@GetSpeed ; No command, get speed + IF USE286 EQ TRUE + shr ax, fpDELAY + ELSE + mov cl, fpDELAY ; Get size of delay field + shr ax, cl ; Right justify the field + ENDIF + mov [wDelay], ax ; Set new delay + +@@GetSpeed: + mov ax, [wCommand] ; Get command + and ax, MASK fpSPEED ; Mask speed + IF USE286 EQ TRUE + shr ax, fpSPEED + ELSE + mov cl, fpSPEED ; Get size of speed field + shr ax, cl ; Right justify the field + ENDIF + or ax, ax ; Any speed specified? + jnz @@SetVariables ; Yes, set variables + mov ax, FADE_SPEED ; Set default speed + +@@SetVariables: + mov [wSpeed], ax ; Set speed + inc ax ; Number of iterations + mov [bLoopCount], al ; Set loop count + mov [bLoopStep], 1 ; Assume we're fading in + mov [bLoopIndex], 0 +; +; Check bounds for bad values +; + mov ax, [wStartIdx] ; Get first index + cmp ax, MAXCOLOR ; Is in the valid range? + jae @@Exit ; No, exit + add ax, [wCount] ; Get last index + cmp ax, MAXCOLOR ; Is in the valid range? + jbe @@BoundsOk ; Yes, continue + mov ax, MAXCOLOR + sub ax, [wStartIdx] + mov [wCount], ax ; Set count to maximum value + or ax, ax + jz @@Exit ; Nothing to do, exit +@@BoundsOk: +; +; Copy the source palette in a local array: if we fade in it's ready to +; use, otherwise we'll overwrite it later +; + mov cx, [wCount] + mov ax, cx + shl ax, 1 + add cx, ax ; CX = wCount * 3 + mov ax, ss + mov es, ax + lea di, [bSPalette] ; ES:DI points to local palette + mov ax, [wStartIdx] + mov si, ax + shl ax, 1 + add ax, si + lds si, [vfpPalette] ; DS:SI points to user palette + add si, ax ; Skip unused entries + cld + shr cx, 1 + rep movsw + rcl cx, 1 + rep movsb +; +; Check direction +; + test [wCommand], MASK fpDIRECTION ; Are we fading in? + jz @@Main ; Yes, ok to continue + mov ax, [wSpeed] ; Get speed + mov [bLoopIndex], al ; Exchange first and last index + mov [bLoopStep], -1 ; Move backward + mov ax, ss ; Overwrite our copy of + mov ds, ax ; user palette with the + mov es, ax ; current active palette + lea di, [bSPalette] + mov ax, [wStartIdx] + mov cx, [wCount] + call ReadPalette ; Read current palette +; +; Prepare variables and registers for fading +; +@@Main: + mov bh, BYTE PTR [bRed] ; Destination red + and bh, 00111111b ; Be sure it's a valid VGA value + mov bl, BYTE PTR [bGreen] ; Destination green + and bl, 00111111b ; Be sure it's a valid VGA value + mov dh, BYTE PTR [bBlue] ; Destination blue + and dh, 00111111b ; Be sure it's a valid VGA value + mov dl, [bLoopIndex] ; Loop index + mov ax, ss ; All tables are stored + mov ds, ax ; in the stack segment, + mov es, ax ; set DS and ES +; +; Main loop +; +@@Loop: + mov ax, [wCount] ; Store count in AX + mov cx, [wSpeed] ; Set maximum speed in CX + lea si, [bSPalette] ; DS:SI points to source palette + lea di, [bDPalette] ; ES:DI points to dest. palette + call RecalcPalette ; Build a faded palette + + .push bx, dx ; Save registers we need + lea si, [bDPalette] ; DS:SI points to palette + mov ax, [wStartIdx] ; First index to write + mov bx, [wCount] ; Total entries to write + mov cx, [wDelay] ; Fade delay between updates + call WritePalette ; Write palette + .pop bx, dx ; Restore BX and DX + + add dl, [bLoopStep] ; Change fade intensity + dec [bLoopCount] ; Done? + jnz @@Loop ; No, loop again + +@@Exit: + .pop si, di, ds, es ; Restore registers + .leave ARG_SIZE +mxFadePalette ENDP + +;------- INTERNAL USE ONLY ------------------------------------------------ +; +; Calculates a partially faded palette. +; +; Input: +; AX = number of entries in palette +; CX = maximum fade intensity (same as fade speed) +; DS:SI = pointer to source palette +; ES:DI = pointer to destination palette +; BH = destination red +; BL = destination green +; DH = destination blue +; DL = relative intensity of destination palette +; Note: +; it's important that a new palette can be calculated in less +; than 1/70th of second. Fading to any RGB value requires use +; of "imul" instructions: "idiv" may be replaced with faster +; "sar", but only when the number of passes is a power of two, +; thus reducing the range of selectable speeds. +; In both cases an extimate of CPU cycles required by this +; procedure shows that it's too slow to run on a 4.77 Mhz 8086 +; CPU and a 256 color palette, so we keep "idiv" and hope +; the target machine to be at least a 6 Mhz 80286 (that's not +; asking too much...). +; +RecalcPalette PROC NEAR + cld + push bp ; Save BP + mov bp, ax ; Copy counter in BP +@@Loop: + lodsb ; Red: read value + sub al, bh ; Subtract destination value + imul dl ; Scale to desired weight + idiv cl ; Put value in AL + add al, bh ; Add destination value... + stosb ; ...and store it + lodsb ; Green: read value + sub al, bl ; Subtract destination value + imul dl ; Scale to desired weight + idiv cl ; Put value in AL + add al, bl ; Add destination value... + stosb ; ...and store it + lodsb ; Blue: read value + sub al, dh ; Subtract destination value + imul dl ; Scale to desired weight + idiv cl ; Put value in AL + add al, dh ; Add destination value... + stosb ; ...and store it + dec bp + jnz @@Loop + pop bp ; Restore BP + ret +RecalcPalette ENDP + +;------- INTERNAL USE ONLY ------------------------------------------------ +; +; Writes a 256 color palette. +; +; Input: +; AX = index of first color to write +; BX = number of colors to write (each color is an RGB triplet) +; CX = number of vertical retraces to wait before writing to DACs +; DS:SI = pointer to first entry of palette +; +WritePalette PROC NEAR + ASSUME ds:NOTHING + mov ah, al ; Save index + mov dx, 03DAh ; Input status register +@@Delay1: + in al, dx + test al, 08h + jnz @@Delay1 ; Wait for display mode +@@Delay2: + in al, dx + test al, 08h + jz @@Delay2 ; Wait for vertical retrace mode + loop @@Delay1 ; Repeat CX times +@@Write: + mov cx, bx ; Get number of colors + mov dx, 03C8h ; PEL write address register + mov al, ah ; Restore index + out dx, al ; Select index of first color + inc dx ; PEL data register + cld ; Move forward + cli ; Disable interrupts +@@Loop: + lodsb + out dx, al ; Red + lodsb + out dx, al ; Green + lodsb + out dx, al ; Blue + loop @@Loop ; Loop until done + sti ; Enable interrupts + ret +WritePalette ENDP + +;------- INTERNAL USE ONLY ------------------------------------------------ +; +; Reads the current palette. +; +; Input: +; AX = index of first color to read +; CX = number of colors +; ES:DI = pointer to destination buffer +; +ReadPalette PROC NEAR + mov dx, 03C7h + out dx, al + inc dx + inc dx + cld +@@Loop: + in al, dx + stosb + in al, dx + stosb + in al, dx + stosb + loop @@Loop + ret +ReadPalette ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxgc.asm b/16/x/mxgc.asm new file mode 100755 index 00000000..85edf7a6 --- /dev/null +++ b/16/x/mxgc.asm @@ -0,0 +1,54 @@ +;----------------------------------------------------------- +; +; MXGC.ASM - Get color function +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxGetColor + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Returns the current setting of the selected DAC register. +; +; Input: +; Index = color index (0-255) +; R, G, B = byte pointers to red, green and blue +; Output: +; none +; +mxGetColor PROC FAR + ARG B:DWORD, \ + G:DWORD, \ + R:DWORD, \ + Index:WORD = ARG_SIZE + .enter 0 + .push ds, si + + mov ax, [Index] + mov dx, 3C7h ; PEL read address register + out dx, al + inc dx + inc dx + + lds si, [R] + in al, dx + mov ds:[si], al + lds si, [G] + in al, dx + mov ds:[si], al + lds si, [B] + in al, dx + mov ds:[si], al + + .pop ds, si + .leave ARG_SIZE +mxGetColor ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxgi.asm b/16/x/mxgi.asm new file mode 100755 index 00000000..7037d411 --- /dev/null +++ b/16/x/mxgi.asm @@ -0,0 +1,132 @@ +;----------------------------------------------------------- +; +; MXGI.ASM - Get image +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxGetImage + +EXTRN subClipImage : NEAR + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_VideoSegment : WORD +EXTRN mx_BytesPerLine : WORD + +;----------------------------------------------------------- +; +; Copies an image from screen to memory. +; +; Input: +; Image = pointer to buffer for image +; X, Y = coordinates of image on screen +; Width = width of image in pixels +; Height = height of image in pixels +; Output: +; none +; +mxGetImage PROC FAR + ARG Height:WORD, \ + Width:WORD, \ + Y:WORD, \ + X:WORD, \ + Image:DWORD = ARG_SIZE + LOCAL PlaneWidth:WORD:4, \ + PixelOffset:WORD, \ + MoveFunction:WORD, \ + ReadPlane:BYTE, \ + Count:BYTE = AUTO_SIZE + ASSUME ds:NOTHING + .enter AUTO_SIZE + .push ds, si, es, di + +; Clip image + mov bx, [X] + mov ax, [Y] + mov cx, [Width] + mov dx, [Height] + call subClipImage + jc @@Exit ; Full clipped + mov [Height], dx + add WORD PTR Image[0], si ; Skip clipped pixels + +; Get pixel address + mul [mx_BytesPerLine] + mov si, bx + shr si, 1 + shr si, 1 + add si, ax + mov [PixelOffset], si + mov ds, [mx_VideoSegment] ; DS:SI points to pixel + and bl, 03h + mov [ReadPlane], bl + +; Compute extra bytes and width count for each plane + mov bx, cx + shr bx, 1 + shr bx, 1 ; Width for each plane + and cl, 03h + mov al, 00001000b + shr al, cl + mov di, 3 SHL 1 +@@PatchLoop: + mov PlaneWidth[di], bx + shr al, 1 + adc bx, 0 + dec di + dec di + jge @@PatchLoop + +; Get image + cld + mov [Count], 4 ; Four planes + lea bx, PlaneWidth ; SS:[BX] = width in bytes for plane + mov es, WORD PTR Image[2] ; ES:DI will point to image + mov ah, [ReadPlane] +@@PlaneLoop: + cmp WORD PTR ss:[bx], 0 ; Exit if nothing more to do + je @@Exit ; (also, never try to move zero bytes!) + mov di, WORD PTR Image[0] + mov al, 04h + mov dx, GDC + out dx, ax ; Select read plane + mov dx, [Height] + mov si, [PixelOffset] ; DS:SI points to video memory +@@Loop: + .push si, di + mov cx, WORD PTR ss:[bx] ; Number of bytes to move +@@MoveLoop: + movsb + add di, 3 + dec cx + jnz @@MoveLoop + .pop si, di + add di, [Width] ; Go to next image line + add si, [mx_BytesPerLine] ; Go to next screen row + dec dx + jnz @@Loop ; Repeat for all lines + inc bx + inc bx ; Select width for next plane + inc ah + test ah, 04h ; Plane wraparound? + jz @@PlaneOk ; No + inc [PixelOffset] ; Yes, bump video pointer + and ah, 03h +@@PlaneOk: + inc WORD PTR Image[0] + dec [Count] + jnz @@PlaneLoop ; Repeat for all planes + +@@Exit: + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxGetImage ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxgm.asm b/16/x/mxgm.asm new file mode 100755 index 00000000..a67476a0 --- /dev/null +++ b/16/x/mxgm.asm @@ -0,0 +1,63 @@ +;----------------------------------------------------------- +; +; MXGM.ASM - Gamma correction +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxGammaCorrect + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +mx_tblGamma LABEL BYTE + DB 00, 10, 14, 17, 19, 21, 23, 24, 26, 27, 28, 29, 31, 32, 33, 34 + DB 35, 36, 37, 37, 38, 39, 40, 41, 41, 42, 43, 44, 44, 45, 46, 46 + DB 47, 48, 48, 49, 49, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55 + DB 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63 + +;----------------------------------------------------------- +; +; Correct palette colors (gamma is 2.3). +; +; Input: +; CPal = pointer to color palette +; GPal = pointer to destination (gamma corrected) palette +; Count = number of colors to convert +; Output: +; none +; +; Note: CPal and GPal may point to the same buffer. +; +mxGammaCorrect PROC FAR + ARG Count:WORD, \ + DPal:DWORD, \ + SPal:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si, es, di + + mov cx, [Count] + jcxz @@Exit ; Exit now if nothing to do + lds si, [SPal] + les di, [DPal] + mov bx, OFFSET mx_tblGamma ; Setup BX for XLAT instruction + cld + mov ax, cx ; AX = Count + add cx, cx ; CX = Count*2 + add cx, ax ; CX = Count*3 +@@Loop: + lodsb + xlat mx_tblGamma + stosb + loop @@Loop + +@@Exit: + .pop ds, si, es, di + .leave ARG_SIZE +mxGammaCorrect ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxgp.asm b/16/x/mxgp.asm new file mode 100755 index 00000000..6c143173 --- /dev/null +++ b/16/x/mxgp.asm @@ -0,0 +1,56 @@ +;----------------------------------------------------------- +; +; MXGP.ASM - Get palette function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxGetPalette + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Returns the current setting of the VGA palette. +; +; Input: +; Buffer = pointer to palette data (R,G,B) +; Start = index of first color to get +; Count = number of color to get +; Output: +; none +; +mxGetPalette PROC FAR + ARG Count:WORD, \ + Start:WORD, \ + Buffer:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push es, di + + les di, [Buffer] + mov cx, [Count] + mov ax, [Start] + mov dx, 3C7h ; PEL read address register + out dx, al + inc dx + inc dx + cld +@@Loop: + in al, dx + stosb + in al, dx + stosb + in al, dx + stosb + loop @@Loop ; Loop until done + + .pop es, di + .leave ARG_SIZE +mxGetPalette ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxgv.asm b/16/x/mxgv.asm new file mode 100755 index 00000000..2a54b1d0 --- /dev/null +++ b/16/x/mxgv.asm @@ -0,0 +1,25 @@ +;----------------------------------------------------------- +; +; MXGV.ASM - Get version function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxGetVersion + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Returns the library version. +; +mxGetVersion PROC FAR + mov ax, MXVERSION + ret +mxGetVersion ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxhl.asm b/16/x/mxhl.asm new file mode 100755 index 00000000..049a0566 --- /dev/null +++ b/16/x/mxhl.asm @@ -0,0 +1,76 @@ +;----------------------------------------------------------- +; +; MXHL.ASM - Horizontal line mask utility +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC subHorizontalLineInfo + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD + +tblLeftSize DW 00h, 03h, 02h, 01h +tblLeftMask DB 00h, 0Eh, 0Ch, 08h +tblRightMask DB 00h, 01h, 03h, 07h +tblPatchMask DB 02h, 06h + +;----------------------------------------------------------- +; +; Prepares register for fast horizontal line drawing. +; +; Input: +; BX, AX = X, Y address of left pixel +; CX = line width +; Output: +; DI = left pixel offset in video memory +; AL = left block write plane mask (0 = none) +; AH = right block write plane mask (0 = none) +; CX = center block width in 4-pixel blocks +; +subHorizontalLineInfo PROC NEAR + ASSUME ds:NOTHING + + mul [mx_BytesPerLine] + mov di, bx + shr di, 1 + shr di, 1 + add di, ax ; Offset of left pixel + + and bx, 03h + mov al, tblLeftMask[bx] + shl bx, 1 + sub cx, tblLeftSize[bx] + jge @@1 ; Ok to continue + +; Special case: start and end in the middle of a 4-pixel block. +; There are only three cases: +; Pixels Left mask CX CX+2 Patch mask Result +; 1) ..o. ..xx -1 1 .xx. ..x. +; 2) .oo. .xxx -1 1 .xx. .xx. +; 3) .o.. .xxx -2 0 .x.. .x.. +; All other cases are automatically handled with the standard masks. + mov bx, cx + inc bx + inc bx + and al, tblPatchMask[bx] ; Combine masks + xor ah, ah ; No right block + xor cx, cx ; No center block + jmp @@Exit + +@@1: + mov bx, cx + and bx, 03h + mov ah, tblRightMask[bx] + shr cx, 2 + +@@Exit: + ret +subHorizontalLineInfo ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxit.asm b/16/x/mxit.asm new file mode 100755 index 00000000..c0d9cedd --- /dev/null +++ b/16/x/mxit.asm @@ -0,0 +1,98 @@ +;----------------------------------------------------------- +; +; MXIT.ASM - Initialization/termination functions +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxInit +PUBLIC mxTerm + +PUBLIC mx_VideoSegment +PUBLIC mx_CodeSegment + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +DB 'MODEX library - Copyright (c) 1992-1994 Alessandro Scotti' + +mx_VideoSegment DW 0A000h +mx_CodeSegment DW SEG MX_TEXT + +;----------------------------------------------------------- +; +; Initialization. +; +; Input: +; none +; Output: +; AX = 0 on success +; +mxInit PROC FAR + LOCAL Result:WORD, \ + VideoSeg:WORD, \ + CStoDSalias:WORD = AUTO_SIZE + ASSUME ds:NOTHING + .enter AUTO_SIZE + .push ds, si, es, di + + mov [Result], -1 ; Assume an error + mov [VideoSeg], 0A000h ; Real mode video segment + mov [CStoDSalias], cs ; Real mode data alias for CS + +; Check if running in protected mode under DPMI + mov ax, 1686h + int 2Fh + or ax, ax + jnz @@1 ; DPMI not found, continue in real mode + +; Get a data alias for CS + mov ax, 000Ah ; DMPI: create data alias + mov bx, cs + int 31h + jc @@Exit ; Exit if service failed + mov [CStoDSalias], ax ; Save data alias for CS +; Get a protected-mode selector for the video segment + mov ax, 0002h + mov bx, 0A000h ; Real mode segment of video + int 31h ; DPMI: get segment selector + jc @@Exit ; Exit if service failed + mov [VideoSeg], ax ; Save protected mode video selector + +; Initialize variables +@@1: + mov ds, [CStoDSalias] + ASSUME ds:MX_TEXT + mov [mx_CodeSegment], ds + mov ax, [VideoSeg] + mov [mx_VideoSegment], ax + +; Don't bother with VGA check for now... + + mov [Result], 0 + +@@Exit: + mov ax, [Result] + .pop ds, si, es, di + .leave +mxInit ENDP + +;----------------------------------------------------------- +; +; Termination. +; +; Input: +; none +; Output: +; always 0. +; +mxTerm PROC FAR + ASSUME ds:NOTHING + xor ax, ax + ret +mxTerm ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxll.asm b/16/x/mxll.asm new file mode 100755 index 00000000..34fec043 --- /dev/null +++ b/16/x/mxll.asm @@ -0,0 +1,82 @@ +;----------------------------------------------------------- +; +; MXLL.ASM - Load latches +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxLoadLatches + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_VideoSegment : WORD + +;----------------------------------------------------------- +; +; Loads the specified value into the VGA latches. +; +; Input: +; BL = value to load into latches +; Output: +; none +; Changes: +; bit mask register to FFh; +; function select register to "move"; +; write mode to 00h. +; Note: +; this is for internal use only. +; +mxLoadLatches PROC NEAR + ASSUME ds:NOTHING + + .push ds, si + mov dx, GDC + mov ax, 0FF08h + out dx, ax ; Set bit mask to FFh + mov ax, 0003h + out dx, ax ; Set function to "move" + mov ax, 0005h + out dx, ax ; Set write mode + mov ax, [mx_VideoSegment] + mov ds, ax + mov si, 0FFFFh + mov bh, 8 ; BH = write plane mask + mov cx, 3 ; CX = count = read plane +; Saves old values and force BL into latches +@@SetLoop: + mov dx, GDC + mov al, 04h + mov ah, cl + out dx, ax ; Select read plane + mov dx, TS + mov al, 02h + mov ah, bh + out dx, ax ; Select write plane + mov al, ds:[si] + push ax + mov ds:[si], bl + mov al, ds:[di] ; Force value into latch + shr bh, 1 ; Next write plane + loop @@SetLoop +; Restore previous values + mov cx, 3 + mov bh, 8 + mov dx, TS +@@ResetLoop: + mov al, 02h + mov ah, bh + out dx, ax ; Select write plane + pop ax + mov ds:[si], al + shr bh, 1 ; Next write plane + loop @@ResetLoop +; Exit + .pop ds, si + ret +mxLoadLatches ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxln.asm b/16/x/mxln.asm new file mode 100755 index 00000000..fbc4ab94 --- /dev/null +++ b/16/x/mxln.asm @@ -0,0 +1,414 @@ +;----------------------------------------------------------- +; +; MXLN.ASM - Line function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxLine + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD +EXTRN mx_VideoSegment : WORD + +EXTRN mx_ClipX1 : WORD +EXTRN mx_ClipY1 : WORD +EXTRN mx_ClipX2 : WORD +EXTRN mx_ClipY2 : WORD + +tblDrawFunc LABEL WORD + DW subWidthMove + DW subHeightMove + DW subWidthOp + DW subHeightOp + +;----------------------------------------------------------- +; +; Draws a line from (X1,Y1) to (X2,Y2) using the Bresenham +; algorithm. +; +; Input: +; X1, Y1 = start point +; X2, Y2 = end point +; Color = line color +; Op = raster operator +; Output: +; none +; +; Note: the end point (X2,Y2) *IS* drawed. I don't like this very much +; but clipping is much simpler. +; +mxLine PROC FAR + ARG Op:WORD, \ + Color:WORD, \ + Y2:WORD, \ + X2:WORD, \ + Y1:WORD, \ + X1:WORD = ARG_SIZE + LOCAL Width:WORD, \ + Height:WORD, \ + ErrorAdd:WORD, \ + ErrorSub:WORD, \ + DeltaX:WORD, \ + DeltaY:WORD, \ + P1:BYTE, \ + P2:BYTE, \ + WritePlane:BYTE = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, di + ASSUME ds:NOTHING + + mov ax, [X1] + mov bx, [Y1] + mov cx, [X2] + mov dx, [Y2] + call subClipLine + jc @@Exit ; Line is full clipped + +; Get width + mov si, cx + xchg ax, si ; SI = X1, AX = X2 + sub ax, si + jge @@1 +; Swap points, we want X1 < X2 + xchg si, cx ; Swap X1 and X2 + xchg bx, dx ; Swap Y1 and Y2 + neg ax +@@1: + mov [Width], ax + +; Get height + mov cx, [mx_BytesPerLine] ; We don't need X2 anymore + mov ax, dx + sub ax, bx + jge @@2 + neg cx ; Move from bottom to top + neg ax ; Get absolute value of AX +@@2: + mov [Height], ax + mov [DeltaY], cx + +; Get pixel address and write plane + mov ax, bx + mul [mx_BytesPerLine] + mov cx, si ; CX = X1 + shr si, 1 + shr si, 1 + add si, ax ; SI = pixel offset + and cl, 03h + mov ax, 1102h + shl ah, cl + mov [WritePlane], ah + mov dx, TS + out dx, ax ; Set write plane + mov ax, [mx_VideoSegment] + mov ds, ax ; DS:SI points to (X1,Y1) + +; Select the function to handle the drawing loop + xor bx, bx + mov al, BYTE PTR [Op] + cmp al, OP_MOVE + je @@3 + and al, 03h + shl al, 1 + shl al, 1 + shl al, 1 + mov ah, al + mov al, 03h + mov dx, GDC + out dx, ax ; Set logical function + inc bx + inc bx +@@3: + mov ax, [Width] + mov cx, [Height] +; Horizontal, vertical and diagonal lines are not optimized yet + cmp ax, cx + jae @@4 + inc bx +@@4: + shl bx, 1 + call tblDrawFunc[bx] + +; Reset logical function if needed + cmp BYTE PTR [Op], OP_MOVE + je @@Exit + mov ax, 0003h + mov dx, GDC + out dx, ax + +@@Exit: + xor ax, ax + .pop ds, si, di + .leave ARG_SIZE + +;----------------------------------------------------------- +; +; Checks the coordinates of a line against the active +; clip region. +; Uses a variation of the Cohen-Sutherland algorithm developed +; by Victor Duvanenko. +; +; Input: +; AX, BX = X1, Y1 +; CX, DX = X2, Y2 +; Output: +; CF = set if line is full clipped +; AX, BX = clipped X1, Y1 +; CX, DX = clipped X2, Y2 +; Note: +; destroys SI, DI +; +subClipLine PROC NEAR + mov di, ax ; Copy X1 to DI and free AX + mov si, dx ; Copy Y2 to SI and free DX +; Compute clip codes for point (X2,Y2)=(CX,SI) + xor al, al +@@P2X1: cmp cx, [mx_ClipX1] + jge @@P2X2 + or al, 1 +@@P2X2: cmp cx, [mx_ClipX2] + jle @@P2Y1 + or al, 2 +@@P2Y1: cmp si, [mx_ClipY1] + jge @@P2Y2 + or al, 4 +@@P2Y2: cmp si, [mx_ClipY2] + jle @@P2XY + or al, 8 +@@P2XY: mov [P2], al +; Compute clip codes for point (X1,Y1)=(DI,BX) + xor al, al +@@P1X1: cmp di, [mx_ClipX1] + jge @@P1X2 + or al, 1 +@@P1X2: cmp di, [mx_ClipX2] + jle @@P1Y1 + or al, 2 +@@P1Y1: cmp bx, [mx_ClipY1] + jge @@P1Y2 + or al, 4 +@@P1Y2: cmp bx, [mx_ClipY2] + jle @@P1XY + or al, 8 +@@P1XY: mov [P1], al +; Check codes for trivial cases + mov ah, [P2] + test al, ah ; Is line invisible? + jnz @@FullClip ; Yes, exit + or ah, al ; Both points clipped? + jz @@Done ; Yes, exit +; Calculate deltas + mov ax, cx + sub ax, di + mov [DeltaX], ax + mov ax, si + sub ax, bx + mov [DeltaY], ax + mov al, [P1] ; Init clipping code +; Clipping loop +@@ClipLoop: + test al, al ; Is first point clipped? + jnz @@ClipX1 ; No, continue + xchg cx, di ; Swap points... + xchg bx, si + xchg al, [P2] ; ...and codes +; Clip left: Y1 = Y1 + DeltaY*(mx_ClipX1-X1)/DeltaX +@@ClipX1: + test al, 1 + jz @@ClipX2 + mov ax, [mx_ClipX1] + sub ax, di + mov di, [mx_ClipX1] + jmp @@ClipX1X2 +; Clip right: Y1 = Y1 + DeltaY*(mx_ClipX2-X1)/DeltaX +@@ClipX2: + test al, 2 + jz @@ClipY1 + mov ax, [mx_ClipX2] + sub ax, di + mov di, [mx_ClipX2] +@@ClipX1X2: + imul [DeltaY] + idiv [DeltaX] + add bx, ax + mov al, 8 + cmp bx, [mx_ClipY2] + jg @@CheckLoop + mov al, 4 + cmp bx, [mx_ClipY1] + jl @@CheckLoop + xor al, al + jmp @@CheckLoop +; Clip top: X1 = X1 + DeltaX*(mx_ClipY1-Y1)/DeltaY +@@ClipY1: + test al, 4 + jz @@ClipY2 + mov ax, [mx_ClipY1] + sub ax, bx + mov bx, [mx_ClipY1] + jmp @@ClipY1Y2 +; Clip bottom: X1 = X1 + DeltaX*(mx_ClipY2-Y1)/DeltaY +@@ClipY2: + mov ax, [mx_ClipY2] + sub ax, bx + mov bx, [mx_ClipY2] +@@ClipY1Y2: + imul [DeltaX] + idiv [DeltaY] + add di, ax + mov al, 1 + cmp di, [mx_ClipX1] + jl @@CheckLoop + mov al, 2 + cmp di, [mx_ClipX2] + jg @@CheckLoop + xor al, al +@@CheckLoop: + mov ah, [P2] + test al, ah + jnz @@FullClip + or ah, al + jnz @@ClipLoop + +@@Done: + mov ax, di + mov dx, si + clc + ret +@@FullClip: + stc + ret +subClipLine ENDP + +; Called when Width >= Height and Op = OP_MOVE +subWidthMove PROC NEAR + mov di, ax + neg di ; Initialize error term + shl cx, 1 + mov [ErrorAdd], cx + mov cx, ax + shl ax, 1 + mov [ErrorSub], ax + mov al, 02h + mov ah, [WritePlane] + mov bl, BYTE PTR [Color] + mov dx, TS + inc cx +@@Loop: + mov ds:[si], bl + dec cx + jz @@Exit + rol ah, 1 + adc si, 0 + out dx, ax + add di, [ErrorAdd] + jl @@Loop + add si, [DeltaY] + sub di, [ErrorSub] + jmp @@Loop +@@Exit: + ret +subWidthMove ENDP + +; Called when Width < Height and Op = OP_MOVE +subHeightMove PROC NEAR + mov di, cx + neg di ; Initialize error term + shl ax, 1 + mov [ErrorAdd], ax + mov ax, cx + shl ax, 1 + mov [ErrorSub], ax + mov bl, BYTE PTR [Color] + mov ah, [WritePlane] + mov al, 02h + mov dx, TS + inc cx +@@Loop: + mov ds:[si], bl + dec cx + jz @@Exit + add si, [DeltaY] + add di, [ErrorAdd] + jl @@Loop + rol ah, 1 ; Next write plane + adc si, 0 ; Bump video offset if plane overflows + out dx, ax + sub di, [ErrorSub] ; Adjust error down + jmp @@Loop +@@Exit: + ret +subHeightMove ENDP + +; Called when Width >= Height and Op <> OP_MOVE +subWidthOp PROC NEAR + mov di, ax + neg di ; Initialize error term + shl cx, 1 + mov [ErrorAdd], cx + mov cx, ax + shl ax, 1 + mov [ErrorSub], ax + mov al, 02h + mov ah, [WritePlane] + mov bl, BYTE PTR [Color] + mov dx, TS + inc cx +@@Loop: + mov bh, ds:[si] ; Latch data + mov ds:[si], bl + dec cx + jz @@Exit + rol ah, 1 + adc si, 0 + out dx, ax + add di, [ErrorAdd] + jl @@Loop + add si, [DeltaY] + sub di, [ErrorSub] + jmp @@Loop +@@Exit: + ret +subWidthOp ENDP + +; Called when Width < Height and Op <> OP_MOVE +subHeightOp PROC NEAR + mov di, cx + neg di ; Initialize error term + shl ax, 1 + mov [ErrorAdd], ax + mov ax, cx + shl ax, 1 + mov [ErrorSub], ax + mov bl, BYTE PTR [Color] + mov ah, [WritePlane] + mov al, 02h + mov dx, TS + inc cx +@@Loop: + mov bh, ds:[si] + mov ds:[si], bl + dec cx + jz @@Exit + add si, [DeltaY] + add di, [ErrorAdd] + jl @@Loop + rol ah, 1 ; Next write plane + adc si, 0 ; Bump video offset if plane overflows + out dx, ax + sub di, [ErrorSub] ; Adjust error down + jmp @@Loop +@@Exit: + ret +subHeightOp ENDP + +mxLine ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxot.asm b/16/x/mxot.asm new file mode 100755 index 00000000..62547665 --- /dev/null +++ b/16/x/mxot.asm @@ -0,0 +1,330 @@ +;----------------------------------------------------------- +; +; MXOT.ASM - Text functions +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES ; We use the reserved name 'WIDTH' +INCLUDE MODEX.DEF + +PUBLIC mxOutChar +PUBLIC mxOutText +PUBLIC mxSetFont +PUBLIC mxSetTextColor +PUBLIC mxGetTextStep +PUBLIC mxSetTextStep + +MAX_WIDTH EQU 16 ; Must be <= 16 +MAX_HEIGHT EQU 32 + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_CodeSegment : WORD +EXTRN mxPutImage : FAR + +; Default 8x8 font +fnt_Default LABEL + 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 OP_MOVE ; Raster op +mx_DeltaX DW 8 ; Horizontal step +mx_DeltaY DW 0 ; Vertical step + +;----------------------------------------------------------- +; +; Sets the current font. +; +; Input: +; Font = pointer to font data +; Width = width of font character in pixels +; Height = height of font character in pixels +; Output: +; AX = 0 on success, else invalid parameters +; +; Note: when the high word of Font (i.e. the segment) is zero, the low +; word is used to select one of the system fonts. +; +mxSetFont PROC FAR + ARG Height:WORD, \ + Width:WORD, \ + Font:DWORD = ARG_SIZE + .enter 0 + .push ds + + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, WORD PTR Font[2] ; Get font segment + test ax, ax ; Null segment? + jnz @@UserFont ; No, install user font + +; Install system font + mov ax, WORD PTR Font[0] ; Get font number + cmp ax, MX_MAXSYSFONT ; Check range + jb @@SystemFont + xor ax, ax ; Out of range, use default font +@@SystemFont: + shl ax, 1 + shl ax, 1 + mov bx, ax + mov ax, tbl_SystemFont[bx] ; Get font offset + mov WORD PTR mx_FontPtr[0], ax + mov WORD PTR mx_FontPtr[2], cs + mov al, BYTE PTR tbl_SystemFont[bx+2] + xor ah, ah + mov [mx_FontWidth], ax + mov [mx_DeltaX], ax + mov dl, BYTE PTR tbl_SystemFont[bx+3] + xor dh, dh + mov [mx_FontHeight], dx + mul dx + mov [mx_FontCharSize], ax + mov [mx_DeltaX], ax + xor ax, ax + mov [mx_DeltaY], ax + jmp @@Exit + +; Install user font +@@UserFont: + mov ax, -1 ; Assume an error + mov bx, [Width] + cmp bx, MAX_WIDTH + ja @@Exit ; Invalid character width + mov dx, [Height] + cmp dx, MAX_HEIGHT + ja @@Exit ; Invalid character height + mov [mx_FontWidth], bx + mov [mx_FontHeight], dx + mov ax, bx + add ax, 7 + .shr ax, 3 + mul dx + mov [mx_FontCharSize], ax + mov ax, WORD PTR Font[0] + mov WORD PTR mx_FontPtr[0], ax + mov ax, WORD PTR Font[2] + mov WORD PTR mx_FontPtr[2], ax + xor ax, ax + +@@Exit: + .pop ds + ASSUME ds:NOTHING + .leave ARG_SIZE +mxSetFont ENDP + +;----------------------------------------------------------- +; +; Sets the text color and raster op. +; +; Input: +; Color = text color (foreground + background*256) +; Op = raster op +; Output: +; none +; +mxSetTextColor PROC FAR + ARG Op:WORD, \ + Color:WORD = ARG_SIZE + .enter 0 + .push ds + + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, [Color] + mov [mx_FontColor], ax + mov ax, [Op] + mov [mx_FontOp], ax + + xor ax, ax + .pop ds + ASSUME ds:NOTHING + .leave ARG_SIZE +mxSetTextColor ENDP + +;----------------------------------------------------------- +; +; Writes a character using the current font and attributes. +; +; Input: +; X, Y = video coordinates +; C = character to print +; Output: +; none +; +mxOutChar PROC FAR + ARG C:BYTE:2, \ + Y:WORD, \ + X:WORD = ARG_SIZE + LOCAL Image:BYTE:MAX_WIDTH*MAX_HEIGHT, \ + Count:WORD = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, es, di + ASSUME ds:NOTHING + +; Gets the pointer to font data for the selected character + lds si, DWORD PTR [mx_FontPtr] + mov al, [C] + xor ah, ah + mul [mx_FontCharSize] ; Offset into font + add si, ax ; DS:SI -> font data for character + +; Converts font data into a 256-color linear image + mov ax, ss + mov es, ax + lea di, [Image] + mov dx, [mx_FontColor] + mov ax, [mx_FontHeight] + mov [Count], ax +@@HeightLoop: + mov cx, [mx_FontWidth] + mov bh, ds:[si] + inc si ; Get a byte from font data + cmp cx, 8 + jbe @@WidthLoop ; Ok for width <= 8 + mov bl, ds:[si] ; Get another byte + inc si +@@WidthLoop: + mov al, dl ; Assume foreground color + shl bx, 1 ; Is font bit set? + jc @@1 ; Yes, foreground is just great + mov al, dh ; Get background color +@@1: + mov es:[di], al ; Put pixel into image + inc di + dec cx + jnz @@WidthLoop + dec [Count] + jnz @@HeightLoop + +; Now pass image to mx_PutImage + lea ax, [Image] + push es + push ax ; Pointer to image + push [X] + push [Y] ; Image coordinates + push [mx_FontWidth] + push [mx_FontHeight] ; Image size + push [mx_FontOp] ; Raster op + call mxPutImage ; Write character + + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxOutChar ENDP + +;----------------------------------------------------------- +; +; Writes a string at the coordinates specified. +; +; Input: +; X, Y = text coordinates +; S = pointer to ASCIIZ string +; Output: +; none +; +mxOutText PROC FAR + ARG S:DWORD, \ + Y:WORD, \ + X:WORD = ARG_SIZE + .enter 0 + .push ds, si + ASSUME ds:NOTHING + + lds si, [S] +@@Loop: + mov al, ds:[si] + test al, al ; End of string? + jz @@Exit ; Yes, exit + inc si + push [X] ; Display character + push [Y] + push ax + call mxOutChar + mov ax, [mx_DeltaX] + add [X], ax ; Bump X coordinate + mov ax, [mx_DeltaY] + add [Y], ax ; Bump Y coordinate + dec [Count] + jnz @@Loop + +@@Exit: + xor ax, ax + .pop ds, si + .leave ARG_SIZE + ret +mxOutText ENDP + +;----------------------------------------------------------- +; +; Sets the distance between characters. +; +; Input: +; DeltaX = horizontal distance in pixels +; DeltaY = vertical distance in pixels +; Output: +; none +; +; Note: this function may be used to set the text direction. +; +mxSetTextStep PROC FAR + ARG DeltaY:WORD, \ + DeltaX:WORD = ARG_SIZE + .enter 0 + .push ds + + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, [DeltaX] + mov [mx_DeltaX], ax + mov ax, [DeltaY] + mov [mx_DeltaY], ax + + .pop ds + .leave ARG_SIZE +mxSetTextStep ENDP + +;----------------------------------------------------------- +; +; Gets the current distance between characters. +; +; Input: +; DeltaX = pointer to horizontal distance in pixels (integer) +; DeltaY = pointer to vertical distance in pixels (integer) +; Output: +; none +; +mxGetTextStep PROC FAR + ARG DeltaY:DWORD, \ + DeltaX:DWORD = ARG_SIZE + .enter 0 + .push ds, si + ASSUME ds:NOTHING + + mov ax, [mx_DeltaX] + lds si, [DeltaX] + mov ds:[si], ax + mov ax, [mx_DeltaY] + lds si, [DeltaY] + mov ds:[si], ax + + .pop ds, si + .leave ARG_SIZE +mxGetTextStep ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxpb.asm b/16/x/mxpb.asm new file mode 100755 index 00000000..8c6aa449 --- /dev/null +++ b/16/x/mxpb.asm @@ -0,0 +1,22 @@ +;----------------------------------------------------------- +; +; MXPB.ASM - Scan buffer for convex polygon fills +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mx_ScanBuffer + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +ALIGN 4 + +mx_ScanBuffer LABEL + DW POLYSCANBUFSIZE DUP(?) + +MX_TEXT ENDS +END diff --git a/16/x/mxpf.asm b/16/x/mxpf.asm new file mode 100755 index 00000000..db0da898 --- /dev/null +++ b/16/x/mxpf.asm @@ -0,0 +1,420 @@ +;----------------------------------------------------------- +; +; MXPG.ASM - Convex polygon fill +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxFillPoly + +;----------------------------------------------------------- +; +; "Local" definitions +; +TPOINT STRUC + X DW ? + Y DW ? +TPOINT ENDS + +; Do NOT change order! +TSCAN STRUC + Y1 DW ? + Y2 DW ? +TSCAN ENDS + +MAXSCANCOLUMNS EQU POLYSCANBUFSIZE / SIZE TSCAN + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_VideoSegment : WORD +EXTRN mx_CodeSegment : WORD +EXTRN mx_BytesPerLine : WORD +EXTRN mx_ClipX1 : WORD +EXTRN mx_ClipY1 : WORD +EXTRN mx_ClipX2 : WORD +EXTRN mx_ClipY2 : WORD +EXTRN mx_ScanBuffer : NEAR + +;----------------------------------------------------------- +; +; Scans an edge using the DDA (digital differential analyzer) algorithm. +; +; Input: +; DS:BX = pointer to start point (X1, Y1) +; DS:SI = pointer to end point (X2, Y2) +; ES:DI = pointer to edge buffer +; Output: +; ES:DI = updated pointer to edge buffer +; Notes: +; must preserve DS:SI. +; +subScan PROC NEAR + mov cx, ds:[si].X + sub cx, ds:[bx].X ; Get width + jg @@1 + ret +@@1: + push bp ; Save BP + + mov ax, ds:[si].Y + mov bx, ds:[bx].Y + sub ax, bx ; Get height + jg @@T2B ; Scan top to bottom + jl @@B2T ; Scan bottom to top + +; Special case: vertical line + mov ax, bx +@@V: + mov es:[di].Y1, ax + add di, SIZE TSCAN + dec cx + jnz @@V + jmp @@Exit + +; Scan top to bottom +@@T2B: + cwd + div cx + mov bp, ax + xor ax, ax + div cx + xchg ax, bx ; BP:BX = fixed 16:16 step + mov dx, 8000h +@@T2BLoop: + mov es:[di].Y1, ax + add di, SIZE TSCAN + add dx, bx + adc ax, bp + dec cx + jnz @@T2BLoop + jmp @@Exit + +; Scan bottom to top +@@B2T: + neg ax + cwd + div cx + mov bp, ax + xor ax, ax + div cx + xchg ax, bx + mov dx, 8000h +@@B2TLoop: + mov es:[di].Y1, ax + add di, SIZE TSCAN + sub dx, bx + sbb ax, bp + dec cx + jnz @@B2TLoop + +@@Exit: + pop bp ; Restore BP + ret +subScan ENDP + +;----------------------------------------------------------- +; +; Fills a convex polygon with the specified color. +; +; Input: +; Count = number of vertexes +; Map = indexes of points and colors (integer) +; Points = array of points (integer X, Y coordinates) +; Color = base color +; Output: +; none +; Notes: +; vertexes must be in counterclockwise order, arrays are 0-based. +; +mxFillPoly PROC FAR + ARG Color:WORD, \ + Points:DWORD, \ + Map:DWORD, \ + Count:WORD = ARG_SIZE + LOCAL WritePlane:BYTE:2, \ + ScanOffsetT:WORD, \ + ScanOffsetB:WORD, \ + ScanCount:WORD, \ + Holder:WORD, \ + Height:WORD, \ + MinIdxT:WORD, \ + MinIdxB:WORD, \ + MaxIdx:WORD, \ + Width:WORD, \ + BoxX1:WORD, \ + BoxY1:WORD, \ + BoxX2:WORD, \ + BoxY2::WORD = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, es, di + ASSUME ds:NOTHING + +; Check that at least three vertexes are specified + mov cx, [Count] + cmp cx, 3 + jb @@Exit + +;------------------------------ +; Find bounding box for polygon + les di, [Map] + lds si, [Points] ; Pointer to vertex array + mov [BoxX1], 32767 + mov [BoxX2], -32768 + mov [BoxY1], 32767 + mov [BoxY2], -32768 + + xor dx, dx +@@MinMaxLoop: + mov bx, es:[di] ; Get index of vertex + .shl bx, 2 ; Get offset in point array + add bx, si + +; Check X range +@@CheckMinX: + mov ax, ds:[bx].X ; Get X coordinate + cmp ax, [BoxX1] + jge @@CheckMaxX + mov [BoxX1], ax + mov [MinIdxT], dx + mov [MinIdxB], dx +@@CheckMaxX: + cmp ax, [BoxX2] + jle @@CheckMinY + mov [BoxX2], ax + mov [MaxIdx], dx + +; Check Y range +@@CheckMinY: + mov ax, ds:[bx].Y + cmp ax, [BoxY1] + jge @@CheckMaxY + mov [BoxY1], ax +@@CheckMaxY: + cmp ax, [BoxY2] + jle @@CheckDone + mov [BoxY2], ax + +; Repeat thru all points +@@CheckDone: + inc di ; Next map entry + inc dx + inc di + inc dx + dec cx + jnz @@MinMaxLoop + +;--------------------------------- +; Check if polygon is full clipped + mov ax, [BoxX2] + cmp ax, [mx_ClipX1] ; Is poly full clipped? + jl @@Exit + mov bx, [BoxX1] + cmp bx, [mx_ClipX2] ; Is poly full clipped? + jg @@Exit + sub ax, bx ; Get width + jle @@Exit ; Exit if not positive + mov ax, [BoxY2] + cmp ax, [mx_ClipY1] ; Is poly full clipped? + jl @@Exit + mov bx, [BoxY1] + cmp bx, [mx_ClipY2] ; Is poly full clipped? + jg @@Exit + sub ax, bx ; Get height + jle @@Exit ; Exit if not positive + + dec [Count] + shl [Count], 1 ; We'll work with word offsets + mov es, [mx_CodeSegment] + +;-------------- +; Scan top edge + mov ax, OFFSET mx_ScanBuffer + mov [ScanOffsetT], ax + mov si, [MinIdxT] ; Offset of bottom point index +@@STLoop: + lds bx, [Map] ; DS:BX -> map table + mov di, ds:[bx+si] ; Index of top point #1 + dec si ; Next point + dec si + test si, si + jnl @@ST1 + mov si, [Count] +@@ST1: + mov [MinIdxT], si ; Save new index of top point + mov si, ds:[bx+si] ; Get index of top point #2 + .shl di, 2 ; Convert indexes to offsets + .shl si, 2 + lds bx, [Points] ; DS:BX -> point array + add si, bx ; DS:SI -> top point #2 + add bx, di ; DS:BX -> top point #1 + mov di, [ScanOffsetT] + call subScan ; Scan edge + mov [ScanOffsetT], di + mov si, [MinIdxT] + cmp si, [MaxIdx] ; End of edge? + jne @@STLoop ; No, continue + +;----------------- +; Scan bottom edge + mov ax, OFFSET mx_ScanBuffer + OFFSET Y2 + mov [ScanOffsetB], ax + mov si, [MinIdxB] ; Offset of bottom point index +@@SBLoop: + lds bx, [Map] ; DS:BX -> map table + mov di, ds:[bx+si] ; Index of bottom point #1 + inc si ; Next bottom point + inc si + cmp si, [Count] + jbe @@SB1 + xor si, si +@@SB1: + mov [MinIdxB], si ; Save new index of bottom point + mov si, ds:[bx+si] ; Get index of bottom point #2 + .shl di, 2 ; Convert indexes to offsets + .shl si, 2 + lds bx, [Points] ; DS:BX -> point array + add si, bx ; DS:SI -> top point #2 + add bx, di ; DS:BX -> top point #1 + mov di, [ScanOffsetB] + call subScan ; Scan edge + mov [ScanOffsetB], di + mov si, [MinIdxB] + cmp si, [MaxIdx] ; End of edge? + jne @@SBLoop ; No, continue + +;-------------------- +; Clip left and right + mov si, OFFSET mx_ScanBuffer + mov ax, [BoxX1] + mov cx, [BoxX2] + sub cx, ax ; CX = bounding box width + mov bx, [mx_ClipX1] + sub bx, ax + jle @@ClipL1 ; No need to clip left + sub cx, bx ; Update width + add ax, bx ; BoxX1 = mx_ClipX1 + mov [BoxX1], ax + .shl bx, 2 ; Warning!!! This is an hand-coded + add si, bx ; multiply by the size of TSCAN +@@ClipL1: + mov bx, ax + add bx, cx ; Last scan column + sub bx, [mx_ClipX2] + jle @@ClipL2 ; No need to clip right + sub cx, bx ; Clip right +@@ClipL2: + test cx, cx ; Is clipped width positive? + jle @@Exit ; No, exit + mov [ScanCount], cx ; Save number of columns to draw + mov [ScanOffsetT], si ; Remember offset of (clipped) buffer + mov ds, [mx_CodeSegment] ; DS:SI -> scan buffer + +;------------------------------ +; Check if Y clipping is needed + mov ax, [BoxY1] + cmp ax, [mx_ClipY1] + jl @@ClipTB ; Need to clip top + mov ax, [BoxY2] + cmp ax, [mx_ClipY2] + jg @@ClipTB ; Need to clip bottom + jmp @@ClipYExit ; Skip Y clipping + +;-------------------- +; Clip top and bottom +@@ClipTB: + mov di, cx ; DI = scan count + inc di ; Increment count for pre-loop test + sub si, SIZE TSCAN +@@ClipYLoop: + dec di ; Any column left? + jz @@ClipYExit ; No, exit + add si, SIZE TSCAN + mov ax, ds:[si].Y1 ; Y1 + mov cx, ds:[si].Y2 ; Y2 + mov dx, [mx_ClipY2] + cmp ax, dx ; Full clipped? + jg @@ClipYClip ; Yes, skip this column + cmp cx, dx ; Need to clip bottom? + jle @@ClipY1 ; No, continue +; Clip bottom + mov ds:[si].Y2, dx + mov bx, cx + sub bx, dx ; Clip distance + sub cx, ax ; Height + jle @@ClipYClip + mov cx, ds:[si].Y2 +@@ClipY1: + mov dx, [mx_ClipY1] + cmp cx, dx ; Full top clipped? + jl @@ClipYClip ; Yes, skip + sub cx, ax ; Get height + jle @@ClipYClip ; Skip if not positive + cmp ax, dx ; Need to clip top? + jge @@ClipYLoop ; No, continue +; Clip top + mov ds:[si].Y1, dx ; Y1 = mx_ClipY1 + sub dx, ax ; DX = number of pixels clipped + cmp cx, dx + ja @@ClipYLoop ; Not clipped, continue +@@ClipYClip: + mov ds:[si].Y1, -1 ; Mark column as clipped + jmp @@ClipYLoop +@@ClipYExit: + +;------------- +; Draw columns + mov es, [mx_VideoSegment] + mov si, [ScanOffsetT] + mov cl, BYTE PTR [BoxX1] ; Init write plane + and cl, 03h + mov al, 11h + shl al, cl + mov [WritePlane], al + .shr [BoxX1], 2 +@@DrawLoop: + mov ax, ds:[si].Y1 + test ax, ax ; Was column clipped? + js @@DrawNext ; Yes, skip + mov cx, ds:[si].Y2 + sub cx, ax ; CX = height + jle @@DrawNext + mul [mx_BytesPerLine] ; Get pixel address + add ax, [BoxX1] + mov di, ax + mov ah, [WritePlane] + mov dx, TS + mov al, 02h + out dx, ax + mov ax, [Color] + mov dx, [mx_BytesPerLine] + shr cx, 1 + jnc @@FillScan + mov es:[di], al + add di, dx + jcxz @@DrawNext +@@FillScan: + mov es:[di], al + add di, dx + mov es:[di], al + add di, dx + dec cx + jnz @@FillScan +@@DrawNext: + rol [WritePlane], 1 + adc [BoxX1], 0 ; Bump pointer to video memory if needed + add si, SIZE TSCAN + dec [ScanCount] + jnz @@DrawLoop + +@@Exit: + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxFillPoly ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxpg.asm b/16/x/mxpg.asm new file mode 100755 index 00000000..caa7cf1b --- /dev/null +++ b/16/x/mxpg.asm @@ -0,0 +1,589 @@ +;----------------------------------------------------------- +; +; MXPG.ASM - Convex polygon fill with Gouraud shading +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxGouraudPoly + +;----------------------------------------------------------- +; +; "Local" definitions +; +TPOINT STRUC + X DW ? + Y DW ? +TPOINT ENDS + +; Do NOT change order! +TSCAN STRUC + Y1 DW ? + E1 DB ? + C1 DB ? + Y2 DW ? + E2 DB ? + C2 DB ? +TSCAN ENDS + +MAXSCANCOLUMNS EQU POLYSCANBUFSIZE / SIZE TSCAN + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_VideoSegment : WORD +EXTRN mx_CodeSegment : WORD +EXTRN mx_BytesPerLine : WORD +EXTRN mx_ClipX1 : WORD +EXTRN mx_ClipY1 : WORD +EXTRN mx_ClipX2 : WORD +EXTRN mx_ClipY2 : WORD +EXTRN mx_ScanBuffer : NEAR + +;----------------------------------------------------------- +; +; Scans an edge using the DDA (digital differential analyzer) algorithm. +; Also interpolates color for shading. +; +; Input: +; DS:BX = pointer to start point (X1, Y1) +; DS:SI = pointer to end point (X2, Y2) +; ES:DI = pointer to edge buffer +; DX = start color +; AX = end color +; Output: +; ES:DI = updated pointer to edge buffer +; Notes: +; must preserve DS:SI. +; +subScan PROC NEAR + mov cx, ds:[si].X + sub cx, ds:[bx].X ; Get width + jg @@1 + ret +@@1: + push bp ; Save BP + push di ; Save scan info offset + push cx ; Save height + push ax ; Save colors + push dx + + mov ax, ds:[si].Y + mov bx, ds:[bx].Y + sub ax, bx ; Get height + jg @@T2B ; Scan top to bottom + jl @@B2T ; Scan bottom to top + +; Special case: vertical line + mov ax, bx +@@V: + mov es:[di].Y1, ax + add di, SIZE TSCAN + dec cx + jnz @@V + jmp @@GetColorInfo + +; Scan top to bottom +@@T2B: + cwd + div cx + mov bp, ax + xor ax, ax + div cx + xchg ax, bx ; BP:BX = fixed 16:16 step + mov dx, 8000h +@@T2BLoop: + mov es:[di].Y1, ax + add di, SIZE TSCAN + add dx, bx + adc ax, bp + dec cx + jnz @@T2BLoop + jmp @@GetColorInfo + +; Scan bottom to top +@@B2T: + neg ax + cwd + div cx + mov bp, ax + xor ax, ax + div cx + xchg ax, bx + mov dx, 8000h +@@B2TLoop: + mov es:[di].Y1, ax + add di, SIZE TSCAN + sub dx, bx + sbb ax, bp + dec cx + jnz @@B2TLoop + +; Now get the color info +@@GetColorInfo: + pop bx ; Restore colors + pop ax + pop cx ; Height + pop di ; ES:DI -> scan info + + sub ax, bx ; Get color range + jg @@CL2R + jl @@CR2L + +; Special case: same color + mov ah, bl + mov al, 80h +@@CV: + mov WORD PTR es:[di].E1, ax + add di, SIZE TSCAN + dec cx + jnz @@CV + jmp @@Exit + +; Scan left to right +@@CL2R: + cwd + div cx + mov bp, ax + xor ax, ax + div cx + xchg ax, bx ; BP:BX = fixed 16:16 step + mov dx, 8000h +@@CL2RLoop: + mov es:[di].C1, al + mov es:[di].E1, dh + add di, SIZE TSCAN + add dx, bx + adc ax, bp + dec cx + jnz @@CL2RLoop + jmp @@Exit + +; Scan right to left +@@CR2L: + neg ax + cwd + div cx + mov bp, ax + xor ax, ax + div cx + xchg ax, bx + mov dx, 8000h + +@@CR2LLoop: + mov es:[di].C1, al + mov es:[di].E1, dh + add di, SIZE TSCAN + sub dx, bx + sbb ax, bp + dec cx + jnz @@CR2LLoop + +@@Exit: + pop bp + ret +subScan ENDP + +;----------------------------------------------------------- +; +; Fills a scan column. +; +; Input: +; DS:SI = current TSCAN +; ES:DI = address of top pixel +; CX = number of pixels to write +; DX = base color +; Output: +; none +; +subFillScan PROC NEAR + mov ax, WORD PTR ds:[si].E2 + mov bx, WORD PTR ds:[si].E1 + cmp ah, bh + jg @@L2R ; Color increases + jl @@R2L ; Color decreases + +; Special case: color doesn't change + add ax, dx + mov dx, [mx_BytesPerLine] +@@V: + mov es:[di], ah + add di, dx + dec cx + jnz @@V + ret + +; Color increases +@@L2R: + .push bp, si + mov si, bx + add si, dx ; Relocate color + sub ax, bx + xor dx, dx + div cx + mov bp, ax ; BP = color step, integer part + xor ax, ax + div cx + mov bx, ax ; BX = color step, fractional part + mov dx, 8000h + mov ax, [mx_BytesPerLine] + xchg si, ax +@@L2RLoop: + mov es:[di], ah + add dx, bx + adc ax, bp + add di, si + dec cx + jnz @@L2RLoop + .pop bp, si + ret + +; Color decreases +@@R2L: + .push bp, si + mov si, bx + add si, dx ; Relocate color + sub ax, bx + neg ax + xor dx, dx + div cx + mov bp, ax ; BP = color step, integer part + xor ax, ax + div cx + mov bx, ax ; BX = color step, fractional part + mov dx, 8000h + mov ax, [mx_BytesPerLine] + xchg si, ax +@@R2LLoop: + mov es:[di], ah + sub dx, bx + sbb ax, bp + add di, si + dec cx + jnz @@R2LLoop + .pop bp, si + ret +subFillScan ENDP + +;----------------------------------------------------------- +; +; Fills a convex polygon with the specified color. +; Interpolates pixel colors using the Gouraud algorithm. +; +; Input: +; Count = number of vertexes +; Map = indexes of points and colors (integer) +; Points = array of points (integer X, Y coordinates) +; Colors = array of colors (integer) +; Color = base color +; Output: +; none +; Notes: +; vertexes must be in counterclockwise order, arrays are 0-based. +; +mxGouraudPoly PROC FAR + ARG Color:WORD, \ + Colors:DWORD, \ + Points:DWORD, \ + Map:DWORD, \ + Count:WORD = ARG_SIZE + LOCAL WritePlane:BYTE:2, \ + ScanOffsetT:WORD, \ + ScanOffsetB:WORD, \ + ScanCount:WORD, \ + Holder:WORD, \ + Height:WORD, \ + MinIdxT:WORD, \ + MinIdxB:WORD, \ + MaxIdx:WORD, \ + Width:WORD, \ + BoxX1:WORD, \ + BoxY1:WORD, \ + BoxX2:WORD, \ + BoxY2::WORD = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, es, di + ASSUME ds:NOTHING + +; Check that at least three vertexes are specified + mov cx, [Count] + cmp cx, 3 + jb @@Exit + +;------------------------------ +; Find bounding box for polygon + les di, [Map] + lds si, [Points] ; Pointer to vertex array + mov [BoxX1], 32767 + mov [BoxX2], -32768 + mov [BoxY1], 32767 + mov [BoxY2], -32768 + + xor dx, dx +@@MinMaxLoop: + mov bx, es:[di] ; Get index of vertex + .shl bx, 2 ; Get offset in point array + add bx, si + +; Check X range +@@CheckMinX: + mov ax, ds:[bx].X ; Get X coordinate + cmp ax, [BoxX1] + jge @@CheckMaxX + mov [BoxX1], ax + mov [MinIdxT], dx + mov [MinIdxB], dx +@@CheckMaxX: + cmp ax, [BoxX2] + jle @@CheckMinY + mov [BoxX2], ax + mov [MaxIdx], dx + +; Check Y range +@@CheckMinY: + mov ax, ds:[bx].Y + cmp ax, [BoxY1] + jge @@CheckMaxY + mov [BoxY1], ax +@@CheckMaxY: + cmp ax, [BoxY2] + jle @@CheckDone + mov [BoxY2], ax + +; Repeat thru all points +@@CheckDone: + inc di ; Next map entry + inc di + inc dx + inc dx + dec cx + jnz @@MinMaxLoop + +;--------------------------------- +; Check if polygon is full clipped + mov ax, [BoxX2] + cmp ax, [mx_ClipX1] ; Is poly full clipped? + jl @@Exit + mov bx, [BoxX1] + cmp bx, [mx_ClipX2] ; Is poly full clipped? + jg @@Exit + sub ax, bx ; Get width + jle @@Exit ; Exit if not positive + mov ax, [BoxY2] + cmp ax, [mx_ClipY1] ; Is poly full clipped? + jl @@Exit + mov bx, [BoxY1] + cmp bx, [mx_ClipY2] ; Is poly full clipped? + jg @@Exit + sub ax, bx ; Get height + jle @@Exit ; Exit if not positive + + dec [Count] + shl [Count], 1 ; We'll work with word offsets + mov es, [mx_CodeSegment] + +;-------------- +; Scan top edge + mov ax, OFFSET mx_ScanBuffer + mov [ScanOffsetT], ax + mov si, [MinIdxT] ; Offset of bottom point index +@@STLoop: + lds bx, [Map] ; DS:BX -> map table + mov di, ds:[bx+si] ; Index of top point #1 + dec si ; Next point + dec si + test si, si + jnl @@ST1 + mov si, [Count] +@@ST1: + mov [MinIdxT], si ; Save new index of top point + mov si, ds:[bx+si] ; Get index of top point #2 + lds bx, [Colors] ; Get pointer to color array + shl di, 1 ; Convert indexes to offsets + shl si, 1 + mov ax, ds:[bx+si] ; Get colors + mov dx, ds:[bx+di] + lds bx, [Points] ; DS:BX -> point array + shl si, 1 + shl di, 1 + add si, bx ; DS:SI -> top point #2 + add bx, di ; DS:BX -> top point #1 + mov di, [ScanOffsetT] + call subScan ; Scan edge + mov [ScanOffsetT], di + mov si, [MinIdxT] + cmp si, [MaxIdx] ; End of edge? + jne @@STLoop ; No, continue + +;----------------- +; Scan bottom edge + mov ax, OFFSET mx_ScanBuffer + OFFSET Y2 + mov [ScanOffsetB], ax + mov si, [MinIdxB] ; Offset of bottom point index +@@SBLoop: + lds bx, [Map] ; DS:BX -> map table + mov di, ds:[bx+si] ; Index of bottom point #1 + inc si ; Next bottom point + inc si + cmp si, [Count] + jbe @@SB1 + xor si, si +@@SB1: + mov [MinIdxB], si ; Save new index of bottom point + mov si, ds:[bx+si] ; Get index of bottom point #2 + lds bx, [Colors] ; Get pointer to color array + shl di, 1 ; Convert indexes to offsets + shl si, 1 + mov ax, ds:[bx+si] ; Get colors + mov dx, ds:[bx+di] + lds bx, [Points] ; DS:BX -> point array + shl si, 1 + shl di, 1 + add si, bx ; DS:SI -> top point #2 + add bx, di ; DS:BX -> top point #1 + mov di, [ScanOffsetB] + call subScan ; Scan edge + mov [ScanOffsetB], di + mov si, [MinIdxB] + cmp si, [MaxIdx] ; End of edge? + jne @@SBLoop ; No, continue + +;-------------------- +; Clip left and right + mov si, OFFSET mx_ScanBuffer + mov ax, [BoxX1] + mov cx, [BoxX2] + sub cx, ax ; CX = bounding box width + mov bx, [mx_ClipX1] + sub bx, ax + jle @@ClipL1 ; No need to clip left + sub cx, bx ; Update width + add ax, bx ; BoxX1 = mx_ClipX1 + mov [BoxX1], ax + .shl bx, 3 ; Warning!!! This is an hand-coded + add si, bx ; multiply by the size of TSCAN +@@ClipL1: + mov bx, ax + add bx, cx ; Last scan column + sub bx, [mx_ClipX2] + jle @@ClipL2 ; No need to clip right + sub cx, bx ; Clip right +@@ClipL2: + test cx, cx ; Is clipped width positive? + jle @@Exit ; No, exit + mov [ScanCount], cx ; Save number of columns to draw + mov [ScanOffsetT], si ; Remember offset of (clipped) buffer + mov ds, [mx_CodeSegment] ; DS:SI -> scan buffer + +;------------------------------ +; Check if Y clipping is needed + mov ax, [BoxY1] + cmp ax, [mx_ClipY1] + jl @@ClipTB ; Need to clip top + mov ax, [BoxY2] + cmp ax, [mx_ClipY2] + jg @@ClipTB ; Need to clip bottom + jmp @@ClipYExit ; Skip Y clipping + +;-------------------- +; Clip top and bottom +@@ClipTB: + mov di, cx ; DI = scan count + inc di ; Increment count for pre-loop test + sub si, SIZE TSCAN +@@ClipYLoop: + dec di ; Any column left? + jz @@ClipYExit ; No, exit + add si, SIZE TSCAN + mov ax, ds:[si].Y1 ; Y1 + mov cx, ds:[si].Y2 ; Y2 + mov dx, [mx_ClipY2] + cmp ax, dx ; Full clipped? + jg @@ClipYClip ; Yes, skip this column + cmp cx, dx ; Need to clip bottom? + jle @@ClipY1 ; No, continue +; Clip bottom, need to scale colors too + mov ds:[si].Y2, dx + mov bx, cx + sub bx, dx ; Clip distance + sub cx, ax ; Height + jle @@ClipYClip + mov ax, WORD PTR ds:[si].E1 + sub ax, WORD PTR ds:[si].E2 + imul bx + idiv cx + add WORD PTR ds:[si].E2, ax + mov ax, ds:[si].Y1 ; Restore AX and CX + mov cx, ds:[si].Y2 +@@ClipY1: + mov dx, [mx_ClipY1] + cmp cx, dx ; Full top clipped? + jl @@ClipYClip ; Yes, skip + sub cx, ax ; Get height + jle @@ClipYClip ; Skip if not positive + cmp ax, dx ; Need to clip top? + jge @@ClipYLoop ; No, continue +; Clip top, need to scale colors too + mov ds:[si].Y1, dx ; Y1 = mx_ClipY1 + sub dx, ax ; DX = number of pixels clipped + cmp cx, dx + jbe @@ClipYClip ; Full clipped, skip + mov ax, WORD PTR ds:[si].E2 + sub ax, WORD PTR ds:[si].E1 ; AX = color distance + imul dx + idiv cx + add WORD PTR ds:[si].E1, ax ; Update starting color + jmp @@ClipYLoop +@@ClipYClip: + mov ds:[si].Y1, -1 ; Mark column as clipped + jmp @@ClipYLoop +@@ClipYExit: + +;------------- +; Draw columns + mov es, [mx_VideoSegment] + mov si, [ScanOffsetT] + mov cl, BYTE PTR [BoxX1] ; Init write plane + and cl, 03h + mov al, 11h + shl al, cl + mov [WritePlane], al + .shr [BoxX1], 2 + mov ax, [Color] ; Make 8:8 fixed color + mov ah, al + xor al, al + mov [Color], ax +@@DrawLoop: + mov ax, ds:[si].Y1 + test ax, ax ; Was column clipped? + js @@DrawNext ; Yes, skip + mov cx, ds:[si].Y2 + sub cx, ax ; CX = height + jle @@DrawNext + mul [mx_BytesPerLine] ; Get pixel address + add ax, [BoxX1] + mov di, ax + mov ah, [WritePlane] + mov al, 02h + mov dx, TS + out dx, ax + mov dx, [Color] + call subFillScan +@@DrawNext: + rol [WritePlane], 1 + adc [BoxX1], 0 ; Bump pointer to video memory if needed + add si, SIZE TSCAN + dec [ScanCount] + jnz @@DrawLoop + +@@Exit: + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxGouraudPoly ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxpi.asm b/16/x/mxpi.asm new file mode 100755 index 00000000..9e8525f5 --- /dev/null +++ b/16/x/mxpi.asm @@ -0,0 +1,267 @@ +;----------------------------------------------------------- +; +; MXPI.ASM - Put image +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxPutImage + +EXTRN subClipImage : NEAR + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_VideoSegment : WORD +EXTRN mx_BytesPerLine : WORD + +mxTable LABEL WORD ; Raster ops + DW subMove + DW subAnd + DW subOr + DW subXor + DW subTrans + DW subAdd + +;----------------------------------------------------------- +; +; Move functions. +; Note: loops unrolled and optimized for CX even, no check for CX = 0. +; +subMove PROC NEAR + shr cx, 1 ; Make CX even + jc @@Odd ; Special case if odd byte +@@Loop: movsb + add si, 3 + movsb + add si, 3 + dec cx + jnz @@Loop +@@Exit: ret +@@Odd: movsb + add si, 3 + jcxz @@Exit + jmp @@Loop +subMove ENDP +; +subAnd PROC NEAR + shr cx, 1 + jc @@Odd +@@Loop: mov al, ds:[si] + mov ah, ds:[si+4] + and es:[di], ax + inc di + inc di + add si, 8 + dec cx + jnz @@Loop +@@Exit: ret +@@Odd: lodsb + and es:[di], al + inc di + add si, 3 + jcxz @@Exit + jmp @@Loop +subAnd ENDP +; +subOr PROC NEAR + shr cx, 1 + jc @@Odd +@@Loop: mov al, ds:[si] + mov ah, ds:[si+4] + or es:[di], ax + inc di + inc di + add si, 8 + dec cx + jnz @@Loop +@@Exit: ret +@@Odd: lodsb + or es:[di], al + inc di + add si, 3 + jcxz @@Exit + jmp @@Loop +subOr ENDP +; +subXor PROC NEAR + shr cx, 1 + jc @@Odd +@@Loop: mov al, ds:[si] + mov ah, ds:[si+4] + xor es:[di], ax + inc di + inc di + add si, 8 + dec cx + jnz @@Loop +@@Exit: ret +@@Odd: lodsb + xor es:[di], al + inc di + add si, 3 + jcxz @@Exit + jmp @@Loop +subXor ENDP +; +subTrans PROC NEAR +@@Loop: mov al, ds:[si] + cmp al, ah + je @@Skip + mov es:[di], al +@@Skip: inc di + add si, 4 + dec cx + jnz @@Loop +@@Exit: ret +subTrans ENDP +; +subAdd PROC NEAR +@@Loop: mov al, ds:[si] + add es:[di], al + inc di + add si, 4 + dec cx + jnz @@Loop + ret +subAdd ENDP + +;----------------------------------------------------------- +; +; Copies a "raw" image from memory to screen. +; +; Input: +; Image = pointer to image +; X, Y = coordinates of destination +; Width = width of image in pixels +; Height = height of image in pixels +; Op = raster op (OP_xxx) +; Output: +; none +; +mxPutImage PROC FAR + ARG Op:WORD, \ + Height:WORD, \ + Width:WORD, \ + Y:WORD, \ + X:WORD, \ + Image:DWORD = ARG_SIZE + LOCAL PlaneWidth:WORD:4, \ + PixelOffset:WORD, \ + MoveFunction:WORD, \ + Count:BYTE, \ + ReadPlane:BYTE, \ + OpInfo:BYTE, \ + WritePlane:BYTE = AUTO_SIZE + ASSUME ds:NOTHING + .enter AUTO_SIZE + .push ds, si, es, di + +; Clip image + mov bx, [X] + mov ax, [Y] + mov cx, [Width] + mov dx, [Height] + call subClipImage + jc @@Exit ; Full clipped + mov [Height], dx + add WORD PTR Image[0], si ; Skip clipped pixels + +; Get pixel address + mul [mx_BytesPerLine] + mov di, bx + shr di, 1 + shr di, 1 + add di, ax + mov [PixelOffset], di + mov es, [mx_VideoSegment] ; ES:DI points to pixel + and bl, 03h + mov [ReadPlane], bl + +; Compute extra bytes and width count for each plane + mov bx, cx + shr bx, 1 + shr bx, 1 ; Width for each plane + and cl, 03h + mov al, 00001000b + shr al, cl + mov si, 3 SHL 1 +@@PatchLoop: + mov PlaneWidth[si], bx + shr al, 1 + adc bx, 0 + dec si + dec si + jge @@PatchLoop + +; Setup planes for output to VGA registers + mov cl, [ReadPlane] + mov al, 00010001b + shl al, cl + mov [WritePlane], al + +; Install move function + mov bx, [Op] + mov [OpInfo], bh ; Remember additional info if needed + xor bh, bh + cmp bl, OP_ADD + jbe @@SetMoveFunction + xor bl, bl +@@SetMoveFunction: + shl bx, 1 + mov ax, mxTable[bx] + mov [MoveFunction], ax + +; Put image + cld + mov [Count], 4 ; Four planes + lea bx, PlaneWidth ; SS:[BX] = width in bytes for plane + mov ds, WORD PTR Image[2] +@@PlaneLoop: + cmp WORD PTR ss:[bx], 0 ; Exit if nothing more to do + je @@Exit ; (also, never try to move zero bytes!) + mov si, WORD PTR Image[0] + mov ah, [WritePlane] + and ah, 0Fh + mov al, 02h + mov dx, TS + out dx, ax ; Select write plane + mov ah, [ReadPlane] + and ah, 03h + mov al, 04h + mov dx, GDC + out dx, ax ; Select read plane + mov dx, [Height] + mov di, [PixelOffset] +@@Loop: + push si + push di + mov cx, WORD PTR ss:[bx] ; Number of bytes to move + mov ah, [OpInfo] ; Transparent color for subTrans + call [MoveFunction] + pop di + pop si + add si, [Width] ; Go to next image line + add di, [mx_BytesPerLine] ; Go to next screen row + dec dx + jnz @@Loop ; Repeat for all lines + inc bx + inc bx ; Select width for next plane + inc [ReadPlane] + rol [WritePlane], 1 + adc [PixelOffset], 0 + inc WORD PTR Image[0] + dec [Count] + jnz @@PlaneLoop ; Repeat for all planes + +@@Exit: + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxPutImage ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxpn.asm b/16/x/mxpn.asm new file mode 100755 index 00000000..eaaf61b4 --- /dev/null +++ b/16/x/mxpn.asm @@ -0,0 +1,60 @@ +;----------------------------------------------------------- +; +; MXPN.ASM - Panning function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxPan + +EXTRN mxWaitDisplay : FAR +EXTRN mxStartAddress : FAR + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD + +;----------------------------------------------------------- +; +; Moves the screen. +; +; Input: +; X, Y = new X, Y coordinates of view screen +; Output: +; none +; +mxPan PROC FAR + ARG Y:WORD, \ + X:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + + mov ax, [Y] + mul [mx_BytesPerLine] + mov dx, [X] + shr dx, 1 + shr dx, 1 + add ax, dx + push ax ; Push the start address + call mxWaitDisplay + call mxStartAddress + + mov dx, 03DAh ; Set the pixel pan register + in al, dx + mov dx, 03C0h + mov al, 33h + out dx, al + mov al, BYTE PTR [X] + and al, 3 + shl al, 1 + out dx, al + + xor ax, ax + .leave ARG_SIZE +mxPan ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxpp.asm b/16/x/mxpp.asm new file mode 100755 index 00000000..fc1755a3 --- /dev/null +++ b/16/x/mxpp.asm @@ -0,0 +1,121 @@ +;----------------------------------------------------------- +; +; MXPP.ASM - Get/put pixel functions +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxGetPixel +PUBLIC mxPutPixel + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD +EXTRN mx_VideoSegment : WORD +EXTRN mx_ClipX1 : WORD +EXTRN mx_ClipY1 : WORD +EXTRN mx_ClipX2 : WORD +EXTRN mx_ClipY2 : WORD + +;----------------------------------------------------------- +; +; Gets a pixel. +; +; Input: +; X, Y = pixel coordinates +; Output: +; pixel color +; +mxGetPixel PROC FAR + ARG Y:WORD, \ + X:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si + + xor ax, ax + mov si, [X] + cmp si, [mx_ClipX1] + jl @@Exit + cmp si, [mx_ClipX2] + jg @@Exit + mov bx, [Y] + cmp bx, [mx_ClipY1] + jl @@Exit + cmp bx, [mx_ClipY2] + jg @@Exit + + mov al, 04h ; Set read plane + mov ah, BYTE PTR [X] + and ah, 3 + mov dx, GDC + out dx, ax + + mov ds, [mx_VideoSegment] + mov ax, bx + mul [mx_BytesPerLine] + .shr si, 2 + add si, ax + + mov al, ds:[si] ; Get pixel value + xor ah, ah + +@@Exit: + .pop ds, si + .leave ARG_SIZE +mxGetPixel ENDP + +;----------------------------------------------------------- +; +; Puts a pixel of the specified color. +; +; Input: +; X, Y = pixel coordinates +; Color = pixel color +; Output: +; none +; +mxPutPixel PROC FAR + ARG Color:BYTE:2, \ + Y:WORD, \ + X:WORD = ARG_SIZE + .enter 0 + .push ds, si + + mov si, [X] + cmp si, [mx_ClipX1] + jl @@Exit + cmp si, [mx_ClipX2] + jg @@Exit + mov ax, [Y] + cmp ax, [mx_ClipY1] + jl @@Exit + cmp ax, [mx_ClipY2] + jg @@Exit + + mov ds, [mx_VideoSegment] + mul [mx_BytesPerLine] + .shr si, 2 + add si, ax + + mov cl, BYTE PTR [X] ; Set write plane + and cl, 3 + mov ax, 0102h + shl ah, cl + mov dx, TS + out dx, ax + + mov al, [Color] ; Write pixel + mov ds:[si], al + +@@Exit: + xor ax, ax + .pop ds, si + .leave ARG_SIZE +mxPutPixel ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxra.asm b/16/x/mxra.asm new file mode 100755 index 00000000..dd8e6839 --- /dev/null +++ b/16/x/mxra.asm @@ -0,0 +1,37 @@ +;----------------------------------------------------------- +; +; MXRA.ASM - Row address +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxRowAddress + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Sets the row address register. +; +; Input: +; RowAddress = row size in words +; Output: +; none +; +mxRowAddress PROC FAR + ARG RowAddress:BYTE:2 = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + mov dx, CRTC + mov al, 13h + mov ah, [RowAddress] + out dx, ax + xor ax, ax + .leave ARG_SIZE +mxRowAddress ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxrp.asm b/16/x/mxrp.asm new file mode 100755 index 00000000..de820c16 --- /dev/null +++ b/16/x/mxrp.asm @@ -0,0 +1,101 @@ +;----------------------------------------------------------- +; +; MXRP.ASM - Rotate palette function +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxRotatePalette + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Rotates the palette of the specified number of colors. +; +; Input: +; Palette = pointer to palette +; Count = number of colors to rotate +; Step = step size +; Output: +; none +; +; Note: if Step is positive palette is rotated left to right, otherwise +; right to left. +; +mxRotatePalette PROC FAR + ARG Step:WORD, \ + Count:WORD, \ + Palette:DWORD = ARG_SIZE + LOCAL Holder:BYTE:768 = AUTO_SIZE + ASSUME ds:NOTHING + .enter AUTO_SIZE + .push ds, si, es, di + + mov bx, [Count] + add bx, bx + add bx, [Count] ; BX = Count*3 + + lds si, [Palette] ; DS:SI -> palette + push ss + pop es + lea di, Holder ; ES:DI -> local space + cld + + mov ax, [Step] + mov dx, ax + test ax, ax + jz @@Exit ; Nothing to do, exit + jl @@RightToLeft + +@@LeftToRight: + add ax, ax + add dx, ax ; DX = Step*3 + sub bx, dx ; BX = (Count-Step)*3 + add si, bx + push si + mov cx, dx + rep movsb + mov es, WORD PTR Palette[2] + mov di, si + dec di ; ES:DI -> last byte of palette + pop si + dec si + mov cx, bx + std + rep movsb + push ss + pop ds + lea si, Holder + les di, [Palette] + mov cx, dx + cld + rep movsb + jmp @@Exit + +@@RightToLeft: + add ax, ax + add dx, ax + neg dx ; DX = Step*3 + sub bx, dx ; BX = (Count-Step)*3 + mov cx, dx + rep movsb + les di, [Palette] + mov cx, bx + rep movsb + push ss + pop ds + lea si, Holder + mov cx, dx + rep movsb + +@@Exit: + .pop ds, si, es, di + .leave ARG_SIZE +mxRotatePalette ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxsa.asm b/16/x/mxsa.asm new file mode 100755 index 00000000..3ebae67d --- /dev/null +++ b/16/x/mxsa.asm @@ -0,0 +1,44 @@ +;----------------------------------------------------------- +; +; MXSA.ASM - Start address function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxStartAddress + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Modifies the starting address of video memory. +; +; Input: +; StartAddr = new start address of video memory +; Output: +; none +; +mxStartAddress PROC FAR + ARG StartAddr:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + + mov bx, [StartAddr] + mov dx, CRTC + mov al, 0Ch ; Linear Starting Address high + mov ah, bh + cli + out dx, ax + mov al, 0Dh ; Linear Starting Address low + mov ah, bl + out dx, ax + sti + + .leave ARG_SIZE +mxStartAddress ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxsc.asm b/16/x/mxsc.asm new file mode 100755 index 00000000..bcae45e6 --- /dev/null +++ b/16/x/mxsc.asm @@ -0,0 +1,50 @@ +;----------------------------------------------------------- +; +; MXSC.ASM - Set color function +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxSetColor + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Updates the selected DAC register. +; +; Input: +; Index = index of color to set +; R, G, B = color components +; Output: +; none +; +mxSetColor PROC FAR + ARG B:BYTE:2, \ + G:BYTE:2, \ + R:BYTE:2, \ + Index:WORD = ARG_SIZE + .enter 0 + .push ds, si + + mov ax, [Index] + mov dx, 3C8h ; PEL write address register + out dx, al + inc dx + + mov al, [R] + out dx, al + mov al, [G] + out dx, al + mov al, [B] + out dx, al + + .pop ds, si + .leave ARG_SIZE +mxSetColor ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxsi.asm b/16/x/mxsi.asm new file mode 100755 index 00000000..b88d3b11 --- /dev/null +++ b/16/x/mxsi.asm @@ -0,0 +1,317 @@ +;----------------------------------------------------------- +; +; MXPI.ASM - Stretch image +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxStretchImage + +EXTRN subClipBox : NEAR + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_VideoSegment : WORD +EXTRN mx_BytesPerLine : WORD + +mxTable LABEL WORD ; Raster ops + DW subMove + DW subAnd + DW subOr + DW subXor + DW subTrans + DW subAdd + +;----------------------------------------------------------- +; +; Stretches and copies a "raw" image from memory to screen. +; +; Input: +; Image = pointer to image +; X, Y = coordinates of destination +; Width = width of image in pixels +; Height = height of image in pixels +; NewWidth = new width of image in pixels +; NewHeight = new height of image in pixels +; Op = raster op (OP_xxx) +; Output: +; none +; +mxStretchImage PROC FAR + ARG Op:WORD, \ + NewHeight:WORD, \ + NewWidth:WORD, \ + Height:WORD, \ + Width:WORD, \ + Y:WORD, \ + X:WORD, \ + Image:DWORD = ARG_SIZE + LOCAL PixelOffset:WORD, \ + MoveFunction:WORD, \ + ReadPlane:BYTE, \ + OpInfo:BYTE, \ + WidthStep:DWORD, \ + HeightStep:DWORD, \ + ImageLo:WORD, \ + WritePlane:BYTE = AUTO_SIZE + ASSUME ds:NOTHING + .enter AUTO_SIZE + .push ds, si, es, di + +; Get width stretch factor + IF USE386 EQ TRUE + movzx edx, [Width] + xor eax, eax + movzx ebx, [NewWidth] + shl ebx, 16 + idiv ebx + mov [WidthStep], eax + ELSE + xor dx, dx ; Width stretch factor + mov ax, [Width] + mov bx, [NewWidth] + div bx + mov WORD PTR WidthStep[2], ax + xor ax, ax + div bx + mov WORD PTR WidthStep[0], ax + ENDIF +; Get height stretch factor + IF USE386 EQ TRUE + movzx edx, [Height] + xor eax, eax + movzx ebx, [NewHeight] + shl ebx, 16 + idiv ebx + mov [HeightStep], eax + ELSE + xor dx, dx + mov ax, [Height] + mov bx, [NewHeight] + div bx + mov WORD PTR HeightStep[2], ax + xor ax, ax + div bx + mov WORD PTR HeightStep[0], ax + ENDIF + +; Clip image + mov bx, [X] + mov ax, [Y] + mov cx, [NewWidth] + mov dx, [NewHeight] + call subClipBox + jc @@Exit ; Full clipped + mov [NewWidth], cx + mov [NewHeight], dx + sub [X], bx + sub [Y], ax + +; Get pixel address + mul [mx_BytesPerLine] + mov di, bx + shr di, 1 + shr di, 1 + add di, ax + mov [PixelOffset], di + mov es, [mx_VideoSegment] ; ES:DI points to pixel + and bl, 03h + mov [ReadPlane], bl ; Set read plane + mov cl, bl + mov al, 00010001b + shl al, cl + mov [WritePlane], al ; Set write plane + +; Relocate image origin if previously clipped + mov ax, [Y] + test ax, ax + jz @@OriginYDone + IF USE386 EQ TRUE + shl eax, 16 + imul [HeightStep] + mov ax, [Width] + mul dx + ELSE + mov bx, ax + mul WORD PTR HeightStep[0] + mov cx, dx + mov ax, bx + mul WORD PTR HeightStep[2] + add ax, cx + mul [Width] + ENDIF + add WORD PTR [Image], ax +@@OriginYDone: + mov ax, [X] + test ax, ax + jz @@OriginXDone + IF USE386 EQ TRUE + shl eax, 16 + imul [WidthStep] + add WORD PTR [Image], dx + ELSE + mov bx, ax + mul WORD PTR WidthStep[0] + mov cx, dx + mov ax, bx + mul WORD PTR WidthStep[2] + add ax, cx + add WORD PTR [Image], ax + ENDIF +@@OriginXDone: + mov ax, WORD PTR HeightStep[2] + mul [Width] + mov WORD PTR HeightStep[2], ax + +; Install move function + mov bx, [Op] + mov [OpInfo], bh ; Remember additional info if needed + xor bh, bh + cmp bl, OP_ADD + jbe @@SetMoveFunction + xor bl, bl +@@SetMoveFunction: + shl bx, 1 + mov ax, mxTable[bx] + mov [MoveFunction], ax + +; Put image + mov ds, WORD PTR Image[2] + xor ax, ax + mov [ImageLo], ax +@@Loop: + mov si, WORD PTR Image[0] ; Get pointer to image + mov ah, [WritePlane] + and ah, 0Fh + mov al, 02h + mov dx, TS + out dx, ax ; Select write plane + mov ah, [ReadPlane] + and ah, 03h + mov al, 04h + mov dx, GDC + out dx, ax ; Select read plane + mov cx, [NewHeight] + mov di, [PixelOffset] ; ES:DI points to video memory + mov ah, [OpInfo] ; Additional raster op info + xor bx, bx + mov dx, [mx_BytesPerLine] + call [MoveFunction] ; Draw column + inc [ReadPlane] ; Next read plane + rol [WritePlane], 1 ; Next write plane + adc [PixelOffset], 0 ; Update video offset if needed + mov dx, WORD PTR WidthStep[0] + mov ax, WORD PTR WidthStep[2] + add [ImageLo], dx + adc WORD PTR Image[0], ax ; Next image column + dec [NewWidth] + jnz @@Loop ; Repeat for all columns + +@@Exit: + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE + +;----------------------------------------------------------- +; +; Move functions, on entry: +; AH = additional raster op info (e.g. transparent color) +; BX = 0, +; CX = pixel count, +; DX = mx_BytesPerLine. +; +subMove PROC NEAR +@@Loop: mov al, ds:[si] + mov es:[di], al + add di, dx + dec cx + jz @@Exit + add si, WORD PTR HeightStep[2] + add bx, WORD PTR HeightStep[0] + jnc @@Loop + add si, [Width] + jmp @@Loop +@@Exit: ret +subMove ENDP +; +subAnd PROC NEAR +@@Loop: mov al, ds:[si] + and es:[di], al + add di, dx + dec cx + jz @@Exit + add si, WORD PTR HeightStep[2] + add bx, WORD PTR HeightStep[0] + jnc @@Loop + add si, [Width] + jmp @@Loop +@@Exit: ret +subAnd ENDP +; +subOr PROC NEAR +@@Loop: mov al, ds:[si] + or es:[di], al + add di, dx + dec cx + jz @@Exit + add si, WORD PTR HeightStep[2] + add bx, WORD PTR HeightStep[0] + jnc @@Loop + add si, [Width] + jmp @@Loop +@@Exit: ret +subOr ENDP +; +subXor PROC NEAR +@@Loop: mov al, ds:[si] + xor es:[di], al + add di, dx + dec cx + jz @@Exit + add si, WORD PTR HeightStep[2] + add bx, WORD PTR HeightStep[0] + jnc @@Loop + add si, [Width] + jmp @@Loop +@@Exit: ret +subXor ENDP +; +subTrans PROC NEAR +@@Loop: mov al, ds:[si] + cmp al, ah + je @@Skip + mov es:[di], al +@@Skip: + add di, dx + dec cx + jz @@Exit + add si, WORD PTR HeightStep[2] + add bx, WORD PTR HeightStep[0] + jnc @@Loop + add si, [Width] + jmp @@Loop +@@Exit: ret +subTrans ENDP +; +subAdd PROC NEAR +@@Loop: mov al, ds:[si] + add es:[di], al + add di, dx + dec cx + jz @@Exit + add si, WORD PTR HeightStep[2] + add bx, WORD PTR HeightStep[0] + jnc @@Loop + add si, [Width] + jmp @@Loop +@@Exit: ret +subAdd ENDP + +mxStretchImage ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxsl.asm b/16/x/mxsl.asm new file mode 100755 index 00000000..d7908855 --- /dev/null +++ b/16/x/mxsl.asm @@ -0,0 +1,62 @@ +;----------------------------------------------------------- +; +; MXLN.ASM - Start line function +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxStartLine + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD + +;----------------------------------------------------------- +; +; Changes the video start address to the specified line. +; +; Input: +; Line = new start line +; Output: +; none +; +mxStartLine PROC FAR + ARG Line:WORD = ARG_SIZE + .enter 0 + ASSUME ds:NOTHING + + mov ax, [Line] ; Get video offset + mul [mx_BytesPerLine] + xchg ax, bx ; Copy it into BX + +; Wait display + mov dx, STATUS +@@1: in al, dx + test al, 08h + jnz @@1 + +; Set starting address + mov dx, CRTC + mov al, 0Ch ; Linear Starting Address high + mov ah, bh + cli + out dx, ax + mov al, 0Dh ; Linear Starting Address low + mov ah, bl + out dx, ax + sti + +; Wait retrace + mov dx, STATUS +@@2: in al,dx + test al, 08h + jz @@2 + + xor ax, ax + .leave ARG_SIZE +MX_TEXT ENDS +END diff --git a/16/x/mxsm.asm b/16/x/mxsm.asm new file mode 100755 index 00000000..183fba1e --- /dev/null +++ b/16/x/mxsm.asm @@ -0,0 +1,508 @@ +;----------------------------------------------------------- +; +; MXSM.ASM - Set/change mode functions +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxChangeMode +PUBLIC mxGetAspect +PUBLIC mxGetScreenSize +PUBLIC mxSetMode + +PUBLIC mx_ScreenWidth +PUBLIC mx_ScreenHeight +PUBLIC mx_BytesPerLine + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mxSetSysClipRegion : FAR + +EXTRN mx_VideoSegment : WORD +EXTRN mx_CodeSegment : WORD + +mx_ScreenWidth DW ? ; Current screen width +mx_ScreenHeight DW ? +mx_AspectX DW ? ; Aspect ratio for current mode +mx_AspectY DW ? +mx_BytesPerLine DW 0 ; Bytes per line + +; +; Tables for setting video modes, sources: +; - MODEX.ASM, Matt Pritchard +; - Dr. Dobb's Journal, Michael Abrash +; - Fractint VIDEO.ASM module +; +TBL_SingleLine LABEL WORD ; CRTC + DW 04009h ; Cell height: 1 scan line + DW 00014h ; Double word mode off + DW 0E317h ; Byte mode on + DW 0 +TBL_DoubleLine LABEL WORD ; CRTC + DW 04109h ; Cell height: 2 scan lines + DW 00014h + DW 0E317h + DW 0 +TBL_Width320 LABEL WORD ; CRTC + DW 05F00h ; Horizontal total + DW 04F01h ; Horizontal displayed + DW 05002h ; Start horizontal blanking + DW 08203h ; End horizontal blanking + DW 05404h ; Start horizontal sync + DW 08005h ; End horizontal sync + DW 02813h ; Row address + DW 0 +TBL_Width360 LABEL WORD ; CRTC + DW 06B00h ; Horizontal total + DW 05901h ; Horizontal displayed + DW 05A02h ; Start horizontal blanking + DW 08E03h ; End horizontal blanking + DW 05E04h ; Start horizontal sync + DW 08A05h ; End horizontal sync + DW 02D13h ; Row address + DW 0 +TBL_Height175 LABEL WORD ; CRTC + DW 0BF06h ; Vertical total + DW 01F07h ; Overflow + DW 08310h ; Start vertical sync + DW 08511h ; End vertical sync + DW 05D12h ; Vertical displayed + DW 06315h ; Start vertical blanking + DW 0BA16h ; End vertical blanking + DW 0 +TBL_Height200 LABEL WORD ; CRTC + DW 0BF06h ; Vertical total + DW 01F07h ; Overflow + DW 09C10h ; Start vertical sync + DW 08E11h ; End vertical sync + DW 08F12h ; Vertical displayed + DW 09615h ; Start vertical blanking + DW 0B916h ; End vertical blanking + DW 0 +TBL_Height240 LABEL WORD ; CRTC + DW 00D06h ; Vertical total + DW 03E07h ; Overflow + DW 0EA10h ; Start vertical sync + DW 08C11h ; End vertical sync + DW 0DF12h ; Vertical displayed + DW 0E715h ; Start vertical blanking + DW 00616h ; End vertical blanking + DW 0 +TBL_Tweak400x600: + DW 07400h + DW 06301h + DW 06402h + DW 09703h + DW 06804h + DW 09505h + DW 08606h + DW 0F007h + DW 06009h + DW 0310Fh + DW 05B10h + DW 08D11h + DW 05712h + DW 03213h + DW 00014h + DW 06015h + DW 08016h + DW 0E317h + DW 0 + +TBL_320x200: + DB 63h ; 400 scan lines, 25 MHz clock + DW 6, 5 ; Aspect: 6/5 = 1.2:1 + DW 320, 200 ; Size + DW TBL_Width320, TBL_Height200, TBL_DoubleLine, 0 + DW 819 ; Max height +TBL_320x240: + DB 0E3h ; 400 scan lines, 25 MHz clock + DW 1, 1 ; Aspect: 1/1 = 1:1 + DW 320, 240 ; Size + DW TBL_Width320, TBL_Height240, TBL_DoubleLine, 0 + DW 819 ; Max height +TBL_320x400: + DB 63h ; 480 scan lines, 25 MHz clock + DW 6, 10 ; Aspect: 6/10 = 0.6:1 + DW 320, 400 ; Size + DW TBL_Width320, TBL_Height200, TBL_SingleLine, 0 + DW 819 ; Max height +TBL_320x480: + DB 0E3h ; 480 scan lines, 25 MHz clock + DW 1, 2 ; Aspect: 1/2 = 0.5:1 + DW 320, 480 ; Size + DW TBL_Width320, TBL_Height240, TBL_SingleLine, 0 + DW 819 ; Max height +TBL_360x200: + DB 067h ; 400 scan lines, 28 MHz clock + DW 27, 20 ; Aspect: 27/20 = 1.35:1 + DW 360, 200 ; Size + DW TBL_Width360, TBL_Height200, TBL_DoubleLine, 0 + DW 728 ; Max height +TBL_360x240: + DB 0E7h ; 480 scan lines, 28 MHz clock + DW 9, 8 ; Aspect: 9/8 = 1.125:1 + DW 360, 240 ; Size + DW TBL_Width360, TBL_Height240, TBL_DoubleLine, 0 + DW 728 ; Max height +TBL_360x400: + DB 067h ; 400 scan lines, 28 MHz clock + DW 27, 40 ; Aspect: 27/40 = 0.675:1 + DW 360, 400 ; Size + DW TBL_Width360, TBL_Height200, TBL_SingleLine, 0 + DW 728 ; Max height +TBL_360x480: + DB 0E7h ; 480 scan lines, 28 MHz clock + DW 9, 16 ; Aspect: 9/16 = 0.5625:1 + DW 360, 480 ; Size + DW TBL_Width360, TBL_Height240, TBL_SingleLine, 0 + DW 728 ; Max height +TBL_320x175: + DB 0A3h + DW 0, 0 ; Aspect: + DW 320, 175 + DW TBL_Width320, TBL_Height175, TBL_DoubleLine, 0 + DW 819 +TBL_320x350: + DB 0A3h + DW 0, 0 ; Aspect: + DW 320, 175 + DW TBL_Width320, TBL_Height175, TBL_SingleLine, 0 + DW 819 +TBL_360x175: + DB 0A7h + DW 0, 0 ; Aspect: + DW 360, 480 ; Size + DW TBL_Width360, TBL_Height175, TBL_DoubleLine, 0 + DW 728 ; Max height +TBL_360x350: + DB 0A7h + DW 0, 0 ; Aspect: + DW 360, 480 ; Size + DW TBL_Width360, TBL_Height175, TBL_SingleLine, 0 + DW 728 ; Max height +TBL_400x600: + DB 0E7h ; 28 MHz clock + DW 1, 2 ; Aspect: 1/2 = 0.5:1 + DW 400, 600 ; Size + DW TBL_Tweak400x600, 0 + DW 655 ; Max height + +TBL_Mode LABEL WORD + DW TBL_320x175 + DW TBL_320x200 + DW TBL_320x240 + DW TBL_320x350 + DW TBL_320x400 + DW TBL_320x480 + DW TBL_360x175 + DW TBL_360x200 + DW TBL_360x240 + DW TBL_360x350 + DW TBL_360x400 + DW TBL_360x480 + DW TBL_400x600 + +MAXVMODE EQU ($-OFFSET TBL_Mode) / 2 + +;----------------------------------------------------------- +; +; Enables 80x25 color text mode +; +subText PROC NEAR + ASSUME ds:MX_TEXT + mov ax, 0003h + int 10h ; Call BIOS set mode + + mov [mx_ScreenHeight], 0 + mov [mx_BytesPerLine], 0 + ret +subText ENDP + +;----------------------------------------------------------- +; +; Enables the selected graphics mode. +; +; Input: +; Mode = mode to select (MX_???x???) +; Output: +; none +; +mxSetMode PROC FAR + ARG Mode:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si, es, di + +; Set DS to code segment alias + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov si, [Mode] + cmp si, MAXVMODE ; Is it a valid mode? + ja @@Exit ; No, exit + test si, si ; Text mode? + jnz @@Set ; No, handle it + + call subText ; Back to text mode + jmp @@Exit ; Exit now + +; Set video mode +@@Set: + dec si ; Skip text mode + shl si, 1 + mov si, TBL_Mode[si] + cld + +; Use BIOS to set 320x200x256 linear mode + push si ; Save SI + mov ax, 0013h + int 10h ; Use BIOS to set 320x200 linear mode + pop si ; Restore SI + + mov dx, TS + mov ax, 0604h + out dx, ax ; Disable chain-4 mode + mov ax, 0100h + out dx, ax ; Reset + mov dx, MISC + lodsb + out dx, al ; New timing/size + mov dx, TS + mov ax, 0300h + out dx, ax ; Restart sequencer + +; Unlock CRTC registers 0-7 + mov dx, CRTC + mov al, 11h + out dx, al ; Vertical sync end register + inc dx + in al, dx + and al, 7Fh ; Clear write protect bit + out dx, al + + lodsw ; Get X aspect + mov [mx_AspectX], ax + lodsw ; Get Y aspect + mov [mx_AspectY], ax + lodsw ; Get screen width + mov [mx_ScreenWidth], ax + shr ax, 1 + shr ax, 1 ; Divide by four to get bytes per line + mov [mx_BytesPerLine], ax + lodsw ; Get screen height + mov [mx_ScreenHeight], ax + +; Set CRTC registers + mov bx, si + mov dx, CRTC +@@TableLoop: + mov si, ds:[bx] ; DS:SI -> table of CRTC registers + inc bx + inc bx ; DS:BX -> offset of next table + test si, si ; Last table? + jz @@EndLoop ; Yes, exit loop +@@Loop: + lodsw ; Get CRTC register index and value + test ax, ax ; End of table? + jz @@TableLoop ; Yes, go to next table + out dx, ax ; Set register AL to value AH + jmp @@Loop ; Get next register/value +@@EndLoop: + +; Set virtual screen and system clip region + push [mx_ScreenWidth] + push WORD PTR ds:[bx] + call mxSetSysClipRegion + +; Clear video memory + mov dx, TS + mov ax, 0F02h + out dx, ax ; Enable all planes + mov es, [mx_VideoSegment] + xor di, di + mov cx, 8000h + xor ax, ax + rep stosw + +@@Done: +; Lock CRTC registers 0-7 (some cards need this) + mov dx, CRTC + mov al, 11h + out dx, al ; Vertical sync end register + inc dx + in al, dx + or al, 80h ; Set write protect bit + out dx, al + +@@Exit: + xor ax, ax + mov ax, [mx_ScreenWidth] + .pop ds, si, es, di + .leave ARG_SIZE +mxSetMode ENDP + +;----------------------------------------------------------- +; +; Changes from the current mode the selected graphics mode. +; +; Input: +; Mode = mode to select (MX_???x???) +; Output: +; none +; Notes: +; this function assumes that mxSetMode and mxSetVirtualScreen +; have been called first. View size is rearranged to match the +; specified mode, but video memory is not cleared. +; Differences from mxSetMode: +; - video BIOS is not called to initialize graphics; +; - row address register is not modified; +; - video memory is not cleared; +; - mx_BytesPerLine is not modified; +; - system clip region is not modified. +; +mxChangeMode PROC FAR + ARG Mode:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si, es, di + +; Set DS to code segment alias + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov si, [Mode] + cmp si, MAXVMODE ; Is it a valid mode? + ja @@Exit ; No, exit + test si, si ; Text mode? + jz @@Exit ; Yes, exit + + dec si ; Skip text mode + shl si, 1 + mov si, TBL_Mode[si] + cld + + mov dx, TS + mov ax, 0604h + out dx, ax ; Disable chain-4 mode + mov ax, 0100h + out dx, ax ; Reset + mov dx, MISC + lodsb + out dx, al ; New timing/size + mov dx, TS + mov ax, 0300h + out dx, ax ; Restart sequencer + +; Unlock CRTC registers 0-7 + mov dx, CRTC + mov al, 11h + out dx, al ; Vertical sync end register + inc dx + in al, dx + and al, 7Fh ; Clear write protect bit + out dx, al + + lodsw ; Get X aspect + mov [mx_AspectX], ax + lodsw ; Get Y aspect + mov [mx_AspectY], ax + lodsw ; Get screen width + mov [mx_ScreenWidth], ax + lodsw ; Get screen height + mov [mx_ScreenHeight], ax + +; Set CRTC registers + mov bx, si + mov dx, CRTC +@@TableLoop: + mov si, ds:[bx] ; DS:SI -> table of CRTC registers + inc bx + inc bx ; DS:BX -> offset of next table + test si, si ; Last table? + jz @@EndLoop ; Yes, exit loop +@@Loop: + lodsw ; Get CRTC register index and value + test ax, ax ; End of table? + jz @@TableLoop ; Yes, go to next table + cmp al, 13h ; Row address register? + je @@Loop ; Yes, ignore it + out dx, ax ; Set register AL to value AH + jmp @@Loop ; Get next register/value +@@EndLoop: + +; Lock CRTC registers 0-7 (some cards need this) + mov dx, CRTC + mov al, 11h + out dx, al ; Vertical sync end register + inc dx + in al, dx + or al, 80h ; Set write protect bit + out dx, al + +@@Exit: + xor ax, ax + mov ax, [mx_ScreenWidth] + .pop ds, si, es, di + .leave ARG_SIZE +mxChangeMode ENDP + +;----------------------------------------------------------- +; +; Returns the aspect ratio for the current mode. +; +; Input: +; AspectX = pointer to aspect X +; AspectY = pointer to aspect Y +; +; A rectangle of width AspectX and height AspectY looks like a square. +; +mxGetAspect PROC FAR + ARG AspectY:DWORD, \ + AspectX:DWORD = ARG_SIZE + .enter 0 + .push ds, si + ASSUME ds:NOTHING + + lds si, [AspectX] + mov ax, [mx_AspectX] + mov ds:[si], ax + lds si, [AspectY] + mov ax, [mx_AspectY] + mov ds:[si], ax + + .pop ds, si + .leave ARG_SIZE +mxGetAspect ENDP + +;----------------------------------------------------------- +; +; Returns the current screen size. +; +; Input: +; Width = pointer to screen width +; Height = pointer to screen height +; +mxGetScreenSize PROC FAR + ARG SizeY:DWORD, \ + SizeX:DWORD = ARG_SIZE + .enter 0 + .push ds, si + ASSUME ds:NOTHING + + lds si, [SizeX] + mov ax, [mx_ScreenWidth] + mov ds:[si], ax + lds si, [SizeY] + mov ax, [mx_ScreenHeight] + mov ds:[si], ax + + .pop ds, si + .leave ARG_SIZE +mxGetScreenSize ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxsp.asm b/16/x/mxsp.asm new file mode 100755 index 00000000..1d08e711 --- /dev/null +++ b/16/x/mxsp.asm @@ -0,0 +1,57 @@ +;----------------------------------------------------------- +; +; MXSP.ASM - Set palette function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxSetPalette + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Updates the VGA palette. +; +; Input: +; Buffer = pointer to palette data (R,G,B) +; Start = index of first color to set +; Count = number of color to set +; Output: +; none +; +mxSetPalette PROC FAR + ARG Count:WORD, \ + Start:WORD, \ + Buffer:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si + + lds si, [Buffer] + mov cx, [Count] + mov ax, [Start] + mov dx, 3C8h ; PEL write address register + out dx, al + inc dx + cld + cli ; Disable interrupts +@@Loop: + lodsb + out dx, al ; Red + lodsb + out dx, al ; Green + lodsb + out dx, al ; Blue + loop @@Loop ; Loop until done + sti ; Enable interrupts + + .pop ds, si + .leave ARG_SIZE +mxSetPalette ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxss.asm b/16/x/mxss.asm new file mode 100755 index 00000000..97df7366 --- /dev/null +++ b/16/x/mxss.asm @@ -0,0 +1,72 @@ +;----------------------------------------------------------- +; +; MXSS.ASM - Split screen function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxSplitScreen + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Splits the screen. +; +; Input: +; Line = scan line at which screen has to be splitted +; Output: +; none +; +mxSplitScreen PROC FAR + ARG Line:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + +; Modify the line compare value: bits 0-7 are in the Line Compare +; register (CRTC #18), bit 8 is in the Overflow Low register (CRTC #7) +; and bit 9 is in the Maximum Row Address register (CRTC #9) + mov ax, [Line] + shl ax, 1 ; Adjust line for mode "X" + mov bh, ah + mov bl, ah + and bx, 0201h + mov cl, 4 + shl bx, cl + shl bh, 1 + mov dx, CRTC +; Write bits 0-7 to line compare register + mov ah, al + mov al, 18h + out dx, ax +; Write bit 8 to overflow register + mov al, 07h + out dx, al + inc dx + in al, dx + dec dx + mov ah, al + and ah, 11101111b + or ah, bl + mov al, 07h + out dx, ax +; Write bit 9 to maximum row address register + mov al, 09h + out dx, al + inc dx + in al, dx + dec dx + mov ah, al + and ah, 10111111b + or ah, bh + mov al, 09h + out dx, ax + + .leave ARG_SIZE +mxSplitScreen ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxtl.asm b/16/x/mxtl.asm new file mode 100755 index 00000000..69900c88 --- /dev/null +++ b/16/x/mxtl.asm @@ -0,0 +1,169 @@ +;----------------------------------------------------------- +; +; MXTL.ASM - Put tile +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxPutTile +PUBLIC mxTransPutTile + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_VideoSegment : WORD +EXTRN mx_BytesPerLine : WORD + +;----------------------------------------------------------- +; +; Copies a "mode-x" tile from memory to screen. +; +; Input: +; Image = pointer to tile +; X, Y = coordinates of destination +; Width = width of image in pixels (Width and 3 = 0) +; Height = height of image in pixels +; Output: +; none +; Note: +; no clipping is performed on tiles! +; +mxPutTile PROC FAR + ARG Height:WORD, \ + Width:WORD, \ + Y:WORD, \ + X:WORD, \ + Image:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si, es, di + + mov ax, [Y] ; Get pixel address + mul [mx_BytesPerLine] + mov di, [X] + .shr di, 2 + add di, ax + mov es, [mx_VideoSegment] + + lds si, [Image] ; Get tile address + .shr [Width], 2 ; Number of bytes per plane + mov cl, BYTE PTR [X] + and cl, 3 + mov ah, 11h ; AH = plane mask + shl ah, cl ; Align mask to first plane + + mov [Y], 4 ; Number of planes + mov bx, [mx_BytesPerLine] + sub bx, [Width] ; Extra bytes per line +@@Loop: + mov al, 02h + mov dx, TS + out dx, ax ; Set write plane + mov [X], di ; Save video offset + mov dx, [Height] +@@Loop2: + mov cx, [Width] ; Number of bytes to move + + shr cx, 1 ; Move line + rep movsw + rcl cx, 1 + rep movsb + + add di, bx ; Move video offset to next line + dec dx ; Done all lines? + jnz @@Loop2 ; No, continue + mov di, [X] ; Restore video offset + rol ah, 1 ; Next plane + adc di, 0 ; Bump video offset if needed + dec [Y] ; Any plane left? + jnz @@Loop ; Yes, keep looping + + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxPutTile ENDP + +;----------------------------------------------------------- +; +; Copies a "mode-x" tile from memory to screen. +; Skips over color 0. +; +; Input: +; Image = pointer to tile +; X, Y = coordinates of destination +; Width = width of image in pixels (Width and 3 = 0) +; Height = height of image in pixels +; Output: +; none +; Note: +; no clipping is performed on tiles! +; +mxTransPutTile PROC FAR + ARG Height:WORD, \ + Width:WORD, \ + Y:WORD, \ + X:WORD, \ + Image:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si, es, di + + mov ax, [Y] ; Get pixel address + mul [mx_BytesPerLine] + mov di, [X] + .shr di, 2 + add di, ax + mov es, [mx_VideoSegment] + + lds si, [Image] ; Get tile address + .shr [Width], 2 ; Number of bytes per plane + mov cl, BYTE PTR [X] + and cl, 3 + mov ah, 11h ; AH = plane mask + shl ah, cl ; Align mask to first plane + + mov [Y], 4 ; Number of planes + mov bx, [mx_BytesPerLine] + sub bx, [Width] ; Extra bytes per line +@@Loop: + mov al, 02h + mov dx, TS + out dx, ax ; Set write plane + mov [X], di ; Save video offset + mov dx, [Height] +@@Loop2: + mov cx, [Width] ; Number of bytes to move + +; Move one line + jcxz @@MoveLineDone +@@MoveLineLoop: + mov al, ds:[si] + test al, al + jz @@MoveLineNext + mov es:[di], al +@@MoveLineNext: + inc si + inc di + dec cx + jnz @@MoveLineLoop +@@MoveLineDone: + + add di, bx ; Move video offset to next line + dec dx ; Done all lines? + jnz @@Loop2 ; No, continue + mov di, [X] ; Restore video offset + rol ah, 1 ; Next plane + adc di, 0 ; Bump video offset if needed + dec [Y] ; Any plane left? + jnz @@Loop ; Yes, keep looping + + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxTransPutTile ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxvs.asm b/16/x/mxvs.asm new file mode 100755 index 00000000..992eabab --- /dev/null +++ b/16/x/mxvs.asm @@ -0,0 +1,110 @@ +;----------------------------------------------------------- +; +; MXVS.ASM - Set/get virtual screen +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxSetVirtualScreen +PUBLIC mxGetVirtualScreen + +EXTRN mxRowAddress : FAR +EXTRN mxSetSysClipRegion : FAR + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD +EXTRN mx_CodeSegment : WORD + +mx_VirtualWidth DW ? ; Virtual screen size +mx_VirtualHeight DW ? + +;----------------------------------------------------------- +; +; Sets the virtual screen. +; +; Input: +; Width = virtual screen width +; Height = virtual screen height +; Output: +; 0 on success, else invalid parameters +; +mxSetVirtualScreen PROC FAR + ARG Height:WORD, \ + Width:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds + +; Set DS to code segment + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, 1 ; Assume an error + cmp [Width], 320 ; Check width + jb @@Exit + push ax ; Save return code + mov dx, 0004h + xor ax, ax ; DX:AX = 256K + div [Width] ; Max height in AX + cmp [Height], ax + pop ax ; Restore return code + ja @@Exit ; Exit if bad heigth + + mov ax, [Width] + and ax, 0FFF8h ; Align to byte + mov [mx_VirtualWidth], ax + shr ax, 1 + shr ax, 1 + mov [mx_BytesPerLine], ax + shr ax, 1 + push ax + call mxRowAddress ; Set row address + mov ax, [Height] + mov [mx_VirtualHeight], ax + + push [Width] + push [Height] + call mxSetSysClipRegion + xor ax, ax + +@@Exit: + .pop ds + .leave ARG_SIZE +mxSetVirtualScreen ENDP + +;----------------------------------------------------------- +; +; Returns the current virtual screen size. +; +; Input: +; Width = pointer to virtual screen width +; Height = pointer to virtual screen height +; Output: +; none +; +mxGetVirtualScreen PROC FAR + ARG Height:DWORD, \ + Width:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si + + mov ax, [mx_VirtualWidth] + lds si, [Width] + mov ds:[si], ax + mov ax, [mx_VirtualHeight] + lds si, [Height] + mov ds:[si], ax + + xor ax, ax + .pop ds, si + .leave ARG_SIZE +mxGetVirtualScreen ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxwd.asm b/16/x/mxwd.asm new file mode 100755 index 00000000..de55208f --- /dev/null +++ b/16/x/mxwd.asm @@ -0,0 +1,28 @@ +;----------------------------------------------------------- +; +; MXWD.ASM - Wait display function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxWaitDisplay + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Waits for display start. +; +mxWaitDisplay PROC FAR + mov dx, STATUS +@@1: in al, dx + test al, 08h + jnz @@1 + ret +mxWaitDisplay ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxwm.asm b/16/x/mxwm.asm new file mode 100755 index 00000000..06158859 --- /dev/null +++ b/16/x/mxwm.asm @@ -0,0 +1,39 @@ +;----------------------------------------------------------- +; +; MXWM.ASM - Set write mode function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxWriteMode + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Sets the write mode. +; +; Input: +; Mode = write mode (0,1,2,3) +; Output: +; none +; +mxWriteMode PROC FAR + ARG Mode:BYTE:2 = ARG_SIZE + .enter 0 + + mov dx, GDC + mov ah, [Mode] + and ah, 00000011b + or ah, 01000000b + mov al, 05h + out dx, ax + + .leave ARG_SIZE +mxWriteMode ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxwp.asm b/16/x/mxwp.asm new file mode 100755 index 00000000..19ca99d0 --- /dev/null +++ b/16/x/mxwp.asm @@ -0,0 +1,62 @@ +;----------------------------------------------------------- +; +; MXWP.ASM - Set write/read plane functions +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxWritePlane +PUBLIC mxReadPlane + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Sets the write plane(s). +; +; Input: +; Plane = write plane(s) to set (bit 0 enables plane 0, +; bit 1 enables plane 1 and so on, different planes +; may be selected at the same time) +; Output: +; none +; +mxWritePlane PROC FAR + ARG Plane:BYTE:2 = ARG_SIZE + .enter 0 + + mov ah, [Plane] + and ah, 00001111b ; Mask off unused bits + mov al, 02h + mov dx, TS + out dx, ax + + .leave ARG_SIZE +mxWritePlane ENDP + +;----------------------------------------------------------- +; +; Sets the read plane. +; +; Input: +; Plane = read plane to set (0,1,2,3) +; Output: +; none +; +mxReadPlane PROC FAR + ARG Plane:BYTE:2 = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + mov al, 04h + mov ah, [Plane] + and ah, 0000011b ; Mask off unused bits + mov dx, GDC + out dx, ax + .leave ARG_SIZE +mxReadPlane ENDP + +MX_TEXT ENDS +END diff --git a/16/x/mxwr.asm b/16/x/mxwr.asm new file mode 100755 index 00000000..bd29fe59 --- /dev/null +++ b/16/x/mxwr.asm @@ -0,0 +1,28 @@ +;----------------------------------------------------------- +; +; MXWR.ASM - Wait vertical retrace function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxWaitRetrace + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Waits for vertical retrace start. +; +mxWaitRetrace PROC FAR + mov dx, STATUS +@@1: in al,dx + test al, 08h + jz @@1 + ret +mxWaitRetrace ENDP + +MX_TEXT ENDS +END diff --git a/16/x/readme.txt b/16/x/readme.txt new file mode 100755 index 00000000..306e8b9a --- /dev/null +++ b/16/x/readme.txt @@ -0,0 +1,8 @@ +ModeX - A graphical library for DOS programs +Copyright (c) 1993-1994 Alessandro Scotti +http://www.ascotti.org/ + +Please look at the above site in the "Art of..." and +then in the "Old programs" section for more information. + + diff --git a/16/x_/MODEX.BAK b/16/x_/MODEX.BAK new file mode 100755 index 0000000000000000000000000000000000000000..923d02e969692cfc167d30edfb4314432c257f1a GIT binary patch literal 59392 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 J`ak;Le*p|8pOOFo literal 0 HcmV?d00001 diff --git a/16/x_/default.fnt b/16/x_/default.fnt new file mode 100755 index 00000000..12eb22cb --- /dev/null +++ b/16/x_/default.fnt @@ -0,0 +1,260 @@ +; +; MODEX library default font +; Copyright (c) 1993-1994 by Alessandro Scotti +; + DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; #0 + DB 07Eh, 081h, 0A5h, 081h, 0A5h, 099h, 081h, 07Eh ; #1 + DB 07Eh, 0FFh, 0DBh, 0FFh, 0DBh, 0E7h, 0FFh, 07Eh ; #2 + DB 06Ch, 0FEh, 0FEh, 0FEh, 07Ch, 038h, 010h, 000h ; #3 + DB 010h, 038h, 07Ch, 0FEh, 07Ch, 038h, 010h, 000h ; #4 + DB 010h, 038h, 010h, 054h, 0FEh, 054h, 010h, 0FEh ; #5 + DB 010h, 038h, 07Ch, 0FEh, 0FEh, 07Ch, 010h, 0FEh ; #6 + DB 000h, 018h, 03Ch, 07Eh, 07Eh, 03Ch, 018h, 000h ; #7 + DB 0FFh, 0E7h, 0C3h, 081h, 081h, 0C3h, 0E7h, 0FFh ; #8 + DB 000h, 03Ch, 066h, 042h, 042h, 066h, 03Ch, 000h ; #9 + DB 0FFh, 0C3h, 099h, 0BDh, 0BDh, 099h, 0C3h, 0FFh ; #10 + DB 007h, 003h, 005h, 078h, 084h, 084h, 084h, 078h ; #11 + DB 07Ch, 082h, 082h, 082h, 07Ch, 010h, 038h, 010h ; #12 + DB 01Ch, 010h, 01Ch, 010h, 010h, 010h, 030h, 030h ; #13 + DB 03Eh, 022h, 03Eh, 022h, 022h, 026h, 066h, 060h ; #14 + DB 099h, 05Ah, 03Ch, 0E7h, 0E7h, 03Ch, 05Ah, 099h ; #15 + DB 000h, 010h, 030h, 070h, 0F0h, 070h, 030h, 010h ; #16 + DB 000h, 080h, 0C0h, 0E0h, 0F0h, 0E0h, 0C0h, 080h ; #17 + DB 010h, 038h, 054h, 010h, 010h, 054h, 038h, 010h ; #18 + DB 048h, 048h, 048h, 048h, 048h, 000h, 048h, 000h ; #19 + DB 07Eh, 092h, 092h, 072h, 012h, 012h, 012h, 000h ; #20 + DB 03Ch, 022h, 018h, 024h, 024h, 018h, 044h, 03Ch ; #21 + DB 000h, 000h, 000h, 000h, 000h, 03Eh, 03Eh, 000h ; #22 + DB 038h, 054h, 010h, 010h, 010h, 054h, 038h, 0FEh ; #23 + DB 000h, 010h, 038h, 054h, 010h, 010h, 010h, 000h ; #24 + DB 000h, 010h, 010h, 010h, 054h, 038h, 010h, 000h ; #25 + DB 000h, 008h, 004h, 0FEh, 004h, 008h, 000h, 000h ; #26 + DB 000h, 020h, 040h, 0FEh, 040h, 020h, 000h, 000h ; #27 + DB 000h, 000h, 080h, 080h, 080h, 0FCh, 000h, 000h ; #28 + DB 000h, 024h, 042h, 0FFh, 042h, 024h, 000h, 000h ; #29 + DB 000h, 000h, 010h, 038h, 07Ch, 0FEh, 000h, 000h ; #30 + DB 000h, 000h, 0FEh, 07Ch, 038h, 010h, 000h, 000h ; #31 + DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; + DB 010h, 010h, 010h, 010h, 010h, 000h, 010h, 000h ; ! + DB 000h, 024h, 024h, 000h, 000h, 000h, 000h, 000h ; " + DB 024h, 024h, 07Eh, 024h, 07Eh, 024h, 024h, 000h ; # + DB 038h, 054h, 050h, 038h, 014h, 054h, 038h, 010h ; $ + DB 000h, 002h, 044h, 008h, 010h, 020h, 042h, 000h ; % + DB 038h, 044h, 038h, 060h, 094h, 088h, 074h, 000h ; & + DB 020h, 020h, 040h, 000h, 000h, 000h, 000h, 000h ; ' + DB 010h, 020h, 040h, 040h, 040h, 020h, 010h, 000h ; ( + DB 040h, 020h, 010h, 010h, 010h, 020h, 040h, 000h ; ) + DB 000h, 024h, 018h, 07Eh, 018h, 024h, 000h, 000h ; * + DB 000h, 010h, 010h, 07Ch, 010h, 010h, 000h, 000h ; + + DB 000h, 000h, 000h, 000h, 000h, 010h, 010h, 020h ; , + DB 000h, 000h, 000h, 0FCh, 000h, 000h, 000h, 000h ; - + DB 000h, 000h, 000h, 000h, 000h, 000h, 010h, 000h ; . + DB 000h, 004h, 008h, 010h, 020h, 040h, 080h, 000h ; / + DB 07Ch, 0C6h, 08Ah, 092h, 0A2h, 0C6h, 07Ch, 000h ; 0 + DB 010h, 030h, 010h, 010h, 010h, 010h, 038h, 000h ; 1 + DB 078h, 084h, 004h, 018h, 060h, 080h, 0FCh, 000h ; 2 + DB 078h, 084h, 004h, 038h, 004h, 084h, 078h, 000h ; 3 + DB 01Ch, 024h, 044h, 084h, 0FEh, 004h, 00Eh, 000h ; 4 + DB 0FCh, 080h, 0F8h, 004h, 004h, 084h, 078h, 000h ; 5 + DB 078h, 084h, 080h, 0F8h, 084h, 084h, 078h, 000h ; 6 + DB 0FCh, 004h, 004h, 008h, 010h, 020h, 020h, 000h ; 7 + DB 078h, 084h, 084h, 078h, 084h, 084h, 078h, 000h ; 8 + DB 078h, 084h, 084h, 07Ch, 004h, 084h, 078h, 000h ; 9 + DB 000h, 000h, 010h, 000h, 000h, 000h, 010h, 000h ; : + DB 000h, 000h, 010h, 000h, 000h, 010h, 010h, 020h ; ; + DB 008h, 010h, 020h, 040h, 020h, 010h, 008h, 000h ; < + DB 000h, 000h, 0FCh, 000h, 000h, 0FCh, 000h, 000h ; = + DB 040h, 020h, 010h, 008h, 010h, 020h, 040h, 000h ; > + DB 078h, 084h, 004h, 008h, 010h, 000h, 010h, 000h ; ? + DB 07Ch, 082h, 0BAh, 0A6h, 0BEh, 080h, 07Ch, 000h ; @ + DB 078h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h ; A + DB 0F8h, 084h, 084h, 0F8h, 084h, 084h, 0F8h, 000h ; B + DB 078h, 084h, 080h, 080h, 080h, 084h, 078h, 000h ; C + DB 0F0h, 088h, 084h, 084h, 084h, 088h, 0F0h, 000h ; D + DB 0FCh, 080h, 080h, 0F0h, 080h, 080h, 0FCh, 000h ; E + DB 0FCh, 080h, 080h, 0F0h, 080h, 080h, 080h, 000h ; F + DB 078h, 084h, 080h, 09Ch, 084h, 084h, 078h, 000h ; G + DB 084h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h ; H + DB 038h, 010h, 010h, 010h, 010h, 010h, 038h, 000h ; I + DB 01Ch, 008h, 008h, 008h, 088h, 088h, 070h, 000h ; J + DB 084h, 088h, 090h, 0E0h, 090h, 088h, 084h, 000h ; K + DB 080h, 080h, 080h, 080h, 080h, 080h, 0FCh, 000h ; L + DB 0C6h, 0AAh, 092h, 082h, 082h, 082h, 082h, 000h ; M + DB 082h, 0C2h, 0A2h, 092h, 08Ah, 086h, 082h, 000h ; N + DB 078h, 084h, 084h, 084h, 084h, 084h, 078h, 000h ; O + DB 0F8h, 084h, 084h, 0F8h, 080h, 080h, 080h, 000h ; P + DB 078h, 084h, 084h, 084h, 094h, 088h, 076h, 000h ; Q + DB 0F8h, 084h, 084h, 0F8h, 090h, 088h, 084h, 000h ; R + DB 078h, 084h, 080h, 078h, 004h, 084h, 078h, 000h ; S + DB 0FEh, 010h, 010h, 010h, 010h, 010h, 010h, 000h ; T + DB 084h, 084h, 084h, 084h, 084h, 084h, 078h, 000h ; U + DB 084h, 084h, 084h, 084h, 084h, 048h, 030h, 000h ; V + DB 082h, 082h, 082h, 082h, 092h, 0AAh, 0C6h, 000h ; W + DB 082h, 044h, 028h, 010h, 028h, 044h, 082h, 000h ; X + DB 044h, 044h, 044h, 038h, 010h, 010h, 010h, 000h ; Y + DB 0FEh, 004h, 008h, 010h, 020h, 040h, 0FEh, 000h ; Z + DB 078h, 040h, 040h, 040h, 040h, 040h, 078h, 000h ; [ + DB 000h, 080h, 040h, 020h, 010h, 008h, 004h, 000h ; \ + DB 078h, 008h, 008h, 008h, 008h, 008h, 078h, 000h ; ] + DB 010h, 028h, 044h, 082h, 000h, 000h, 000h, 000h ; ^ + DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0FFh ; _ + DB 020h, 020h, 010h, 000h, 000h, 000h, 000h, 000h ; ` + DB 000h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; a + DB 000h, 040h, 040h, 078h, 044h, 044h, 078h, 000h ; b + DB 000h, 000h, 03Ch, 040h, 040h, 040h, 03Ch, 000h ; c + DB 000h, 004h, 004h, 03Ch, 044h, 044h, 03Ch, 000h ; d + DB 000h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; e + DB 000h, 00Ch, 010h, 03Ch, 010h, 010h, 010h, 000h ; f + DB 000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 038h ; g + DB 000h, 040h, 040h, 078h, 044h, 044h, 044h, 000h ; h + DB 000h, 010h, 000h, 010h, 010h, 010h, 010h, 000h ; i + DB 000h, 004h, 000h, 004h, 004h, 004h, 044h, 038h ; j + DB 000h, 040h, 040h, 050h, 060h, 050h, 048h, 000h ; k + DB 000h, 030h, 010h, 010h, 010h, 010h, 010h, 000h ; l + DB 000h, 000h, 068h, 054h, 054h, 044h, 044h, 000h ; m + DB 000h, 000h, 078h, 044h, 044h, 044h, 044h, 000h ; n + DB 000h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; o + DB 000h, 000h, 078h, 044h, 044h, 078h, 040h, 040h ; p + DB 000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 004h ; q + DB 000h, 000h, 05Ch, 060h, 040h, 040h, 040h, 000h ; r + DB 000h, 000h, 038h, 040h, 07Ch, 004h, 07Ch, 000h ; s + DB 000h, 010h, 038h, 010h, 010h, 010h, 018h, 000h ; t + DB 000h, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; u + DB 000h, 000h, 044h, 044h, 044h, 028h, 010h, 000h ; v + DB 000h, 000h, 044h, 044h, 054h, 054h, 06Ch, 000h ; w + DB 000h, 000h, 044h, 028h, 010h, 028h, 044h, 000h ; x + DB 000h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch ; y + DB 000h, 000h, 07Ch, 004h, 038h, 040h, 07Ch, 000h ; z + DB 000h, 008h, 010h, 010h, 030h, 010h, 010h, 008h ; { + DB 000h, 010h, 010h, 010h, 000h, 010h, 010h, 010h ; | + DB 000h, 020h, 010h, 010h, 018h, 010h, 010h, 020h ; } + DB 064h, 098h, 000h, 000h, 000h, 000h, 000h, 000h ; ~ + DB 000h, 010h, 028h, 044h, 082h, 082h, 0FEh, 000h ;  + DB 07Ch, 080h, 080h, 080h, 080h, 07Ch, 004h, 07Ch ; #128 + DB 000h, 028h, 000h, 044h, 044h, 044h, 038h, 000h ; #129 + DB 03Ch, 000h, 07Ch, 044h, 07Ch, 040h, 07Ch, 000h ; #130 + DB 07Eh, 081h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #131 + DB 024h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #132 + DB 078h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #133 + DB 018h, 018h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #134 + DB 000h, 000h, 078h, 080h, 080h, 078h, 008h, 038h ; #135 + DB 07Ch, 082h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #136 + DB 048h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #137 + DB 078h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #138 + DB 000h, 028h, 000h, 010h, 010h, 010h, 010h, 000h ; #139 + DB 010h, 028h, 000h, 010h, 010h, 010h, 010h, 000h ; #140 + DB 000h, 030h, 000h, 010h, 010h, 010h, 010h, 000h ; #141 + DB 048h, 000h, 078h, 084h, 0FCh, 084h, 084h, 000h ; #142 + DB 030h, 030h, 078h, 084h, 0FCh, 084h, 084h, 000h ; #143 + DB 038h, 000h, 0FCh, 080h, 0F0h, 080h, 0FCh, 000h ; #144 + DB 000h, 000h, 07Eh, 008h, 07Eh, 048h, 07Eh, 000h ; #145 + DB 07Eh, 090h, 090h, 0FCh, 090h, 090h, 09Eh, 000h ; #146 + DB 07Ch, 082h, 038h, 044h, 044h, 044h, 038h, 000h ; #147 + DB 028h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #148 + DB 070h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #149 + DB 038h, 044h, 000h, 044h, 044h, 044h, 038h, 000h ; #150 + DB 070h, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; #151 + DB 028h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch ; #152 + DB 048h, 000h, 078h, 084h, 084h, 084h, 078h, 000h ; #153 + DB 048h, 000h, 084h, 084h, 084h, 084h, 078h, 000h ; #154 + DB 000h, 010h, 038h, 040h, 040h, 040h, 038h, 010h ; #155 + DB 038h, 044h, 040h, 0E0h, 040h, 040h, 082h, 0FCh ; #156 + DB 044h, 07Ch, 010h, 07Ch, 010h, 07Ch, 010h, 000h ; #157 + DB 0F0h, 088h, 08Ah, 0F7h, 082h, 082h, 082h, 000h ; #158 + DB 00Ch, 012h, 010h, 018h, 030h, 010h, 090h, 060h ; #159 + DB 03Ch, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #160 + DB 000h, 018h, 000h, 010h, 010h, 010h, 010h, 000h ; #161 + DB 01Ch, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #162 + DB 01Ch, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; #163 + DB 07Ch, 000h, 078h, 044h, 044h, 044h, 044h, 000h ; #164 + DB 07Ch, 000h, 044h, 064h, 054h, 04Ch, 044h, 000h ; #165 + DB 018h, 024h, 024h, 01Eh, 000h, 03Eh, 000h, 000h ; #166 + DB 01Ch, 022h, 022h, 01Ch, 000h, 03Eh, 000h, 000h ; #167 + DB 010h, 000h, 010h, 020h, 040h, 042h, 03Ch, 000h ; #168 + DB 000h, 000h, 000h, 0FCh, 080h, 080h, 000h, 000h ; #169 + DB 000h, 000h, 000h, 0FCh, 004h, 004h, 000h, 000h ; #170 + DB 040h, 044h, 048h, 057h, 021h, 047h, 004h, 007h ; #171 + DB 040h, 044h, 048h, 052h, 026h, 04Ah, 01Fh, 002h ; #172 + DB 010h, 000h, 010h, 010h, 010h, 010h, 010h, 000h ; #173 + DB 000h, 024h, 048h, 090h, 048h, 024h, 000h, 000h ; #174 + DB 000h, 048h, 024h, 012h, 024h, 048h, 000h, 000h ; #175 + DB 022h, 088h, 022h, 088h, 022h, 088h, 022h, 088h ; #176 + DB 055h, 0AAh, 055h, 0AAh, 055h, 0AAh, 055h, 0AAh ; #177 + DB 0DBh, 077h, 0DBh, 0EEh, 0DBh, 077h, 0DBh, 0EEh ; #178 + DB 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h ; #179 + DB 018h, 018h, 018h, 018h, 0F8h, 018h, 018h, 018h ; #180 + DB 018h, 018h, 0F8h, 018h, 0F8h, 018h, 018h, 018h ; #181 + DB 036h, 036h, 036h, 036h, 0F6h, 036h, 036h, 036h ; #182 + DB 000h, 000h, 000h, 000h, 0FEh, 036h, 036h, 036h ; #183 + DB 000h, 000h, 0F8h, 018h, 0F8h, 018h, 018h, 018h ; #184 + DB 036h, 036h, 0F6h, 006h, 0F6h, 036h, 036h, 036h ; #185 + DB 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h ; #186 + DB 000h, 000h, 0FEh, 006h, 0F6h, 036h, 036h, 036h ; #187 + DB 036h, 036h, 0F6h, 006h, 0FEh, 000h, 000h, 000h ; #188 + DB 036h, 036h, 036h, 036h, 0FEh, 000h, 000h, 000h ; #189 + DB 018h, 018h, 0F8h, 018h, 0F8h, 000h, 000h, 000h ; #190 + DB 000h, 000h, 000h, 000h, 0F8h, 018h, 018h, 018h ; #191 + DB 018h, 018h, 018h, 018h, 01Fh, 000h, 000h, 000h ; #192 + DB 018h, 018h, 018h, 018h, 0FFh, 000h, 000h, 000h ; #193 + DB 000h, 000h, 000h, 000h, 0FFh, 018h, 018h, 018h ; #194 + DB 018h, 018h, 018h, 018h, 01Fh, 018h, 018h, 018h ; #195 + DB 000h, 000h, 000h, 000h, 0FFh, 000h, 000h, 000h ; #196 + DB 018h, 018h, 018h, 018h, 0FFh, 018h, 018h, 018h ; #197 + DB 018h, 018h, 01Fh, 018h, 01Fh, 018h, 018h, 018h ; #198 + DB 036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h ; #199 + DB 036h, 036h, 037h, 030h, 03Fh, 000h, 000h, 000h ; #200 + DB 000h, 000h, 03Fh, 030h, 037h, 036h, 036h, 036h ; #201 + DB 036h, 036h, 0F7h, 000h, 0FFh, 000h, 000h, 000h ; #202 + DB 000h, 000h, 0FFh, 000h, 0F7h, 036h, 036h, 036h ; #203 + DB 036h, 036h, 037h, 030h, 037h, 036h, 036h, 036h ; #204 + DB 000h, 000h, 0FFh, 000h, 0FFh, 000h, 000h, 000h ; #205 + DB 036h, 036h, 0F7h, 000h, 0F7h, 036h, 036h, 036h ; #206 + DB 018h, 018h, 0FFh, 000h, 0FFh, 000h, 000h, 000h ; #207 + DB 036h, 036h, 036h, 036h, 0FFh, 000h, 000h, 000h ; #208 + DB 000h, 000h, 0FFh, 000h, 0FFh, 018h, 018h, 018h ; #209 + DB 000h, 000h, 000h, 000h, 0FFh, 036h, 036h, 036h ; #210 + DB 036h, 036h, 036h, 036h, 03Fh, 000h, 000h, 000h ; #211 + DB 018h, 018h, 01Fh, 018h, 01Fh, 000h, 000h, 000h ; #212 + DB 000h, 000h, 01Fh, 018h, 01Fh, 018h, 018h, 018h ; #213 + DB 000h, 000h, 000h, 000h, 03Fh, 036h, 036h, 036h ; #214 + DB 036h, 036h, 036h, 036h, 0FFh, 036h, 036h, 036h ; #215 + DB 018h, 018h, 0FFh, 018h, 0FFh, 018h, 018h, 018h ; #216 + DB 018h, 018h, 018h, 018h, 0F8h, 000h, 000h, 000h ; #217 + DB 000h, 000h, 000h, 000h, 01Fh, 018h, 018h, 018h ; #218 + DB 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh ; #219 + DB 000h, 000h, 000h, 000h, 0FFh, 0FFh, 0FFh, 0FFh ; #220 + DB 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h ; #221 + DB 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh ; #222 + DB 0FFh, 0FFh, 0FFh, 0FFh, 000h, 000h, 000h, 000h ; #223 + DB 000h, 000h, 062h, 094h, 088h, 094h, 062h, 000h ; #224 + DB 000h, 0F0h, 088h, 0F0h, 088h, 088h, 0F0h, 080h ; #225 + DB 000h, 0F8h, 088h, 080h, 080h, 080h, 080h, 000h ; #226 + DB 000h, 0FCh, 048h, 048h, 048h, 048h, 048h, 000h ; #227 + DB 0FCh, 084h, 040h, 020h, 040h, 084h, 0FCh, 000h ; #228 + DB 03Ch, 040h, 038h, 044h, 044h, 044h, 038h, 000h ; #229 + DB 000h, 000h, 044h, 044h, 044h, 078h, 040h, 040h ; #230 + DB 000h, 036h, 048h, 008h, 008h, 008h, 008h, 000h ; #231 + DB 038h, 010h, 038h, 044h, 044h, 038h, 010h, 038h ; #232 + DB 078h, 084h, 084h, 0FCh, 084h, 084h, 078h, 000h ; #233 + DB 078h, 084h, 084h, 084h, 048h, 048h, 0CCh, 000h ; #234 + DB 078h, 004h, 038h, 044h, 044h, 044h, 038h, 000h ; #235 + DB 000h, 000h, 06Ch, 092h, 092h, 06Ch, 000h, 000h ; #236 + DB 000h, 000h, 03Ah, 044h, 05Ah, 022h, 05Ch, 000h ; #237 + DB 018h, 020h, 040h, 078h, 040h, 020h, 018h, 000h ; #238 + DB 078h, 084h, 084h, 084h, 084h, 084h, 084h, 000h ; #239 + DB 000h, 0FCh, 000h, 0FCh, 000h, 0FCh, 000h, 000h ; #240 + DB 020h, 020h, 0F8h, 020h, 020h, 000h, 0F8h, 000h ; #241 + DB 020h, 010h, 008h, 010h, 020h, 000h, 07Ch, 000h ; #242 + DB 008h, 010h, 020h, 010h, 008h, 000h, 07Ch, 000h ; #243 + DB 00Ch, 012h, 010h, 010h, 010h, 010h, 010h, 010h ; #244 + DB 010h, 010h, 010h, 010h, 010h, 010h, 090h, 060h ; #245 + DB 000h, 010h, 000h, 07Ch, 000h, 010h, 000h, 000h ; #246 + DB 000h, 032h, 04Ch, 000h, 032h, 04Ch, 000h, 000h ; #247 + DB 038h, 044h, 044h, 038h, 000h, 000h, 000h, 000h ; #248 + DB 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h ; #249 + DB 000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h ; #250 + DB 00Eh, 008h, 008h, 008h, 048h, 028h, 018h, 008h ; #251 + DB 038h, 024h, 024h, 024h, 024h, 000h, 000h, 000h ; #252 + DB 03Ch, 004h, 03Ch, 020h, 03Ch, 000h, 000h, 000h ; #253 + DB 000h, 000h, 03Ch, 03Ch, 03Ch, 03Ch, 000h, 000h ; #254 + DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; #255 diff --git a/16/x_/makefile b/16/x_/makefile new file mode 100755 index 00000000..eb7bf624 --- /dev/null +++ b/16/x_/makefile @@ -0,0 +1,82 @@ +# +# MODEX library makefile (for Borland MAKE) +# Copyright (c) 1993,1994 by Alessandro Scotti +# +LIBINCS = MODEX.DEF + +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 + +# +# ASM compiler +# +ASMC = tasm +ASMO = /m5 /zi +#/p + +# +# PAS compiler +# +PASC = tpc +PASO = /m -$D- -$L- -$S- + +# +# LIB maker, uses response file +# +LIBC = tlib + +.asm.obj: + $(ASMC) $(ASMO) $< + +target: modex.lib +# modex.tpu modex.tpp + +#modex.tpu: $(LIBOBJS) modex.pas +# $(PASC) $(PASO) modex +# copy modex.tpu .. +# copy modex.pas .. + +#modex.tpp: $(LIBOBJS) modex.pas +# $(PASC) /cp $(PASO) modex +# copy modex.tpp .. + +modex.lib: modex.lbr $(LIBOBJS) + $(LIBC) modex.lib @modex.lbr + +$(LIBOBJS): modex.def diff --git a/16/x_/modex.def b/16/x_/modex.def new file mode 100755 index 00000000..9c6b75b5 --- /dev/null +++ b/16/x_/modex.def @@ -0,0 +1,154 @@ +;------------------------------------------------------------ +; +; MODEX.DEF - Include file +; Copyright (c) 1993-1994 by Alessandro Scotti +; +JUMPS +LOCALS + +TRUE EQU 1 ; Boolean constants +FALSE EQU 0 + +USE286 = FALSE ; TRUE enables 80286 instructions +USE386 = FALSE ; TRUE enables 80386 (and 80286) instructions + +IF USE286 EQ TRUE + P286 +ENDIF + +IF USE386 EQ TRUE + P386 + USE286 = TRUE +ENDIF + +MXVERSION EQU 0128h ; Library version (1.40) + +;------------------------------------------------------------ +; +; VGA definitions +; +MISC EQU 3C2h ; Miscellaneous output +TS EQU 3C4h ; Timing Sequencer index register +GDC EQU 3CEh ; Graphics Data Controller index register +CRTC EQU 3D4h ; CRTC index register +STATUS EQU 3DAh ; Input Status register one + +;------------------------------------------------------------ +; +; Raster operators +; +OP_SET EQU 0 +OP_MOVE EQU 0 ; Same as OP_SET +OP_AND EQU 1 +OP_OR EQU 2 +OP_XOR EQU 3 +OP_TRANS EQU 4 +OP_ADD EQU 5 ; Must be last op + +;------------------------------------------------------------ +; +; Polygon fill functions +; +POLYSCANBUFSIZE EQU 4*1024 + +;------------------------------------------------------------ +; Macro to push registers, variables or flags onto the stack +; Usage: .push "loc16"[,"loc16"...] +; where "loc16" is a 16-bit register, a word-sized variable or the +; keyword "FLAGS". +; Exmpl: .push ax, flags, var1 +; .pop ax, flags, var1 +; +.push MACRO r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10 + IFNB + .ERROR <.PUSH has more than 10 arguments> + ENDIF + IRP $reg, + IFB <$reg> ;; Is argument blank? + EXITM ;; Yes, exit + ELSEIFIDNI <$reg>, ;; Is argument the keyword "FLAGS"? + pushf ;; Yes, push flags + ELSE + push $reg ;; Push argument + ENDIF + ENDM +ENDM + +;------------------------------------------------------------ +; Macro to pop registers, variables or flags from the stack +; Usage: .pop "loc16"[,"loc16"...] +; where "loc16" is a 16-bit register, a word-sized variable or the +; keyword "FLAGS". +; Exmpl: .push ax, flags, var1 +; .pop ax, flags, var1 +; +.pop MACRO r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10 + IFNB + .ERROR <.POP has more than 10 arguments> + ENDIF + IRP $reg, + IFNB <$reg> ;; Is argument non-blank? + IFIDNI <$reg>, ;; Yes, is it the keyword "FLAGS"? + popf ;; Yes, pop flags + ELSE + pop $reg ;; Pop argument + ENDIF + ENDIF + ENDM +ENDM + +;------------------------------------------------------------ +; +.enter MACRO localsize + IF USE286 EQ TRUE + enter localsize, 0 + ELSE + push bp + mov bp, sp + sub sp, localsize + ENDIF +ENDM + +;------------------------------------------------------------ +; +.leave MACRO argsize + IF USE286 EQ TRUE + leave + ELSE + mov sp, bp + pop bp + ENDIF + IFNB + ret argsize + ELSE + ret + ENDIF +ENDM + +;------------------------------------------------------------ +; +.shr MACRO arg, count + IF USE286 EQ TRUE + shr arg, count + ELSE + $temp = count + WHILE $temp GT 0 + shr arg, 1 + $temp = $temp-1 + ENDM + ENDIF +ENDM + +;------------------------------------------------------------ +; +.shl MACRO arg, count + IF USE286 EQ TRUE + shl arg, count + ELSE + $temp = count + WHILE $temp GT 0 + shl arg, 1 + $temp = $temp-1 + ENDM + ENDIF +ENDM diff --git a/16/x_/modex.h b/16/x_/modex.h new file mode 100755 index 00000000..2c1f1ebe --- /dev/null +++ b/16/x_/modex.h @@ -0,0 +1,153 @@ +/* + MODEX.H - C/C++ include file for the MODEX library + Copyright (c) 1994 Alessandro Scotti +*/ + +#ifndef _MODEX_H_ // Avoid nested inclusions +#define _MODEX_H_ + +// +// Video modes +// +#define MX_TEXT 0 // 80x25 text +#define MX_320x175 1 // 320x175x256 +#define MX_320x200 2 // 320x200x256, 4 pages, aspect 6:5 +#define MX_320x240 3 // 320x240x256, 3 pages, aspect 1:1 +#define MX_320x350 4 // 320x350x256 +#define MX_320x400 5 // 320x400x256, 2 pages +#define MX_320x480 6 // 320x480x256, 1 page +#define MX_360x175 7 // 360x175x256 +#define MX_360x200 8 // 360x200x256, 3 pages +#define MX_360x240 9 // 360x240x256, 2 pages +#define MX_360x350 10 // 360x350x256 +#define MX_360x400 11 // 360x400x256, 1 page +#define MX_360x480 12 // 360x480x256, 1 page +#define MX_400x600 13 // 400x600x256, 1 page + +// +// Fade effects +// +#define MX_FADEIN 0 +#define MX_FADEOUT 1 + +// +// Raster ops +// +#define OP_SET 0 // No operator +#define OP_AND 1 // And +#define OP_OR 2 // Or +#define OP_XOR 3 // Xor +#define OP_TRANS 4 // Transparent +#define OP_ADD 5 // Additive +#define OP_MOVE 0 // Alias for OP_SET + +// +// Temporary definitions +// +#define MXBYTE unsigned char +#define MXBOOL short int +#define MXSINT short int +#define MXUINT unsigned short int +#define MXAPI far pascal +#define MXPTR void far * + +// Functions + +#ifdef __cplusplus // Avoid C++ name mangling +extern "C" { +#endif + +// +// Initialization +// +MXSINT MXAPI mxInit( void ); // Returns 0 if successful +void MXAPI mxTerm( void ); +MXUINT MXAPI mxGetVersion( void ); +// +// Mode setting +// +void MXAPI mxChangeMode( MXUINT mode ); +void MXAPI mxSetMode( MXUINT mode ); +void MXAPI mxGetAspect( MXUINT far *aspectx, MXUINT far *aspecty ); +void MXAPI mxGetScreenSize( MXUINT far *width, MXUINT far *height ); +// +// Hardware support +// +void MXAPI mxWriteMode( MXBYTE wm ); +void MXAPI mxSplitScreen( MXUINT line ); +void MXAPI mxStartAddress( MXUINT sa ); +void MXAPI mxStartLine( MXUINT sl ); +void MXAPI mxWaitDisplay( void ); +void MXAPI mxWaitRetrace( void ); +void MXAPI mxWritePlane( MXBYTE wp ); +void MXAPI mxReadPlane( MXBYTE rp ); +void MXAPI mxRowAddress( MXBYTE ra ); +// +// Virtual screen +// +void MXAPI mxGetVirtualScreen( MXUINT far *width, MXUINT far *height ); +void MXAPI mxSetVirtualScreen( MXUINT width, MXUINT height ); +void MXAPI mxPan( MXUINT x, MXUINT y ); +// +// Clipping +// +MXBOOL MXAPI mxGetClip( void ); +MXBOOL MXAPI mxGetClipRegion( MXSINT far *x, MXSINT far *y, MXSINT far *w, MXSINT far *h ); +MXBOOL MXAPI mxSetClip( MXBOOL ); +void MXAPI mxSetClipRegion( MXUINT x, MXUINT y, MXUINT width, MXUINT height ); +// +// Graphics +// +void MXAPI mxBitBlt( MXSINT sx, MXSINT sy, MXUINT width, MXUINT height, MXSINT dx, MXSINT dy ); +void MXAPI mxFillBox( MXSINT x, MXSINT y, MXUINT width, MXUINT height, MXUINT color, MXUINT op ); +MXBYTE MXAPI mxGetPixel( MXSINT x, MXSINT y ); +void MXAPI mxPutPixel( MXSINT x, MXSINT y, MXBYTE color ); +void MXAPI mxLine( MXSINT x1, MXSINT y1, MXSINT x2, MXSINT y2, MXUINT color, MXUINT op ); +void MXAPI mxGetImage( MXPTR img, MXSINT x, MXSINT y, MXUINT width, MXUINT height ); +void MXAPI mxPutImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT op ); +void MXAPI mxPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT width, MXUINT height ); +void MXAPI mxTransPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT w, MXUINT h ); +void MXAPI mxCircle( MXSINT x, MXSINT y, MXUINT radius, MXBYTE color ); +void MXAPI mxStretchImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT neww, MXUINT newh, MXUINT op ); +// +// Palette +// +void MXAPI mxColorToGray( MXPTR source, MXPTR dest, MXUINT count ); +void MXAPI mxGammaCorrect( MXPTR source, MXPTR dest, MXUINT count ); +void MXAPI mxGetColor( MXUINT index, MXSINT far *r, MXSINT far *g, MXSINT far *b ); +void MXAPI mxSetColor( MXUINT index, MXSINT red, MXSINT green, MXSINT blue ); +void MXAPI mxGetPalette( MXPTR palette, MXUINT index, MXUINT count ); +void MXAPI mxSetPalette( MXPTR palette, MXUINT index, MXUINT count ); +void MXAPI mxFadePalette( MXPTR, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT ); +void MXAPI mxRotatePalette( MXPTR palette, MXUINT count, MXSINT step ); +// +// Text +// +MXSINT MXAPI mxSetFont( MXPTR font, MXUINT charwidth, MXUINT charheight ); +void MXAPI mxSetTextColor( MXUINT color, MXUINT op ); +void MXAPI mxGetTextStep( MXSINT far *deltax, MXSINT far *deltay ); +void MXAPI mxSetTextStep( MXSINT deltax, MXSINT deltay ); +void MXAPI mxOutChar( MXSINT x, MXSINT y, char c ); +void MXAPI mxOutText( MXSINT x, MXSINT y, char far *sz ); +// +// Convex polygons +// +void MXAPI mxFillPoly( MXUINT, MXPTR, MXPTR, MXUINT, MXUINT ); +void MXAPI mxGouraudPoly( MXUINT, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT ); +void MXAPI mxTexturePoly( MXUINT, MXPTR, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT ); + +#ifdef __cplusplus +} +#endif + +// +// Remove temporary defines +// +#undef MXBYTE +#undef MXBOOL +#undef MXSINT +#undef MXUINT +#undef MXPTR +#undef MXAPI + +#endif // _MODEX_H_ diff --git a/16/x_/modex.lbr b/16/x_/modex.lbr new file mode 100755 index 00000000..b1ec26b6 --- /dev/null +++ b/16/x_/modex.lbr @@ -0,0 +1,38 @@ ++-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 diff --git a/16/x_/modex.pas b/16/x_/modex.pas new file mode 100755 index 00000000..7d9d26ed --- /dev/null +++ b/16/x_/modex.pas @@ -0,0 +1,194 @@ +(* + Turbo Pascal interface to the MODEX library + Copyright (c) 1993,1994 by Alessandro Scotti +*) +unit ModeX; +interface + +const + (* Video modes *) + MX_TEXT = 0; + MX_320x175 = 1; + MX_320x200 = 2; + MX_320x240 = 3; + MX_320x350 = 4; + MX_320x400 = 5; + MX_320x480 = 6; + MX_360x175 = 7; + MX_360x200 = 8; + MX_360x240 = 9; + MX_360x350 = 10; + MX_360x400 = 11; + MX_360x480 = 12; + MX_400x600 = 13; + + (* Fade effects *) + MX_FADEIN = 0; + MX_FADEOUT = 1; + + (* Raster ops *) + OP_SET = 0; + OP_AND = 1; + OP_OR = 2; + OP_XOR = 3; + OP_TRANS = 4; + OP_ADD = 5; + OP_MOVE = 0; (* Alias for OP_SET *) + +procedure mxBitBlt( SX, SY: integer; Width, Height: word; DX, DY: integer ); +procedure mxCircle( CX, CY: integer; Radius: word; Color: byte ); +procedure mxChangeMode( Mode: word ); +procedure mxColorToGray( ColorPalette, GrayPalette: pointer; Count: word ); +procedure mxFadePalette( Palette: pointer; Cmd, Start, Count, R, G, B: word ); +procedure mxFillBox( X, Y: integer; Width, Height: word; Color: byte; Op: word ); +procedure mxGammaCorrect( ColorPalette, GammaPalette: pointer; Count: word ); +procedure mxGetAspect( var AspectX, AspectY: word ); +function mxGetClipRegion( var X1, Y1, Width, Height: word ): boolean; +function mxGetClip: boolean; +procedure mxGetImage( Image: pointer; X, Y: integer; Width, Height: word ); +procedure mxGetPalette( Palette: pointer; Start, Count: word ); +function mxGetPixel( X, Y: word ): byte; +procedure mxGetScreenSize( var Width, Height: word ); +procedure mxGetTextStep( var DeltaX, DeltaY: integer ); +function mxGetVersion: word; +procedure mxGetVirtualScreen( var Width, Height: word ); +procedure mxInit; +procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word ); +procedure mxOutChar( X, Y: integer; C: char ); +procedure mxOutText( X, Y: integer; S: pointer ); +procedure mxPan( X, Y: word ); +procedure mxPutImage( Image: pointer; X, Y: integer; Width, Height, Op: word ); +procedure mxPutPixel( X, Y: word; C: byte ); +procedure mxPutTile( Tile: pointer; X, Y: integer; Width, Height: word ); +procedure mxReadPlane( Plane: byte ); +procedure mxRotatePalette( Palette: pointer; Count: word; Step: integer ); +procedure mxRowAddress( RowAddress: byte ); +function mxSetClip( Clip: boolean ): boolean; +procedure mxSetClipRegion( X1, Y1, Width, Height: word ); +procedure mxSetColor( Index, R, G, B: word ); +procedure mxSetFont( Font: pointer; Width, Height: word ); +procedure mxSetMode( Mode: word ); +procedure mxSetPalette( Palette: pointer; Start, Count: word ); +procedure mxSetTextColor( Color, Op: word ); +procedure mxSetTextStep( DeltaX, DeltaY: integer ); +procedure mxSetVirtualScreen( Width, Height: word ); +procedure mxStretchImage( Image: pointer; X, Y: integer; Width, Height, NewWidth, NewHeight, Op: word ); +procedure mxSplitScreen( Line: word ); +procedure mxStartAddress( StartAddress: word ); +procedure mxStartLine( Line: word ); +procedure mxTerm; +procedure mxTransPutTile( Tile: pointer; X, Y: integer; Width, Height: word ); +procedure mxWaitDisplay; +procedure mxWaitRetrace; +procedure mxWriteMode( Mode: byte ); +procedure mxWritePlane( Plane: byte ); + +procedure mxFillPoly( Count: word; var Map, Points; Color: word ); +procedure mxGouraudPoly( Count: word; var Map, Points, Colors; BaseColor: word ); +procedure mxTexturePoly( Count: word; var Map, Points, ImgPoints, Texture; Width: word ); + +procedure mxOutStr( X, Y: integer; S: string ); + +implementation + +procedure mxBitBlt; external; +procedure mxChangeMode( Mode: word ); external; +procedure mxCircle; external; +procedure mxColorToGray; external; +procedure mxFadePalette; external; +procedure mxFillBox; external; +procedure mxGammaCorrect; external; +procedure mxGetAspect( var AspectX, AspectY: word ); external; +function mxGetClipRegion; external; +function mxGetClip: boolean; external; +procedure mxGetImage; external; +procedure mxGetPalette( Palette: pointer; Start, Count: word ); external; +function mxGetPixel( X, Y: word ): byte; external; +procedure mxGetScreenSize( var Width, Height: word ); external; +procedure mxGetTextStep( var DeltaX, DeltaY: integer ); external; +function mxGetVersion: word; external; +procedure mxGetVirtualScreen( var Width, Height: word ); external; +procedure mxInit; external; +procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word ); external; +procedure mxOutChar( X, Y: integer; C: char ); external; +procedure mxOutText( X, Y: integer; S: pointer ); external; +procedure mxPan( X, Y: word ); external; +procedure mxPutImage; external; +procedure mxPutPixel( X, Y: word; C: byte ); external; +procedure mxPutTile; external; +procedure mxReadPlane( Plane: byte ); external; +procedure mxRotatePalette; external; +procedure mxRowAddress( RowAddress: byte ); external; +function mxSetClip( Clip: boolean ): boolean; external; +procedure mxSetClipRegion( X1, Y1, Width, Height: word ); external; +procedure mxSetColor( Index, R, G, B: word ); external; +procedure mxSetFont( Font: pointer; Width, Height: word ); external; +procedure mxSetMode( Mode: word ); external; +procedure mxSetPalette( Palette: pointer; Start, Count: word ); external; +procedure mxSetTextColor( Color, Op: word ); external; +procedure mxSetTextStep( DeltaX, DeltaY: integer ); external; +procedure mxSetVirtualScreen( Width, Height: word ); external; +procedure mxSplitScreen( Line: word ); external; +procedure mxStartAddress( StartAddress: word ); external; +procedure mxStartLine; external; +procedure mxStretchImage; external; +procedure mxTerm; external; +procedure mxTransPutTile; external; +procedure mxWaitDisplay; external; +procedure mxWaitRetrace; external; +procedure mxWriteMode( Mode: byte ); external; +procedure mxWritePlane( Plane: byte ); external; + +procedure mxFillPoly; external; +procedure mxGouraudPoly; external; +procedure mxTexturePoly; external; +{$L MXPB} +{$L MXPF} +{$L MXPG} +{$L MXPT} + +{$L MXBB} +{$L MXCC} +{$L MXCG} +{$L MXCL} +{$L MXCR} +{$L MXFB} +{$L MXFP} +{$L MXGI} +{$L MXGM} +{$L MXGP} +{$L MXGV} +{$L MXHL} +{$L MXIT} +{$L MXLN} +{$L MXOT} +{$L MXPI} +{$L MXPN} +{$L MXPP} +{$L MXRA} +{$L MXRP} +{$L MXSA} +{$L MXSC} +{$L MXSI} +{$L MXSL} +{$L MXSM} +{$L MXSP} +{$L MXSS} +{$L MXTL} +{$L MXVS} +{$L MXWD} +{$L MXWM} +{$L MXWP} +{$L MXWR} + +(* + Prints a Turbo Pascal string. + Note: BP 7.0 supports ASCIIZ strings (PChar type). +*) +procedure mxOutStr; +begin + S := S + #0; + mxOutText( X, Y, @S[1] ); +end; + +end. diff --git a/16/x_/modex/DEMO01.EXE b/16/x_/modex/DEMO01.EXE new file mode 100755 index 0000000000000000000000000000000000000000..28caff88c58a0b8ce5a4d23c6544c00cda8482fc GIT binary patch literal 10208 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 320 ) then begin + S.X := 320; + S.DX := -S.DX; + end; + if( S.X < -16 ) then begin + S.X := -16; + S.DX := -S.DX; + end; + if( S.Y > 240 ) then begin + S.Y := 240; + S.DY := -S.DY; + end; + if( S.Y < -16 ) then begin + S.Y := -16; + S.DY := -S.DY; + end; + (* Draw the sprite, note the Page offset added to the *) + (* Y coordinate of the image *) + mxPutImage( @S.Image, S.X, Page+S.Y, S.W, S.H, OP_TRANS ); +end; + +begin + (* Initialize library *) + mxInit; + + (* Enter graphics mode *) + mxSetMode( MX_320x240 ); + + (* Print initialization message *) + mxSetTextColor( 15, OP_TRANS ); + mxOutStr( 4, 4, 'Initializing...' ); + + (* Initialize sprites *) + for I:=1 to MAX_SPRITE do sxInit( S[I] ); + + (* Draw background *) + for I:=1 to 192 do begin + mxCircle( 160, 480+120, I, I+63 ); + mxCircle( 161, 480+120, I, I+63 ); + end; + + (* Compute and set palette *) + for I:=1 to 192 do with Palette[I+63] do begin + R := 0; + G := 0; + B := 0; + if( I < 64 ) then + R := I shr 1+31 + else if( I < 128 ) then + G := (I-64) shr 1+31 + else + B := (I-128) shr 1+31; + end; + mxSetPalette( @Palette[64], 64, 192 ); + + (* Main loop *) + Page := 240; + while( not KeyPressed ) do begin + (* Set clip region to current page *) + mxSetClipRegion( 0, Page, 320, 240 ); + mxSetClip( TRUE ); + (* Restore background *) + mxBitBlt( 0, 480, 320, 240, 0, Page ); + (* Draw sprites *) + for I:=1 to MAX_SPRITE do sxMove( S[I] ); + (* Print message *) + mxOutStr( 4, Page+4, 'Some sprites moving...' ); + (* Flip page *) + mxStartLine( Page ); + Page := 240-Page; + (* Animate palette *) + mxSetPalette( @Palette[64], 64, 192 ); + mxRotatePalette( @Palette[64], 192, 3 ); + end; + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/x_/modex/DEMO02.EXE b/16/x_/modex/DEMO02.EXE new file mode 100755 index 0000000000000000000000000000000000000000..14e7dc72b16e421ae94767feaa07cb3988f49db1 GIT binary patch literal 24688 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 L6~S)>H$VReFZ-F@ literal 0 HcmV?d00001 diff --git a/16/x_/modex/DEMO02.PAS b/16/x_/modex/DEMO02.PAS new file mode 100755 index 00000000..6b4fb6f9 --- /dev/null +++ b/16/x_/modex/DEMO02.PAS @@ -0,0 +1,125 @@ +(* + DEMO02 - Texture mapping and palette rotation + (c) 1994 by Alessandro Scotti +*) +uses Crt, Modex, Plasma, Threed; + +const + LSIZE = 85; + Trans : TPoint = ( X:0; Y:0; Z:0 ); +type + T2DPoint = record + X, Y: integer; + end; + TTexture = record + Desc : array[ 0..3 ] of T2DPoint; + Width : word; + Data : array[ 1..64*64 ] of byte; + end; + TQuad = record + VtxCnt : word; + Vtx : array[ 0..3 ] of word; + Texture: word; + end; +var + Vtx : array[ 0..7 ] of TPoint; + XVtx : array[ 0..7 ] of TPoint; + VVtx : array[ 0..7 ] of T2DPoint; + Face : array[ 0..5 ] of TQuad; + Txts : array[ 0..5 ] of TTexture; + Nrm : array[ 0..5 ] of TPoint; + XNrm : array[ 0..5 ] of TPoint; + Page : word; + Palette: array[ byte ] of record R, G, B: byte; end; + +(* Make a 64x64 plasma to be used as texture *) +procedure MakeTexture( Idx: word ); +var + I: word; +begin + mxFillBox( 0, 0, 64, 64, 0, OP_SET ); + MakePlasma( 0, 0, 64, 64, 96, Random(192)+1, Random(192)+1, Random(192)+1 ); + mxGetImage( @Txts[Idx].Data, 0, 0, 64, 64 ); + (* Texture vertexes are 8:8 fixed, add $80 (0.5) for best results *) + with Txts[Idx] do begin + Desc[0].X := $80; Desc[0].Y := $80; + Desc[1].X := $80; Desc[1].Y := $3F80; + Desc[2].X := $3F80; Desc[2].Y := $3F80; + Desc[3].X := $3F80; Desc[3].Y := $80; + Width := 64; + end; +end; + +procedure Init; +var + I: integer; +begin + (* Build vertexes for a cube *) + with Vtx[0] do begin X:=-LSIZE; Y:=-LSIZE; Z:=-LSIZE; end; + with Vtx[1] do begin X:=+LSIZE; Y:=-LSIZE; Z:=-LSIZE; end; + with Vtx[2] do begin X:=-LSIZE; Y:=+LSIZE; Z:=-LSIZE; end; + with Vtx[3] do begin X:=+LSIZE; Y:=+LSIZE; Z:=-LSIZE; end; + with Vtx[4] do begin X:=-LSIZE; Y:=-LSIZE; Z:=+LSIZE; end; + with Vtx[5] do begin X:=+LSIZE; Y:=-LSIZE; Z:=+LSIZE; end; + with Vtx[6] do begin X:=-LSIZE; Y:=+LSIZE; Z:=+LSIZE; end; + with Vtx[7] do begin X:=+LSIZE; Y:=+LSIZE; Z:=+LSIZE; end; + for I:=0 to 7 do begin (* Make points 16:16 fixed *) + Vtx[I].X := Vtx[I].X*$10000; + Vtx[I].Y := Vtx[I].Y*$10000; + Vtx[I].Z := Vtx[I].Z*$10000; + end; + (* Build faces *) + with Face[0] do begin Vtx[0]:=0; Vtx[1]:=2; Vtx[2]:=3; Vtx[3]:=1; end; + with Face[1] do begin Vtx[0]:=4; Vtx[1]:=5; Vtx[2]:=7; Vtx[3]:=6; end; + with Face[2] do begin Vtx[0]:=0; Vtx[1]:=1; Vtx[2]:=5; Vtx[3]:=4; end; + with Face[3] do begin Vtx[0]:=1; Vtx[1]:=3; Vtx[2]:=7; Vtx[3]:=5; end; + with Face[4] do begin Vtx[0]:=2; Vtx[1]:=0; Vtx[2]:=4; Vtx[3]:=6; end; + with Face[5] do begin Vtx[0]:=7; Vtx[1]:=3; Vtx[2]:=2; Vtx[3]:=6; end; + for I:=0 to 5 do Face[I].Texture := I; + (* Build textures and palette *) + Randomize; + FillChar( Palette, SizeOf(Palette), 0 ); + MakePlasmaPalette( Palette, PAL_RGB ); + mxSetPalette( @Palette, 0, 193 ); + for I:=0 to 5 do MakeTexture( I ); +end; + +var + AX, AY, AZ: byte; + I: word; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; (* Start with hidden page *) + + AX := 0; + AY := 0; + AZ := 0; + (* Init 3D transforms, perspective is intentionally exaggerated *) + tdSetTranslation( Trans ); + tdSetPerspective( 400*$10000, $10000, $10000 ); + (* Main loop, all magic here! *) + while( not KeyPressed ) do begin + tdSetRotation( AX, AY, AZ ); (* Set new angles *) + tdTransform( Vtx, XVtx, 8 ); (* 3D transform points *) + tdTransformToImage( XVtx, VVtx, 8, 160, 120+Page ); + Inc( AX, 1 ); (* Bump angles *) + Inc( AY, 1 ); + Inc( AZ, 2 ); + mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *) + mxSetClip( TRUE ); + mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *) + mxRotatePalette( @Palette[1], 192, 3 ); (* Rotate palette *) + (* Draw cube: backface culling is straighforward in this case, so *) + (* it can be handled by the polygon filling procedure *) + for I:=0 to 5 do + mxTexturePoly( 4, Face[I].Vtx, VVtx, Txts[I].Desc, Txts[I].Data, Txts[I].Width ); + mxStartLine( Page ); (* Flip pages *) + mxSetPalette( @Palette[1], 1, 192 ); (* Set new palette *) + Page := 240-Page; + end; + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/x_/modex/DEMO03.EXE b/16/x_/modex/DEMO03.EXE new file mode 100755 index 0000000000000000000000000000000000000000..c646c4b0283db932174d915432747c2176034195 GIT binary patch literal 14256 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 RADIUS*RADIUS ) then goto Retry; + Z := Toggle( Round( Sqrt( Abs( RADIUS*RADIUS-X*X-Y*Y ) ) ) ); + case Random(3) of + 0: Swap( X, Z ); + 1: Swap( Y, Z ); + end; + X := X * $10000; Y := Y * $10000; Z := Z * $10000; + end; + end; + (* Initialize morphing *) + Move( CubeVtx^, Vtx^, SizeOf(Vtx^) ); + Status := 0; + Count := WAITCOUNT; +end; + +procedure Morph; +var + I: integer; +begin + (* Fully unoptimized, slowest loop I could think of! *) + for I:=0 to MAXVTX-1 do begin + Vtx^[I].X := ((CubeVtx^[I].X * Morph1)+(SphereVtx^[I].X * Morph2)) div MS; + Vtx^[I].Y := ((CubeVtx^[I].Y * Morph1)+(SphereVtx^[I].Y * Morph2)) div MS; + Vtx^[I].Z := ((CubeVtx^[I].Z * Morph1)+(SphereVtx^[I].Z * Morph2)) div MS; + end; +end; + +var + AX, AY, AZ: byte; + I: word; + C: char; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; (* Start with hidden page *) + + AX := 0; + AY := 0; + AZ := 0; + (* Init 3D transforms, perspective is intentionally exaggerated *) + tdSetTranslation( Trans ); + tdSetPerspective( 400*$10000, $10000, $10000 ); + C := #0; + repeat + tdSetRotation( AX, AY, AZ ); (* Set new angles *) + tdTransform( Vtx^, XVtx^, MAXVTX ); (* 3D transform points *) + tdTransformToImage( XVtx^, VVtx, MAXVTX, 160, 120+Page ); + Inc( AX, 1 ); (* Bump angles *) + Inc( AY, 1 ); + Inc( AZ, 2 ); + mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *) + mxSetClip( TRUE ); + mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *) + (* Draw points *) + for I:=0 to MAXVTX-1 do + mxPutPixel( VVtx[I].X, VVtx[I].Y, 128 + XVtx^[I].Z shr 18 ); + mxStartLine( Page ); (* Flip pages *) + Page := 240-Page; + (* Morph *) + if( Odd(Status) ) then begin + Morph; + Inc( Morph1, Delta1 ); + Inc( Morph2, Delta2 ); + if( Morph1 < 0 )or( Morph2 < 0 ) then Inc( Status ); + if( Status = 4 ) then Status := 0; + end + else begin + Dec( Count ); + if( Count < 0 ) then begin + Inc( Status ); + Count := WAITCOUNT; + Morph1 := InitMorph1[Status]; + Morph2 := InitMorph2[Status]; + Delta1 := InitDelta1[Status]; + Delta2 := InitDelta2[Status]; + end; + end; + until( KeyPressed ); + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/x_/modex/DEMO04.DAT b/16/x_/modex/DEMO04.DAT new file mode 100755 index 0000000000000000000000000000000000000000..72aaad08ac55e4d161e7868374296a4e42554684 GIT binary patch literal 37662 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%0D)*4A2IO9KMZYD#oU43C^WOCfTg8_%RD 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�-ncKj8QX2BIutynAlnfJ{;J0ue86t5F zBjm=|;P0?%@yd7OQ+dFR2PjBAijBxEkSVe|?8Mg`9bSn;0N$gC2!TOY+!Y(CGYIfJ zLl{!MwjfSv@Yn<)6iedBDwo&xm>BZTP_LoO?r4B)pf z@(#EL^wxV26ZBM>A@H@;CKMzBuwQPx9H>JQB5){kn4Lsf3IoM~CNpr(HcqO3&~HpVtQmsBT~d zxVH$Y0;Sm?4|fWkKuWhmh-O4%TaO0lZamnfmB#0>Zx_-Bh%5AyG6O zdf27Mg&5kc(Keic#||#$*c3`(95EhB6xi+ zr;jHFqB^jRfCJqT{=kaD?F7ua9-zYGYb=%+fCNwYB%Z=6k$H6SGb`B^QclPoWFe#| z4n|El2cfEn_)$9{4kY1M%NhUAFi9k&iiacuWK=t|@PIPX`9!E78uX5biQ#`edWO>8*UCA!0r$bsPHHI2=A3k0ZA&IgFiy&iHmJ00dxtgE9;15 z6Ts7BD|ybV-|ex)L}O+-h=?l}lu>LZb1he}&-emQw9TnUE4!jOhiETJJ$#^xvj>eS zGUm@_5QFutmmLVhOyopm|EWI}kR`!tZn2;05|@ zauX7Jc1TzuTx_fgA%#K%^w2J-#M_}0^S}a_Jtao~&Ds?yS&NfnP;4Ut0D&9=u*88W zfUk%zEbsuk1A5A}mk>b6fM5hjXaxrdy{h0KW|_DKXDwntI+?OzUMF!YmJ=?UEF@`A z7$Jufq|F)Obs|U>Zsu_K6n7}>kQ|cP;!p_oaL8fue7+!S@$_M|pLd}cPM-Hk?qA3W zF_$gp_)J<7T$oKjAxDPO^5IE6UOgR-@qh9F3hKyUqU-W#Kv0z2=0KPb1rri;A2tGg zC@S(5Rv`xCg|1=|`7FahG~`l|MCJ%3F9{;!}B z1tHeC7dz_?m=l0F_jX!&T(hjN`M-|~fwm=DZ&H>Cu;X&f4xdIEt7K-iU5jY>}4sN%{1_m(x$M^$NL*gd{ z&*jPSZo3CnMR6d2gTejq0WJc2U@nZ=f$4x7aaY_hH9!JeoVg=9+GcZM$RNNFm1)iZ z{9}SuIa2h|?Igr<%Wd#xn5Sci4-i`>;K;B=rXYYfl*Xe}vMsm|6pElx7F1*bscI&Zuvki%@6AO{J=nJa^)43&@tVBa{vaJ(1pLxK(UQ5>pRM4W+jLJ@L_oU9vB zb=mRwcoR{;{d9iu{un`OG&3<^CHmx2M36*uq_i#zu~-(dm_keDoXPA(Q`Bx({iUCGwCV5wO6Q+hY{P z>eePRD*7uyR1Pb423r&k*?k-VS^|X`9KB2==mkv6#6PikhjMIT<1TMAGTF4i$(=rCIrJ!Ct5o=z#$aJSwpjZrLgM##fl2Mpaq(N(RAX`Zf%u^}smO-}pf*UE zf$yQ9i*zuO%&o)PCWoY=7zNcJUY%!Xqol^Z$s)iYRceuctuN4kJ5W&?j~MUra}s~M zl)%*F3d{0WlA(+b0w6C40}1Mh!4Q8G3CzR+6Xyh2Nl%N+#?A+MP`bc{*B3w)5mHzH zYzddEAb~~I5yr>+RL;S0z2(pn}>jieIrj{juu|xaS6Am%R9(Tvg71*#QK1(j9y47vJra< zD7qCSfvLciKAQHt01dm-qlk?tU2zK}3w9FCn=B^LwtTDX1Ce^gzR2z{DJTsVoQK`Q z0YwK1ekO zroN7j1+dzu&KedMghTjrrYgpp#0jUtkzfqjA^ooW zwgaR-;>y0YF|vb6AulOdp0+Im1jeU4=QEK%(Fd|98mTrJOvDmwMD?MBFqQyneRiAj zSPHd+N^=4+F+R>xVKl-B z+5#E~lOfzjk_}2!e4+*rXS9AB1xKx1g^Ddu!&&Qm5D>VMgqVm0B;3WPNEC!uSHF_U zQz#wou~?l>Pzs%1?3cU^*%o+U&H(}uRKA4_qsC|eC&6(MmHXX9P0G({vI2RP_s7>5 z@TyQxmIs@lQ&0}n?onF_fRxutuOR>-K#>5-WD;bGW!wq#DCG!B>Q_{7a#~mv@L85i z7ecO#0=+sm8^M%p9NUJSET(2MK_-#Ip)27IRXj!dXHFCNw( zqjG^PouI739^*>X1R~!dmxrh+4@%OXlp_uU6*r(BmZOCvQfU5B4OK85so=NP;J9$} zk}1GF>zjxip~Mpb4wX{DKp&N+>7SU*jv|)`* zq6l-K4h;`72oy9ux26(`dPT#k0677KNDIn*$wNSZz^W_;Kng9FqALSH8Nt9!q(*%{ zFc_Z-e37}qjdC8UErD41EgM)`>(iJUIRorDV>9Ho%1b3uZ9dN|}J)aSSD1l7aD>2njvg8+)G zR6*b+U{p5-RK@$F5iBlr7y;*0kbASf@*W(B{GbF5C6hbG9FSf_?Pci<;Fj!RblIw~ zC#K(+IFgJ69%}s+))sq!`}~3xg5rAwaJJ|zd4Xt?qr>PzfFv6b$u>}RcmXp=NAn#V zkUJ+TqMiff6ySzHnJ^e>2tWdXw=hBRkB5{H*>Law!KW`h@cISuLo76X*ng5L(qo$f^tafb_8e zLL~@2kkkQoB*}%%Czt@$%0IhxZ&84mhXcqc_tg;_cmx;&P2kGCv=Lg>x~@VSt0JM| zn1~kFkOC8bm?%x97q>Dk7;*@ZbgBo8pnwJ$+KD(bRW8&z<)-OO%VUYqG`SJBr<0Ho zLmZX$hXYiT&}?foNIpXNO%-ac%6=DD{W>YHpTjsEbX*Kn|MpRWf?C1Q{(@*7J+wTJj{{d_TT_D zj1Z1Q_kaM_$5E&ep3D#?7Xr8g%4Twy&S-Xq5D4$^$Ai^J&+r$LY&G?&S4kx%4hs2E z0*%$h*~s|6ys{vTF+}_qhJ#dr%NjI28`=aMkS^mW5n{|uBwkhQm!a&hgWIDU%7VfG zle>qlgiSg(i7tsj=_=Nk^V8Y0F|1BSMZl-=e}qbCQubCB&qN7o?g4S?htg1tkTi*Q z<;cq+*YG!6C_w?Q`k#d|VE}rH&5^?b#-U*pnn|D{{XjH~wZvLSBl-At{2w7eF@&~ahFO3d8JUm$7%) zAejWd7v_^WAmBB!uKEyB>cE~aWD3;l>#SvsxOn?ldYz^Lk z4I|>}&UCB1CLxIU0d~hgkj*McCrBn!CRt{ifC7ScWWxx7b}BTl!!#N#6XjA=uTp~q zoy8&}BwNVx@SP5`k|Y3fV=~;hb19eGs`mgq5Ota$xjS;`w94EP6az}(iwuY|xDFDi zazT8O2C%6tiHS19yh}ANCm}8V-e`^>sJcY9?DLWgm#;_r@IevX67eQw<5h)IZz6c) zQau({$3TGS(#}~5^&z?9w>VXb!|3SWDiLPFSre2KppxyRAySfq@EiRz0;unlYLNB| zbV)#=kMFTOz+IBX=9fE?YXiRM2vaAHM?wGta(-FGPlrti;e% z!6TD3{OTO=30A;hFCzsq$e{!Yi&;}sH3);02gL$@+O4ugN|C^9g)V|LKD&$T3LyyM zq>!IOVLHu0z#*t?HVzqboiG_jDmKvBK{z=X1Q=Beq3DE&Rz-lJqly&selT6JlAfnixupqK5I|GA_3sK|-Zc?XaBpOjH ziMKK1{~`cWqH#zrs8V8_?W%>*62oub!=sSMR?MlYo|7IJeib362r)x46s^WsX(Yf0 zDd^5LXcT2enni%*O5@aUfOZzE0b>FVl2-+(jQ@iz(J~H9#|6rk2@%+r1X!$oc@%&T z)vgeWUe?&jRAYw?p zL~>Q&(r;b^Wf_}qPJlp#JODNr4u}WF3o52D zW`xcrE za$7L>yW{^fngbjdks*F@dg+FwD-KgE8ALk}OqMZGjdEN7SBZ-lu5+ zSc((OvxSLt3M7VG0x5#g{PCG&9j69rtL4bGPj&KR%9-f+vj zM73u1uS6gOh*8^RIjoTgz)MRug?5Pk8F41Wtz`Tk?rQu$hD@#_1`Kd-{2z})YCxPe z?Tg&q1|$Xyax5lZS7E)9d8Q11WE}E&{{NyoRDk;Mw}lZ(~KvJ069vcDLM*hK_N5u zxAA|2hM`!Ni}VtWW-%^&DdCS?aYV`)YCypGYchE9;u>I(bVWQYuaYB!`>+7fVZAKi z;=NdsBS0uj_UPXDKRL|*Vf>%tBhf48L_x_;>JBk9!T}3}B^B!%NQ0SID%N8YKo^BZ zMu3@GU%p5}2-=d*1)JO(|Cfmgd85H73akHl{9kxkpbF$g08V}pNQ8OjRx+y`KEssA z8eUgw&sxf2xdi4VKd6auh!B7;Mx;5ptcU~s=kb4j_xIn&{{x(}4ge#<9u+iEch@=j zyjF7c0RS<2p#OvWM!z!Iu}~lugI`wdj`5(1g2i;yn;s?EUX|{kF;YMWl>GDfzmqvH zga`{@ay^Cs3TFFQ2VTnaEB8PHl%9?NJJElnOrKOILM(9YoQ00TZ^r)>oWUhSA<1v$ zS~x0U9=zVY@qfW+BaqH-$NxF&fDvYSd_+rZln0?y0qc-e;xd^!6#=qDhK?5$r;sNL zqIfj~m@aYUUPS;d(}XX;Yn3OB@4{$MKnCte*Nu1n*YSU7Q_w0Y6Cvyq3TSAjy_+nz z1Pb*s`YmrLx#VKYO0-AD{}t*h@hUa;lR7{w&{pmuWJYH^t?9ydsY}OAN?*Kq!qoKi z8F5cMv260xxXBZyEn7TeTx@LYm;Sz9)6?Q6rO%i$b;gpkaTBL6n-Uv4E^gwK zrKw9|<6C-2rr>3W+rA>^TwsdCPxPKeJbkgLhGvZ=nr=)Y;cLJuT zPM^GV>D1T><0p(uo%mqfxXIJfr;ndF3I31c{|QK) zk)A$zLh91E@zc{%wQ}5)8Pk?7TQ)N_ec8m=*tq+C1WVGMShg&E>GYYCXU<4XUy_Nf+XH|0;ViUTbB03^chR1O`J3{eetC9rEwD{Pne#bHZv`K0;+i5 z35c6EGktn$?1Uu~VyC91O`i0`;_)0Rz}K7H}{xb*Q8@Ci?( zj*p!(WATLPlPBDF4lGU`KW@_a*tm(Ylg5o3hY-ZY%|HpqO-)}qIW~5}{U>1Bgt&1N zB=r-QOq)1<+_Kbh<0q#tLlV-b#&QDp-x5xai=F)7%o&TPPg^E)wB(7IOViV4Oo*Mf zICdf&x&H*<{L<6YQqv#A2*8OcGne5JXFNDz0(JpW9CzPkU~1|Usf(ASFPl1k>dc9; zadFF@NKaclbt0#aK5*T40ze_@QCihlNT>uJaNi|iIZk5T{1Ox z67kxSwEM4yi>EF@_6SKQFPhoB2fQ6U)+<-FFTUfGmau_?-#kW2a4@ XG;Ye`)EVP3#M6mPm!(a=?*#mR$DZhs literal 0 HcmV?d00001 diff --git a/16/x_/modex/DEMO04.EXE b/16/x_/modex/DEMO04.EXE new file mode 100755 index 0000000000000000000000000000000000000000..1fec5e8aa383353d986ca1e4420838b09e61eef4 GIT binary patch literal 24384 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 Im202>1y)VB#{d8T literal 0 HcmV?d00001 diff --git a/16/x_/modex/DEMO04.PAS b/16/x_/modex/DEMO04.PAS new file mode 100755 index 00000000..1a946315 --- /dev/null +++ b/16/x_/modex/DEMO04.PAS @@ -0,0 +1,198 @@ +(* + DEMO04 - Multiple textures and triple buffering (3 pages) + (c) 1994 by Alessandro Scotti +*) +uses Crt, Modex, Threed; + +const + MAXVTX = 256; + MAXCUB = 2; + MAXTXT = 2; + Trans : TPoint = ( X:0; Y:0; Z:0 ); + TxtSunDial: array[ 0..7 ] of word = ( + $7F80,$0080, $0080,$0080, $0080,$7E80, $7F80,$7E80 ); + TxtSapphire : array[ 0..7 ] of word = ( + $0080,$0080, $0080,$1F80, $1F80,$1F80, $1F80,$0080 ); + TxtMarble: array[ 0..7 ] of word = ( + $0080,$8080, $0080,$FD80, $7F80,$FD80, $7F80,$8080 ); +type + T2DPoint = record + X, Y: integer; + end; + TTexture = record + Desc : array[ 0..3 ] of record X, Y: word end; + Width : word; + Data : pointer; + end; + TQuad = record + Vtx : array[ 0..3 ] of word; + Texture: word; + end; + TCube = record + Face : array[ 0..5 ] of TQuad; + Base : integer; + end; +var + Vtx, XVtx: array[ 0..MAXVTX ] of TPoint; + VVtx : array[ 0..MAXVTX ] of T2DPoint; + Cube : array[ 0..MAXCUB ] of TCube; + ZList : array[ 0..MAXCUB ] of integer; + VtxCnt : word; + Txts : array[ 0..MAXTXT ] of TTexture; + Page : word; + Palette : array[ byte ] of record R, G, B: byte; end; + TxtDat1, TxtDat2: pointer; + +(* Add a new entry to the vertex array *) +procedure AddVtx( PX, PY, PZ: longint ); +begin + with Vtx[VtxCnt] do begin X:=PX*$10000; Y:=PY*$10000; Z:=PZ*$10000; end; + Inc( VtxCnt ); +end; + +procedure MakeCube( var C: TCube; X1,Y1,Z1, X2,Y2,Z2, TX,TY,TZ, Texture: integer ); +const + FaceIdx: array[ 0..23 ] of integer = ( + 0,1,2,3, 0,4,5,1, 1,5,6,2, 2,6,7,3, 3,7,4,0, 6,5,4,7 ); +var + I, VC: integer; +begin + VC := VtxCnt; + C.Base := VC; + AddVtx( X1+TX, Y1+TY, Z1+TZ ); + AddVtx( X2+TX, Y1+TY, Z1+TZ ); + AddVtx( X2+TX, Y2+TY, Z1+TZ ); + AddVtx( X1+TX, Y2+TY, Z1+TZ ); + AddVtx( X1+TX, Y1+TY, Z2+TZ ); + AddVtx( X2+TX, Y1+TY, Z2+TZ ); + AddVtx( X2+TX, Y2+TY, Z2+TZ ); + AddVtx( X1+TX, Y2+TY, Z2+TZ ); + for I:=0 to 23 do C.Face[I shr 2].Vtx[I and 3] := VC+FaceIdx[I]; + for I:=0 to 5 do C.Face[I].Texture := Texture; +end; + +procedure MakeTexture( Idx: integer; var VtxData ); +var + P: ^word; + I: integer; +begin + P := @VtxData; + with Txts[Idx] do begin + for I:=0 to 3 do begin + Desc[I].X := P^; Inc( P ); + Desc[I].Y := P^; Inc( P ); + end; + Width := 129; + Data := TxtDat1; + end; +end; + +procedure Init; +var + I: integer; + V: integer; + F: file; + P: array[ 1..768 ] of byte; +begin + (* Initialize objects *) + VtxCnt := 0; + MakeCube( Cube[0], -64,-64,8, 64,64,-8, 0,0,0, 1 ); (* Sundial *) + Cube[0].Face[0].Texture := 0; + V := VtxCnt; + MakeCube( Cube[1], -16,-16,16, 16,16,-16, 0,0,0, 2 ); (* Sapphire *) + tdSetTranslation( Trans ); + tdSetRotation( 32, 32, 00 ); + tdRotate( Vtx[V], XVtx[V], 8 ); (* Got to rotate this cube *) + for I:=V to V+7 do begin + Vtx[I].X := XVtx[I].X; + Vtx[I].Y := XVtx[I].Y; + Vtx[I].Z := XVtx[I].Z + 100*$10000; + end; + MakeCube( Cube[2], -64,-4,48, 64,4,-48, 0,68,56, 1 ); (* Marble *) + (* Load texture and palette *) + Assign( F, 'DEMO04.DAT' ); + Reset( F, 1 ); + BlockRead( F, P, SizeOf(P) ); + mxSetPalette( @P, 0, 256 ); + GetMem( TxtDat1, 63*1024 ); + BlockRead( F, TxtDat1^, 129*286 ); + Close( F ); + TxtDat2 := Ptr( Seg(TxtDat1^), Ofs(TxtDat1^)+129*254 ); + (* Init textures *) + MakeTexture( 0, TxtSundial ); + MakeTexture( 1, TxtMarble ); + MakeTexture( 2, TxtSapphire ); + Txts[2].Data := TxtDat2; +end; + +(* Sort procedure, not worth optimizing with only a few objects *) +procedure SortObjects; +var + I, J, K: integer; + ZMax: array[ 0..MAXCUB ] of longint; + ZI: integer; + L: longint; +begin + for I:=0 to MAXCUB do begin + L := XVtx[Cube[I].Base].Z; + for J:=1 to 7 do + if( L > XVtx[Cube[I].Base+J].Z ) then L := XVtx[Cube[I].Base+J].Z; + ZMax[I] := L; + ZList[I] := I; + end; + for I:=0 to MAXCUB-1 do begin + ZI := I; + for J:=I+1 to MAXCUB do + if( ZMax[ZList[J]] > ZMax[ZList[ZI]] ) then ZI := J; + if( ZI <> I ) then begin + K := ZList[I]; + ZList[I] := ZList[ZI]; + ZList[ZI] := K; + end; + end; +end; + +var + AX, AY, AZ: byte; + I, J, K: word; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; (* Start with hidden page *) + + (* Init 3D transforms, perspective is intentionally exaggerated *) + AX := 0; AY := 0; AZ := 0; + tdSetTranslation( Trans ); + tdSetPerspective( 600*$10000, $10000, $10000 ); + (* Main loop, all magic here! *) + while( not KeyPressed ) do begin + tdSetRotation( AX, AY, AZ ); (* Set new angles *) + tdTransform( Vtx, XVtx, VtxCnt ); (* 3D transform points *) + tdTransformToImage( XVtx, VVtx, VtxCnt, 160, 120+Page ); + Inc( AX, 1 ); (* Bump angles *) + Inc( AY, 2 ); + Inc( AZ, 1 ); + mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *) + mxSetClip( TRUE ); + mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *) + (* Draw objects *) + SortObjects; + for I:=0 to MAXCUB do with Cube[ZList[I]] do begin + for J:=0 to 5 do begin + K := Face[J].Texture; + mxTexturePoly( 4, Face[J].Vtx, VVtx, Txts[K].Desc, Txts[K].Data^, Txts[K].Width ); + end; + end; + (* Flip page: at 320x240 the Start Address Register Low is always zero *) + case Page of + 0 : begin PortW[$3D4] := $000C; Page := 240; end; + 240: begin PortW[$3D4] := $4B0C; Page := 480; end; + 480: begin PortW[$3D4] := $960C; Page := 0; end; + end; + mxWaitRetrace; (* If the frame rate seems low, try to remove this line *) + end; + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/x_/modex/DEMO05.EXE b/16/x_/modex/DEMO05.EXE new file mode 100755 index 0000000000000000000000000000000000000000..21a7c207f7134ed187a08530637509b96b37b19e GIT binary patch literal 22528 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 CoI~RP literal 0 HcmV?d00001 diff --git a/16/x_/modex/DEMO05.PAS b/16/x_/modex/DEMO05.PAS new file mode 100755 index 00000000..819c5cf3 --- /dev/null +++ b/16/x_/modex/DEMO05.PAS @@ -0,0 +1,131 @@ +(* + DEMO05 - A Gouraud-shaded rotating torus + (c) 1994 Alessandro Scotti +*) +uses Crt, Modex, Threed; + +(* Define ALTPAL for alternate palette *) +{$define ALTPAL} + +const + MAXVTX1 = 15; RADIUS1 = 70; (* MAXVTX1+1 must be multiple of 4 *) + MAXVTX2 = 15; RADIUS2 = 30; + MAXVTX = (MAXVTX1+1)*(MAXVTX2+1)-1; + MAXFACE = MAXVTX; + Trans : TPoint = ( X:0; Y:0; Z:0 ); (* Object translation *) + Light : TPoint = ( X:0; Y:0; Z:-63*$10000 ); (* Light direction *) +type + TQuad = record + QVtx : array[ 0..3 ] of integer; + end; +var + Vtx, XVtx : array[ 0..MAXVTX ] of TPoint; (* Points *) + VVtx : array[ 0..MAXVTX ] of record X, Y: integer end; + Face : array[ 0..MAXFACE ] of TQuad; (* Polys *) + Culled : array[ 0..MAXFACE ] of integer; + GNrm,XGNrm: array[ 0..MAXVTX ] of TVector; (* Gouraud normals *) + VtxLight : array[ 0..MAXVTX ] of integer; (* Points brightness *) + Page : word; + +function GetVtx( I1, I2: integer ): integer; +begin + GetVtx := (I1 mod (MAXVTX1+1))*(MAXVTX2+1) + I2 mod (MAXVTX2+1); +end; + +procedure Init; +var + R, N, X, Y, Z: real; + I, J, K, V: integer; +begin + (* Build vertexes *) + for I:=0 to MAXVTX1 do begin + K := (I + (MAXVTX1+1) shr 2) mod (MAXVTX1+1); + R := RADIUS1 + RADIUS2*Cos( 2*K*Pi / (MAXVTX1+1) ); + for J:=0 to MAXVTX2 do begin + V := I*(MAXVTX2+1)+J; (* Index of current vertex *) + (* Compute coordinates of current vertex *) + X := R*Cos(2*J*Pi / (MAXVTX2+1)); (* Get coordinates *) + Y := R*Sin(2*J*Pi / (MAXVTX2+1)); + Z := RADIUS2*Sin(2*K*Pi / (MAXVTX1+1)); + Vtx[V].X := Round( X )*$10000; (* Save coordinates *) + Vtx[V].Y := Round( Y )*$10000; + Vtx[V].Z := Round( Z )*$10000; + (* Compute direction of Gouraud normal thru current vertex *) + X := X - RADIUS1*Cos(2*J*Pi / (MAXVTX2+1)); + Y := Y - RADIUS1*Sin(2*J*Pi / (MAXVTX2+1)); + N := Sqrt( X*X + Y*Y + Z*Z ); (* Get vector length *) + GNrm[V].X := Trunc( X*$10000/N ); (* Save normal vector *) + GNrm[V].Y := Trunc( Y*$10000/N ); + GNrm[V].Z := Trunc( Z*$10000/N ); + end; + end; + (* Generate faces so that depth-sorting is not needed: there are still *) + (* some *very* little errors, but this is the best I could devise *) + J := 0; + K := 0; + for I:=0 to MAXFACE do with Face[I] do begin + QVtx[0] := GetVtx( J, K ); + QVtx[1] := GetVtx( J, K+1 ); + QVtx[2] := GetVtx( J+1, K+1 ); + QVtx[3] := GetVtx( J+1, K ); + Inc( K ); + if( K > MAXVTX2 ) then begin + K := 0; + Inc( J ); + end; + end; +{$ifndef ALTPAL} + for I:=0 to 63 do mxSetColor( I+64, 0, 0, I ); (* Blue palette *) +{$else} + for I:=0 to 31 do mxSetColor(I+64, 0, I shl 1, 0); (* Green neon palette *) + for I:=32 to 63 do mxSetColor ( I+64, (I-32) shl 1, 63, (I-32) shl 1 ); +{$endif} +end; + +var + AX, AY, AZ: byte; + I: word; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; (* Start with hidden page *) + + AX := 0; + AY := 0; + AZ := 0; + (* Init 3D transforms, perspective is intentionally exaggerated *) + tdSetTranslation( Trans ); + tdSetLight( Light ); + tdSetPerspective( 400*$10000, $10000, $10000 ); + (* Main loop, all magic here! *) + while( not KeyPressed ) do begin + tdSetRotation( AX, AY, AZ ); (* Set new angles *) + tdTransform( Vtx, XVtx, MAXVTX+1 ); (* 3D transform points *) + tdTransformToImage( XVtx, VVtx, MAXVTX+1, 160, 120+Page ); + tdRotate( GNrm, XGNrm, MAXVTX+1 ); (* Rotate Gouraud normals *) + tdTransformLight( XGNrm, VtxLight, MAXVTX+1 ); + (* Backplane culling is not really needed here! *) + FillChar( Culled, SizeOf(Culled), 0 ); + tdBackPlaneCull( Face, XVtx, Culled, MAXFACE+1, SizeOf(TQuad) ); + Inc( AX, 1 ); (* Bump angles *) + Inc( AY, 2 ); + Inc( AZ, 3 ); + mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *) + mxSetClip( TRUE ); + mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *) + (* Draw polygons *) + for I:=0 to MAXFACE do with Face[I] do + if( Culled[I] >= 0 ) then mxGouraudPoly( 4, QVtx, VVtx, VtxLight, 64 ); + (* Flip page: at 320x240 the Start Address Register Low is always zero *) + case Page of + 0 : begin PortW[$3D4] := $000C; Page := 240; end; + 240: begin PortW[$3D4] := $4B0C; Page := 480; end; + 480: begin PortW[$3D4] := $960C; Page := 0; end; + end; + mxWaitRetrace; (* Uncomment this instruction if screen flickers *) + end; + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/x_/modex/DEMO06.DAT b/16/x_/modex/DEMO06.DAT new file mode 100755 index 0000000000000000000000000000000000000000..1ac2c2bb8f8c79a7cf1f3c968f75e8e5ac8cd705 GIT binary patch literal 77568 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 P3zel81wBCVexm$;I2yv& literal 0 HcmV?d00001 diff --git a/16/x_/modex/DEMO06.EXE b/16/x_/modex/DEMO06.EXE new file mode 100755 index 0000000000000000000000000000000000000000..f1308e8a536aa9d3d4574566fd018d698d5ef784 GIT binary patch literal 10864 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 G@BaZ%)XT^K literal 0 HcmV?d00001 diff --git a/16/x_/modex/DEMO06.PAS b/16/x_/modex/DEMO06.PAS new file mode 100755 index 00000000..f26af067 --- /dev/null +++ b/16/x_/modex/DEMO06.PAS @@ -0,0 +1,135 @@ +(* + DEMO06 - Magnifying glass + (c) 1994 Alessandro Scotti +*) +uses Crt, Modex; + +const + R = 40; (* Lens radius *) + K : real = 1.8; (* Magnifying factor, less makes a stronger lens *) +type + TLine = array[ 0..319 ] of byte; + PLine = ^TLine; + TScreen = array[ 0..239 ] of PLine; +var + VScreen: TScreen; (* Virtual screen *) + BallX : array[ 0..R, 0..R ] of integer; + BallY : array[ 0..R, 0..R ] of integer; + Sprite : array[ -R..R, -R..R ] of byte; + Page : word; + +(* Returns "lens-view" coordinates of X,Y *) +procedure GetCoords( var X, Y: integer ); +var + LR, Z, SinA, SinB, TgB, Q: real; +begin + LR := Sqrt( X*X + Y*Y ); + if( LR = 0 ) then Exit; + if( LR < R ) then begin + Z := Sqrt( R*R - LR*LR ); + SinA := LR / R; + SinB := SinA / K; + TgB := SinB / Sqrt( 1-SinB*SinB ); + Q := LR - TgB*Z; + X := Round( X * ( Q/LR ) ); + Y := Round( Y * ( Q/LR ) ); + end; +end; + +procedure Init; +var + F : file; + Palette: array[ 0..767 ] of record R, G, B: byte; end; + X, Y, + X2, Y2 : integer; +begin + (* Load background image *) + Assign( F, 'demo06.dat' ); + Reset( F, 1 ); + BlockRead( F, Palette, 768 ); + mxSetPalette( @Palette, 0, 256 ); + for Y:=0 to 239 do begin + New( VScreen[Y] ); + BlockRead( F, VScreen[Y]^, 320 ); + mxPutImage( VScreen[Y], 0, 480+Y, 320, 1, OP_MOVE ); + end; + Close( F ); + (* Build lens *) + for X:=0 to R do begin + for Y:=0 to R do begin + X2 := X; + Y2 := Y; + GetCoords( X2, Y2 ); + BallX[X, Y] := X2; + BallY[X, Y] := Y2; + end; + end; +end; + +procedure PutLens( OX, OY: integer ); +var + X, Y: integer; +begin + for X:=0 to R do begin + for Y:=0 to R do begin + Sprite[Y][X] := VScreen[ OY+BallY[X,Y] ]^[ OX+BallX[X,Y] ]; + Sprite[Y][-X] := VScreen[ OY+BallY[X,Y] ]^[ OX-BallX[X,Y] ]; + Sprite[-Y][X] := VScreen[ OY-BallY[X,Y] ]^[ OX+BallX[X,Y] ]; + Sprite[-Y][-X] := VScreen[ OY-BallY[X,Y] ]^[ OX-BallX[X,Y] ]; + end; + end; + (* Draw the sprite *) + mxPutImage( @Sprite, OX-R, OY-R+Page, 2*R+1, 2*R+1, OP_MOVE ); +end; + +function Delta: integer; +begin + Delta := Random(3)+2; +end; + +procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer ); +begin + if( Cond ) then begin + Coord := NewCoord; + DeltaC := Sign*Delta; + end; +end; + +var + X, Y, DX, DY: integer; + C: char; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; + X := R; + Y := R; + Randomize; + DX := Delta; + DY := Delta; + + (* Main loop *) + repeat + (* Update video *) + mxBitBlt( 0, 480, 320, 240, 0, Page ); + PutLens( X, Y ); + mxCircle( X, Page+Y, R, 0 ); + (* Update lens coordinates *) + Inc( X, DX ); + Check( X+R >= 319, X, DX, 319-R, -1 ); + Check( X <= R, X, DX, R, +1 ); + Inc( Y, DY ); + Check( Y+R >= 239, Y, DY, 239-R, -1 ); + Check( Y <= R, Y, DY, R, +1 ); + (* Flip pages: double buffering, avoid wait for display *) + case Page of + 0 : begin PortW[$3D4] := $000C; Page := 240; end; + 240: begin PortW[$3D4] := $4B0C; Page := 0; end; + end; + mxWaitRetrace; (* Wait for hidden page to show *) + until( KeyPressed ); + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/x_/modex/DEMO07.EXE b/16/x_/modex/DEMO07.EXE new file mode 100755 index 0000000000000000000000000000000000000000..8a401169bba312a0d668452c9df6086505c394a8 GIT binary patch literal 7440 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 639, X, DX, 319, -1 ); + Check( X < 0, X, DX, 0, +1 ); + Inc( Y, DY ); + Check( Y+200 >= 399, Y, DY, 199, -1 ); + Check( Y < 0, Y, DY, 0, +1 ); + mxPan( X, Y ); + mxWaitRetrace; + end; + + (* Shutdown *) + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/x_/modex/MATH.INC b/16/x_/modex/MATH.INC new file mode 100755 index 00000000..742af410 --- /dev/null +++ b/16/x_/modex/MATH.INC @@ -0,0 +1,34 @@ +; +; MATH.INC - Include file for THREED.ASM +; + +; 3-dimensional point, coordinates in fixed format (16:16) +; +TPOINT STRUC + X DD ? + Y DD ? + Z DD ? +TPOINT ENDS + +; 2-dimensional point, coordinates in integer format +; +TIMAGEPOINT STRUC + IX DW ? + IY DW ? +TIMAGEPOINT ENDS + +; Fixed-point divide: EAX = EAX / arg +; +.xdiv MACRO arg + xor edx, edx + shld edx, eax, 16 + shl eax, 16 + idiv arg +ENDM + +; Fixed-point multiply: EAX = EAX * arg +; +.xmul MACRO arg + imul arg + shrd eax, edx, 16 +ENDM diff --git a/16/x_/modex/PLASMA.PAS b/16/x_/modex/PLASMA.PAS new file mode 100755 index 00000000..237e292a --- /dev/null +++ b/16/x_/modex/PLASMA.PAS @@ -0,0 +1,103 @@ +unit Plasma; +interface + +const + PAL_RGB = 0; + PAL_CLOUDS = 1; + PAL_LANDSCAPE = 2; + +procedure MakePlasma( X, Y: integer; W, H: word; C1, C2, C3, C4: byte ); +procedure MakePlasmaPalette( var Palette; What: word ); + +implementation uses Modex; + +procedure NewColor( XA, YA, X, Y, XB, YB: integer ); +var + Color: longint; +begin + Color := Abs( XA-XB )+Abs( YA-YB ); + Color := Random( Color shl 1 )-Color; + Color := (Color+mxGetPixel( XA, YA )+mxGetPixel( XB, YB )+1) shr 1; + if( Color < 1 ) then Color := 1; + if( Color > 192 ) then Color := 192; + if( mxGetPixel( X, Y ) = 0 ) then + mxPutPixel( X, Y, Lo(Color) ); +end; + +procedure Divide( X1, Y1, X2, Y2: integer ); +var + X, Y, Color: integer; +begin + if not( (X2-X1<2)and(Y2-Y1<2) ) then begin + X := (X1+X2) shr 1; + Y := (Y1+Y2) shr 1; + NewColor( X1, Y1, X, Y1, X2, Y1 ); + NewColor( X2, Y1, X2, Y, X2, Y2 ); + NewColor( X1, Y2, X, Y2, X2, Y2 ); + NewColor( X1, Y1, X1, Y, X1, Y2 ); + Color := (mxGetPixel( X1, Y1 )+mxGetPixel( X2, Y1 )+ + mxGetPixel( X2, Y2 )+mxGetPixel( X1, Y2 )) shr 2; + mxPutPixel( X, Y, Color ); + Divide( X1, Y1, X, Y ); + Divide( X, Y1, X2, Y ); + Divide( X, Y, X2, Y2 ); + Divide( X1, Y, X, Y2 ); + end; +end; + +procedure MakePlasma; +begin + Dec( W ); + Dec( H ); + mxPutPixel( X, Y, C1 ); + mxPutPixel( X, Y+H, C2 ); + mxPutPixel( X+W, Y+H, C3 ); + mxPutPixel( X+W, Y, C4 ); + Divide( X, Y, X+W, Y+H ); +end; + +procedure MakePlasmaPalette; +type + TPal = array[ byte ] of record R, G, B: byte end; +var + I: word; +begin + FillChar( TPal(Palette)[1], 192*3, 0 ); + case What of + PAL_CLOUDS: + for I:=1 to 192 do begin + TPal(Palette)[I].R := Abs( I-96 )*63 div 96; + TPal(Palette)[I].G := Abs( I-96 )*63 div 96; + TPal(Palette)[I].B := 63; + end; + PAL_LANDSCAPE: + begin + for I:=0 to 31 do begin + TPal(Palette)[I+1].R := I; + TPal(Palette)[I+1].G := I; + TPal(Palette)[I+1].B := I + I shr 1+15; + end; + for I:=32 to 63 do begin + TPal(Palette)[I+1].R := 0; + TPal(Palette)[I+1].G := I; + TPal(Palette)[I+1].B := 0; + end; + for I:=64 to 191 do begin + TPal(Palette)[I+1].R := (I-64) div 3 + 15; + TPal(Palette)[I+1].G := (I-64) div 3 + 15; + TPal(Palette)[I+1].B := (I-64) div 3 + 15; + end; + end; + else + for I:=1 to 64 do begin + TPal(Palette)[I].G := I-1; + TPal(Palette)[I].B := 64-I; + TPal(Palette)[I+64].R := I-1; + TPal(Palette)[I+64].G := 64-I; + TPal(Palette)[I+128].B := I-1; + TPal(Palette)[I+128].R := 64-I; + end; + end; +end; + +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 index 0000000000000000000000000000000000000000..a10d7db5a0a62654c70c632d8ce6b078a520613c GIT binary patch literal 10336 zcmbVy3s_TEw(vTSoID5tMX9d_w3u4aR7pjJ@F+^O-bz#J1NEZq*xKpbnYI^CaBinU z9O@%E)H?0hnUZ!!WWE_Y+WW;0{cphDYcwb*je_>8JQNX74~7B?7ZB3qu6+V(ZR`F2 zpM3kAz1Lo^z4qE`@3jxh*S!ei!2l7km)-jpIRohcZz=(%006$=FqT&-fC4PyiF z6qYtD-88^C7N7x3HoH{V|fe95SC3Gz-=t+DBwFXRvITXa2_8pDXoOZ^fveybGb-FMZ0`K0}NZp6iB;hC?#A&)8=aPiOJ&1FO3Yye{DS#SS zcG@~~PN)ENoa>fUJjFFqaEfapk4xlnnLL`w;|i6EdYk9E%`O_uu0YW2iUG5z4Z32n zIRYZR1gZ$S(ngR-4=DtEE8yA?Y7)dz7EJ-yHiVKUDWk}hfgBH-@ECwQ4GX>j-&QQK zZmg$cA(|uph;`}8d~SOc4cr>nUNAesT>RJYebij{sEvb(E1P?3 z@RLcLH-+^2iPQT96Gsdx)C(pBWAcAgjxJLnD1vSB@arT_WvOnm+M0%PrFYt;UAKW6VLEW2L!zf zxn-Pp;f6~%UkkYvr1~{hlTEDG_{Y>%8rxrnrm~sT`@AVqc&L!VLj{J1fxF?syU^6< zU10h$gcfRL^VNr-%#$O%qZ_`sU}nljU{IIh&dj0fk3~y+h6&^ewyB2au;)>j; zD{|kXvgHpI5wDY$F|K^!llK8lF8ScykT8UPcSlF%pxgauPvJHiwk`be&be-#EtCGy zuz+lJHjEi1D`4*V73LqO*9n>QM{Cz7Unt<-UY>kB?-@b6;-@sU<=hiA_x!;5f%?M6 z;A{#C8{xiCH7fRQ>>>c+li&XoS1O0>Q9ovp!fous$IU)u+`osCl@A{``@pzY{*;Ec zoO^=)w{eG}FuGLWyZ_BO6r;}Zy}?VqAP`>&MXCq91n1x%u5Qdlzw6V1eN(#>eabaU~CZ~&Z?xp*SJf6$Bj9$95KDbhE( z^|?-v{Z1I%UbPyuxORqudHrNJeh@6W{e&nKo*(S>i@)?^h@&lSH~`9WP%sUpe^kzp zn2ov$ronryLBZ62uhkzk^^qYI_sI_6zSuYC?X(}N7TmEK?n?a6)$lRoYew5u*oU4? zqL~_1m=#~c<5qDv9@Xw0ZHg^;7$^?M;6qLr z#s4Zl0LNCKF^;XoM{$*cn5(pr^RYp$kt2e2johfgT+5~AN97JO*mSeFbD%J_k)tdZ z#1s9;8Y%4>G`Z^&WP1(yRH0@)5Y()|vJ%880Wu#%Uhzhho`XlNXgoNM?43XPs>U9z zevdYcDTxF@I~D}ZI1r+v!J5xed_;)?fhq*55vYMu0GpNun}!8jGzWGQx09Oy3GFeb z&(NUXPpUQdI2zog3MfTtlVWKpGB9yVOEvHd(1^Q(NWsEAR6K;1qI{F86g42*w0dbN z>S5yWh`O{i8j!V-vdGLDae2_-Mq-6T%&pO*+LifZ@#v#38H+WIR2v8ScrFss$#y_` zqDgx!X_G@zNYRb*(`O>V(61L#X-KZxHZFcJ{$l&H}@d z_@Vg0Z8UQcAppr&wuQ$J$Dhle%naxSEf72wp#@<}5PS#m&JB9*ct%;PB-W|-Go1Sa zhG7!Ji4S3CZ>j6(JyciM`*+W7In&rWm85%aS1f&smAO>yP8`gY={(0 z8X-$9tX7GZV8m}f0~^*nV9QePHU)NX_UlWO%pUiidViH^sFuPYaFRlU8=0*Wjlhq0 zw=nh=CsT2j>Bj!6r2isi-yBf2^N&P_4X1tKLW6|y zw`%%$2ThLpP>m-_VxlTjAQ-GN`C)%i){tvwwD-v{w`HPB1w}R9xw+FY+Ta>K3j47! z9;4Ns4MRn^PVlr=s$`HB&_4r`k~Ic*%@o=5vYoR3lvR%<%-0B}NMXaM`S(J^Zwo=V z^FHH#IFKoq-8Jp>V*K7@#V9zw)85JJ?BBHp%d z?s=y&V#gs+wM4x0XAq9ZSJ_Pc!l`%<22;D~_B(EieAl^M%{xs!2Pr;WUjh(cB`qjl z#6g;WLSMp$04xl=-Zzln&(u2=`eYPPkm*E~P~_Xj1h;R&L6%U{5RXd?fxa+(2^VT` zNZCJ--^UC(aa5@F+hI-|6>42TC%7dAEoxM6M{W>T`Zr{i3WEbz>aNuiG`YsV- z5{ljs@d(jFB-xD*$m$xAb^W2TM#x5_-MT03x`#wpT+os~eNfTJbRJY#hAX~ioND`x zp>Aimy{&sV1m=egZW6)o{VCJO!6R*WAMteP4I8QFXfyL$cBRZ3H3RYfg<4CmWA?Bc zWcH}p0NgQoOytL7_KbaR{D;xy*bbMcM&2A#H1^8)8@N#b@YE*yW#$j;&t?0#o$?;# zixG1p*N=I3?3$>AaWMYHXe*J1w<Y^Hdy!j!WCjK=WGDpnAn45z5Mrqiw3i}S zb4Iaf1hpXO%@NS6lVKeE9C?{Xc-7N4l%POR4}wCx>S@H9fuOwR&g`1yNc7}Q!+k@G1As5!gM<%; z<2{^`F$BxOYH;@+8fB`sb{X6yIxZAw>CkrkeVw=d4B2iN)%E{P$p^JlOWGNu_rUZaIA;ZuF;6Gj8rME#M`!GJ#qpHM-WzuPa`O&rYu7IT4t2< zDkGD};lzupK>Rb5DH4L>moj^0T)}}(?m#PNa38qL9r%_z(8Z-6xWw(@7Q?Y$g3kV^ zF6mKz7~ih;;76j79;h8SUp^lOZk39hRufaPfO1Wq?wuOrArv~RZWjbl7-wX2X(wYY z196Qk8#m9{uCZhO0pc>5YtESefX_ipmsy8qTB3DU%`TwOjmm)&XUWRO{v%eLF7u$$ zF*5Tg?l@WY5m24CC_bNn+dX}Rvfs9U9XL}4*1&{3x{NAq;cU@2x!sy89A3+D6dvT- z5ptdLn6<84dQZJI^%CwXvQu0aN5y2Hv!-@&V4*yu4P}%!n&-;E8|~|JZV(@3oQuQ> zjHqEcYysg?qOgP&9}9}V3htN8gi!~9_BEHJPn(QF0&SqByho9i2_+>_}(tB9uv87ThDmex^oJ302w32F}pPEccNl z?B6;jaF$NI#^oxL5^r!@8Sw;-hgk6o+J0gt*UkmpHR7kV{nSkE8mSW=OW1=wJR29G zwpw+q+?xunl^YrG5;jhLggxIv;O~vVNqwNks%hmEH6iN|Cc<-UTNH5yLlC{DMC1(T zMH#gABco6ro+~3R)$1X+8(G)orz*xm@`Wvv26~11_LmMa7KNI*{*v?mTwi4OT+gsq zUC%($_Lt)P*I%l!rhbbvryz6Y1fF(MHT%ECIY*$%Z5f-;?v2K`YParNPStKf2Na_M zsFODFWC2^1NjooAWwKUycZU^hnd+h(O;u*(t4z`Iv8OWUKn&Vu1l9Ft=IAz7sM)@a zK5~&)A?4>6UC**Yy)AQG(eh|p&V-`nlWfbU6fM`{;U4K$37zDqF05jgEz=1Wg|2d& z+R!BFr4j!*SWbaa!9RteWR8*L7e8a1%s+0V_{WSKKi@csHyOkE=Zvwr=aL)w8r^Pc zk@!bQZq9QHy}mEQns}E}A?^ZatoU2N+BW#7)|b#@A=J`#Tci(0#Vzq6)Z zMkluu20oRT1-dFKT(xKsDrO)TFbbV5N0lQDGO@CN)d|ZLx+j(^+9ncZt*Omu*D#%3 zCQgARtph$r{20V<{027?NDpVYNP|=L!t*Q86>}jQ7x_#a)NItmZf{C3&;Np8;~0Ys3? zcKSH`jl+jp{qmTNXpq%wR&m})dCtZS9;m=5*I2|Y0K>Q9;c#(32$ixZ!0TnP=sa@* zb6U)28IA?aXGlW4ETP>s>PB8qZ7M&3=}iX(59a;1@7z=fNVS!;G}qBWTN{<~5m&QQ5< zGr9*WM%Y9ZW*{H0x88_&;ggToTCeq3zw6;O>DF^SBW<2aKkzJg(D7&(F0ACT3va}1 zulf+I{)JnZW5M8>vX$PcLZ>w=n#x|kcHM@JIWh8cu3A7;43^cfcD+xI`=#Nup-HmL zaA^Xb?!!EM3Z~y-ZvM$VZe6H0Io`ANk%9UYh};rc5s6pq%<){gE}2t6E~hIQ2fjL? zy2ul+T>yo?NSo#+{i8pcN#sE&Vf=RxL&6;X6}U=$pjkFu9U{D5w|P9 zZ`0}8ljG4+#H2kXPeB-$2>cUApQXi_P?7**0vugWi&`j2#61$6Nw{4jmN*ZNzDSF5 zf>QRZcdFhlSGjpkTmXxFy`Cd4W6u#4E>Itv(B6NGor7PXAlqK)G21Ie3bM@@x_Uh01*cqFih@HD|fnnCdgxHKXa)0^K>n|JJ zyD-y)paE+&4D8vSkYnAorDjwY--5%FE%ZxOpdjKJ`Fj#OXlVXf2oq z8SWq~#j*?weoNc&a`PQSFZ%`dfVJQV__!mqk3PaW8m?iKe|K}haXCNWux}3jDL2BR zx89*Goa1u6qe1j(dChOsq^@t^k{CxryHD+CZn)d(_!~GHt~&HhdL4G2b~FrrK~L+f z{q`=ux9XhCw949c{MEAl+FHV!rH_9BadHd+GDmZVk8xaXa5UVu-eLJC4l-|r_#AiC zR}+T#Y(DO27^)R(#e|bQcD6X0@A&50TWUM4?Nq`w34~-*B=PN%;C@puoevw)b0vck zn(qkLay&mA?(cG0%M{P4Je&o`Rb{_asu9}ziSJM0>6zh}Y zgAeUN5NY(C(b2PXeO^CidKM+i_jNP8^2dgEFXw%%`Xt+ao-wFx4d4%$X#h*q# z4INm8wvd9MxgA28Lm`NL^YEWO$c?nrUXcMC6 z4>|fx!%w4S8+s%)j{9CD?*^P8>}&YWnl&8ZXm}l~e(UDpUa8u&+Aqyai}d`C%yn}I zUhhJ|@9wgxd)>c9No=`Hl6b`wA|c5ARW#2@!lbdHAB5s z7Ik44y`4Q=zEi%=FSyfq9ejn0md}tU$mh$mnSW+pWS(a$*$Va;`?yRmOOOrw&8s*z8^mu~(bKS(b9mBXLU|Tgg9S%Zm4=|SIquT^*w5E-~M;L+2Fq3)6`~@H>8!1gVul`pPm+x zlEzfbiE@Hv_R8$!N+)HR?r3V0oS+LA8F5*%KvCZ`hamrxljda=2~kewz;e8+HYz>1 z-MXHdUXIt%-*~5{w+;&zai5*2aMJh+S2!&g^-B5_`qHNrCH?qXr0~vf^Ul*7l{MxB z)W#WmegE~??7Iojatz0E@4UnerBBv?PsjcYWq<87Zn5&$@|f(KWcb4eQ~1@RT-L5# zyWX0LRQyCCdZ`kR5;q0yGUfI*=wTWK%~ECI)d)PFjIXGMgREstg%|L;MpbbZ4n|s- zigWOO$2)`CliFvMj=g(hJTH_iQ`+mTZEowZ8xxELYWdE}IJvrBU;42kr9sY{Q!dN- ze@bb3k~gK)Kf*6gx%3F1mQo+XC#779;pe5)&*#HaF3sl^j;2=eZ$V#_e!Ko-Mes?{ z5fmQ>1QLs0PEEyOr79ITC~*vdT6K$+-#Hp|8OrsT_DQo%a7t2@pF$=-=2J-LCw~eo zA1y8LE)Q8)85kN!bjB6s!C9Y{aN6E!ziw@}%JS2!XRYQHFFbEJ{k(9=Yh3>%e%!89 z)p+N1)f9HBBv2Xw(QDVQ%N7Qw2McEBr{zt;RAj3CTJ2Tq*HCx?3eQ8XrmnT_MqMMG zf(%WD^ECmtrOV}ojwJ)$d8rvn{7A1)mwV@HQB^cB*xlxR*z^1& zxTwxO9`oE@>`3ak*Edw-P3_!^k1q1KO&)#ZF|@a)!f>7>K$QiG#FJZDJo_JVIWHb^ zS>X^?4;^|plRs31usdOgT>B`5m205)Q2BEZcHW{qoK&61+N;|XhtX!t-&+S0+<%Y3 zWEYdX$^sS1qA>+w@r@reGS&FTbR<(VnwVs&&ZwZ`$VH!`;`56>rs5wLN#GzERVJN+ zDcIPQ&o80_I4|;eYh{GZ;EP+q;Z4VMSVvf_qLCS4s5%-6;yB7_$HW-jstN#WTWcpqf%%dJHOY=_6jU?hxnW{|uph0p%tl>XM`MU1IH=Ne(!mJA^(vd_I6b8LQ#6E!+huq49+~>7Wd&|G3E0Wk&0^ zIlwF5T{Q=3*4bpPe+jGDN0F0p2>D6jQ5P)sPVGNob-76w`TqsWIEmcCi1FZZj1owB zFs8t^RnfNP6Kpw?sxqgvgjHo~k)M z$CV_Uzzji5fe+A2%VVMcl+~iDYpXjSsBY~|a9ghz)QGX*HU61P4)@OIQnC6+Zhp9T z-gn-G4c?R*40_MC1WQu!qhUG-)p+&1CA{t``OzIr9diL$wJ{gyUi=T6Ho8}aA6w5u zX)4C&bnwXDDVv4qktWo{TZW=WTsA874UXJ__>%{=$eCNrovi1+>-~#=Pa}G`G>Z!C z#jBbntiSi~xIm7XK`SpeE91}Abr{_K-b2zSpOM|@d#@llpZ?$fMWzGnNB4IDUIzaU DJ^3nG literal 0 HcmV?d00001 diff --git a/16/x_/modex/QIX2.PAS b/16/x_/modex/QIX2.PAS new file mode 100755 index 00000000..d1b59791 --- /dev/null +++ b/16/x_/modex/QIX2.PAS @@ -0,0 +1,210 @@ +{$E-,N+} +uses Crt, Modex; + +const + DEFVERT = 12; (* Vertex count *) + DEFREPL = 3; (* Repetition count *) + DEFQIXS = 2; (* Qixs *) + FADESPEED = 48; +type + TPoint = record + X, Y : integer; + end; + TRGB = record + R, G, B: byte; + end; + TQix = record + Color: integer; + Vert : array[ 0..DEFVERT-1, 0..DEFREPL-1 ] of TPoint; + Delta: array[ 0..DEFVERT-1 ] of TPoint; + end; +var + Page : integer; + MaxX, + MaxY : word; + Qix : array[ 0..DEFQIXS-1 ] of TQix; + Pal : array[ byte ] of TRGB; + +type + TReal = double; + TRPoint = record + X, Y: TReal; + end; + TMatrix = array[ 0..3, 0..3 ] of TReal; +var + M: TMatrix; + G: array[ 0..DEFVERT-1 ] of TRPoint; + C: array[ 0..DEFVERT-1 ] of TRPoint; + +procedure BumpPal( Idx, DR, DG, DB, Steps: integer ); +var + I: integer; +begin + for I:=1 to Steps do begin + Pal[Idx+1].R := Pal[Idx].R + DR; + Pal[Idx+1].G := Pal[Idx].G + DG; + Pal[Idx+1].B := Pal[Idx].B + DB; + Inc( Idx ); + end; +end; + +procedure InitPalette; +begin + with Pal[0] do begin R:=0; G:=0; B:=0; end; + with Pal[1] do begin R:=0; G:=0; B:=62; end; + BumpPal( 1, 0, 2, -2, 31 ); + BumpPal( 32, 2, -2, 0, 31 ); + BumpPal( 63, -2, 2, 2, 31 ); + BumpPal( 94, 2, 0, -2, 31 ); + BumpPal( 125, -2, -2, 2, 31 ); +end; + +procedure Init( var Qix: TQix; Color: integer ); +var + I: integer; +begin + FillChar( Qix.Vert, SizeOf(Qix.Vert), 0 ); + for I:=0 to DEFVERT-1 do begin + Qix.Vert[I, DEFREPL-1].X := Random( MaxX ); + Qix.Vert[I, DEFREPL-1].Y := Random( MaxY ); + Qix.Delta[I].X := Random(5)+1; + Qix.Delta[I].Y := Random(5)+1; + end; + Qix.Color := Color; + + (* Initialize matrix (Catmull-Rom) *) + M[0,0] := -1/2; M[0,1] := 3/2; M[0,2] := -3/2; M[0,3] := 1/2; + M[1,0] := 1; M[1,1] := -5/2; M[1,2] := 2; M[1,3] := -1/2; + M[2,0] := -1/2; M[2,1] := 0; M[2,2] := 1/2; M[2,3] := 0; + M[3,0] := 0; M[3,1] := 1; M[3,2] := 0; M[3,3] := 0; +end; + +procedure mxBezier( var Qix: TQix; I0, Idx, N: integer ); +var + I, J: integer; + T, T2, T3: TReal; + X0, Y0, X, Y: TReal; + Delta: TReal; +begin + (* Compute coefficients *) + for I:=0 to 3 do begin + C[I].X := 0; + for J:=0 to 3 do C[I].X := C[I].X + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].X; + C[I].Y := 0; + for J:=0 to 3 do C[I].Y := C[I].Y + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].Y; + end; + X0 := C[3].X; + Y0 := C[3].Y; + Delta := 1 / N; + T := 0; + for I:=1 to N do begin + T := T + Delta; + T2 := T*T; + T3 := T*T2; + X := C[0].X*T3 + C[1].X*T2 + C[2].X*T + C[3].X; + Y := C[0].Y*T3 + C[1].Y*T2 + C[2].Y*T + C[3].Y; + mxLine( Round(X0), Page+Round(Y0), Round(X), Page+Round(Y), Qix.Color, OP_SET ); + X0 := X; + Y0 := Y; + end; +end; + +procedure Plot( var Qix: TQix; Idx: integer ); +var + I, J: integer; +begin + for I:=0 to DEFVERT-1 do begin + mxBezier( Qix, I, Idx, 12 ); + end; +end; + +procedure Update( var Qix: TQix; Idx: integer ); +var + I: integer; +begin + for I:=0 to DEFVERT-1 do with Qix do begin + Inc( Vert[I,Idx].X, Delta[I].X ); + if( Vert[I,Idx].X < 0 ) then begin + Vert[I,Idx].X := 0; + Delta[I].X := Random( 5 )+1; + end; + if( Vert[I,Idx].X > MaxX ) then begin + Vert[I,Idx].X := MaxX; + Delta[I].X := -Random( 5 )-1; + end; + Inc( Vert[I,Idx].Y, Delta[I].Y ); + if( Vert[I,Idx].Y < 0 ) then begin + Vert[I,Idx].Y := 0; + Delta[I].Y := Random( 5 )+1; + end; + if( Vert[I,Idx].Y > MaxY ) then begin + Vert[I,Idx].Y := MaxY; + Delta[I].Y := -Random( 5 )-1; + end; + end; +end; + +procedure Copy( var Qix: TQix; Dest, Src: integer ); +var + I: integer; +begin + for I:=0 to DEFVERT-1 do with Qix do begin + Vert[I,Dest].X := Vert[I,Src].X; + Vert[I,Dest].Y := Vert[I,Src].Y; + end; +end; + +procedure AnimateQix; +var + Q, Idx, I, J, P, Count: integer; +begin + Count := 0; + P := DEFREPL-1; + I := 0; + J := 1; + repeat + mxSetClipRegion( 0, Page, MaxX+1, MaxY+1 ); + mxSetClip( TRUE ); + mxFillBox( 0, Page, MaxX+1, MaxY+1, 0, OP_SET ); + for Q:=0 to DEFQIXS-1 do begin + Copy( Qix[Q], I, P ); + Update( Qix[Q], I ); + for Idx:=0 to DEFREPL-1 do begin + Plot( Qix[Q], Idx ); + end; + end; + I := (I+1) mod DEFREPL; + J := (J+1) mod DEFREPL; + P := (P+1) mod DEFREPL; + Inc( Count ); + mxStartLine( Page ); + if( Count >= FADESPEED ) then begin + for Q:=0 to DEFQIXS-1 do begin + Inc( Qix[Q].Color ); + if( Qix[Q].Color > 156 ) then + Qix[Q].Color := 1; + end; + Count := 0; + end; + Page := 240-Page; + until( KeyPressed ); +end; + +var + I: integer; +begin + Randomize; + mxInit; + mxSetMode( MX_320x240 ); + mxGetScreenSize( MaxX, MaxY ); + for I:=0 to DEFQIXS-1 do + Init( Qix[I], (I*(155 div DEFQIXS)) mod 155 + 1 ); + InitPalette; + mxSetPalette( @Pal, 0, 157 ); + Page := 240; + Dec( MaxX ); + Dec( MaxY ); + AnimateQix; + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/x_/modex/README.TXT b/16/x_/modex/README.TXT new file mode 100755 index 00000000..306e8b9a --- /dev/null +++ b/16/x_/modex/README.TXT @@ -0,0 +1,8 @@ +ModeX - A graphical library for DOS programs +Copyright (c) 1993-1994 Alessandro Scotti +http://www.ascotti.org/ + +Please look at the above site in the "Art of..." and +then in the "Old programs" section for more information. + + diff --git a/16/x_/modex/SINCOS.INC b/16/x_/modex/SINCOS.INC new file mode 100755 index 00000000..6986eeeb --- /dev/null +++ b/16/x_/modex/SINCOS.INC @@ -0,0 +1,518 @@ +; +; SINCOS.INC - Sin/cos tables for THREED.ASM +; + +tblSin LABEL DWORD + DD 0 + DD 411733 + DD 823219 + DD 1234209 + DD 1644455 + DD 2053710 + DD 2461729 + DD 2868265 + DD 3273072 + DD 3675909 + DD 4076531 + DD 4474698 + DD 4870169 + DD 5262706 + DD 5652074 + DD 6038037 + DD 6420363 + DD 6798821 + DD 7173184 + DD 7543226 + DD 7908725 + DD 8269459 + DD 8625213 + DD 8975771 + DD 9320922 + DD 9660458 + DD 9994176 + DD 10321873 + DD 10643353 + DD 10958422 + DD 11266890 + DD 11568571 + DD 11863283 + DD 12150850 + DD 12431097 + DD 12703856 + DD 12968963 + DD 13226258 + DD 13475586 + DD 13716797 + DD 13949745 + DD 14174291 + DD 14390298 + DD 14597637 + DD 14796184 + DD 14985817 + DD 15166424 + DD 15337895 + DD 15500126 + DD 15653022 + DD 15796488 + DD 15930439 + DD 16054795 + DD 16169479 + DD 16274424 + DD 16369565 + DD 16454846 + DD 16530216 + DD 16595628 + DD 16651044 + DD 16696429 + DD 16731757 + DD 16757007 + DD 16772163 + DD 16777216 + DD 16772163 + DD 16757007 + DD 16731757 + DD 16696429 + DD 16651044 + DD 16595628 + DD 16530216 + DD 16454846 + DD 16369565 + DD 16274424 + DD 16169479 + DD 16054795 + DD 15930439 + DD 15796488 + DD 15653022 + DD 15500126 + DD 15337895 + DD 15166424 + DD 14985817 + DD 14796184 + DD 14597637 + DD 14390298 + DD 14174291 + DD 13949745 + DD 13716797 + DD 13475586 + DD 13226258 + DD 12968963 + DD 12703856 + DD 12431097 + DD 12150850 + DD 11863283 + DD 11568571 + DD 11266890 + DD 10958422 + DD 10643353 + DD 10321873 + DD 9994176 + DD 9660458 + DD 9320922 + DD 8975771 + DD 8625213 + DD 8269459 + DD 7908725 + DD 7543226 + DD 7173184 + DD 6798821 + DD 6420363 + DD 6038037 + DD 5652074 + DD 5262706 + DD 4870169 + DD 4474698 + DD 4076531 + DD 3675909 + DD 3273072 + DD 2868265 + DD 2461729 + DD 2053710 + DD 1644455 + DD 1234209 + DD 823219 + DD 411733 + DD 0 + DD -411733 + DD -823219 + DD -1234209 + DD -1644455 + DD -2053710 + DD -2461729 + DD -2868265 + DD -3273072 + DD -3675909 + DD -4076531 + DD -4474698 + DD -4870169 + DD -5262706 + DD -5652074 + DD -6038037 + DD -6420363 + DD -6798821 + DD -7173184 + DD -7543226 + DD -7908725 + DD -8269459 + DD -8625213 + DD -8975771 + DD -9320922 + DD -9660458 + DD -9994176 + DD -10321873 + DD -10643353 + DD -10958422 + DD -11266890 + DD -11568571 + DD -11863283 + DD -12150850 + DD -12431097 + DD -12703856 + DD -12968963 + DD -13226258 + DD -13475586 + DD -13716797 + DD -13949745 + DD -14174291 + DD -14390298 + DD -14597637 + DD -14796184 + DD -14985817 + DD -15166424 + DD -15337895 + DD -15500126 + DD -15653022 + DD -15796488 + DD -15930439 + DD -16054795 + DD -16169479 + DD -16274424 + DD -16369565 + DD -16454846 + DD -16530216 + DD -16595628 + DD -16651044 + DD -16696429 + DD -16731757 + DD -16757007 + DD -16772163 + DD -16777216 + DD -16772163 + DD -16757007 + DD -16731757 + DD -16696429 + DD -16651044 + DD -16595628 + DD -16530216 + DD -16454846 + DD -16369565 + DD -16274424 + DD -16169479 + DD -16054795 + DD -15930439 + DD -15796488 + DD -15653022 + DD -15500126 + DD -15337895 + DD -15166424 + DD -14985817 + DD -14796184 + DD -14597637 + DD -14390298 + DD -14174291 + DD -13949745 + DD -13716797 + DD -13475586 + DD -13226258 + DD -12968963 + DD -12703856 + DD -12431097 + DD -12150850 + DD -11863283 + DD -11568571 + DD -11266890 + DD -10958422 + DD -10643353 + DD -10321873 + DD -9994176 + DD -9660458 + DD -9320922 + DD -8975771 + DD -8625213 + DD -8269459 + DD -7908725 + DD -7543226 + DD -7173184 + DD -6798821 + DD -6420363 + DD -6038037 + DD -5652074 + DD -5262706 + DD -4870169 + DD -4474698 + DD -4076531 + DD -3675909 + DD -3273072 + DD -2868265 + DD -2461729 + DD -2053710 + DD -1644455 + DD -1234209 + DD -823219 + DD -411733 +tblCos LABEL DWORD + DD 16777216 + DD 16772163 + DD 16757007 + DD 16731757 + DD 16696429 + DD 16651044 + DD 16595628 + DD 16530216 + DD 16454846 + DD 16369565 + DD 16274424 + DD 16169479 + DD 16054795 + DD 15930439 + DD 15796488 + DD 15653022 + DD 15500126 + DD 15337895 + DD 15166424 + DD 14985817 + DD 14796184 + DD 14597637 + DD 14390298 + DD 14174291 + DD 13949745 + DD 13716797 + DD 13475586 + DD 13226258 + DD 12968963 + DD 12703856 + DD 12431097 + DD 12150850 + DD 11863283 + DD 11568571 + DD 11266890 + DD 10958422 + DD 10643353 + DD 10321873 + DD 9994176 + DD 9660458 + DD 9320922 + DD 8975771 + DD 8625213 + DD 8269459 + DD 7908725 + DD 7543226 + DD 7173184 + DD 6798821 + DD 6420363 + DD 6038037 + DD 5652074 + DD 5262706 + DD 4870169 + DD 4474698 + DD 4076531 + DD 3675909 + DD 3273072 + DD 2868265 + DD 2461729 + DD 2053710 + DD 1644455 + DD 1234209 + DD 823219 + DD 411733 + DD 0 + DD -411733 + DD -823219 + DD -1234209 + DD -1644455 + DD -2053710 + DD -2461729 + DD -2868265 + DD -3273072 + DD -3675909 + DD -4076531 + DD -4474698 + DD -4870169 + DD -5262706 + DD -5652074 + DD -6038037 + DD -6420363 + DD -6798821 + DD -7173184 + DD -7543226 + DD -7908725 + DD -8269459 + DD -8625213 + DD -8975771 + DD -9320922 + DD -9660458 + DD -9994176 + DD -10321873 + DD -10643353 + DD -10958422 + DD -11266890 + DD -11568571 + DD -11863283 + DD -12150850 + DD -12431097 + DD -12703856 + DD -12968963 + DD -13226258 + DD -13475586 + DD -13716797 + DD -13949745 + DD -14174291 + DD -14390298 + DD -14597637 + DD -14796184 + DD -14985817 + DD -15166424 + DD -15337895 + DD -15500126 + DD -15653022 + DD -15796488 + DD -15930439 + DD -16054795 + DD -16169479 + DD -16274424 + DD -16369565 + DD -16454846 + DD -16530216 + DD -16595628 + DD -16651044 + DD -16696429 + DD -16731757 + DD -16757007 + DD -16772163 + DD -16777216 + DD -16772163 + DD -16757007 + DD -16731757 + DD -16696429 + DD -16651044 + DD -16595628 + DD -16530216 + DD -16454846 + DD -16369565 + DD -16274424 + DD -16169479 + DD -16054795 + DD -15930439 + DD -15796488 + DD -15653022 + DD -15500126 + DD -15337895 + DD -15166424 + DD -14985817 + DD -14796184 + DD -14597637 + DD -14390298 + DD -14174291 + DD -13949745 + DD -13716797 + DD -13475586 + DD -13226258 + DD -12968963 + DD -12703856 + DD -12431097 + DD -12150850 + DD -11863283 + DD -11568571 + DD -11266890 + DD -10958422 + DD -10643353 + DD -10321873 + DD -9994176 + DD -9660458 + DD -9320922 + DD -8975771 + DD -8625213 + DD -8269459 + DD -7908725 + DD -7543226 + DD -7173184 + DD -6798821 + DD -6420363 + DD -6038037 + DD -5652074 + DD -5262706 + DD -4870169 + DD -4474698 + DD -4076531 + DD -3675909 + DD -3273072 + DD -2868265 + DD -2461729 + DD -2053710 + DD -1644455 + DD -1234209 + DD -823219 + DD -411733 + DD 0 + DD 411733 + DD 823219 + DD 1234209 + DD 1644455 + DD 2053710 + DD 2461729 + DD 2868265 + DD 3273072 + DD 3675909 + DD 4076531 + DD 4474698 + DD 4870169 + DD 5262706 + DD 5652074 + DD 6038037 + DD 6420363 + DD 6798821 + DD 7173184 + DD 7543226 + DD 7908725 + DD 8269459 + DD 8625213 + DD 8975771 + DD 9320922 + DD 9660458 + DD 9994176 + DD 10321873 + DD 10643353 + DD 10958422 + DD 11266890 + DD 11568571 + DD 11863283 + DD 12150850 + DD 12431097 + DD 12703856 + DD 12968963 + DD 13226258 + DD 13475586 + DD 13716797 + DD 13949745 + DD 14174291 + DD 14390298 + DD 14597637 + DD 14796184 + DD 14985817 + DD 15166424 + DD 15337895 + DD 15500126 + DD 15653022 + DD 15796488 + DD 15930439 + DD 16054795 + DD 16169479 + DD 16274424 + DD 16369565 + DD 16454846 + DD 16530216 + DD 16595628 + DD 16651044 + DD 16696429 + DD 16731757 + DD 16757007 + DD 16772163 diff --git a/16/x_/modex/THREED.ASM b/16/x_/modex/THREED.ASM new file mode 100755 index 00000000..5ecd3ba3 --- /dev/null +++ b/16/x_/modex/THREED.ASM @@ -0,0 +1,872 @@ +COMMENT / + Fixed-point math functions and 3D transforms + Copyright (c) 1993,94 by Alessandro Scotti +/ +WARN PRO +P386 +JUMPS +LOCALS + +INCLUDE MATH.INC + +PUBLIC tdFixedMul +PUBLIC tdGetNormal +PUBLIC tdRotate +PUBLIC tdGetSurfaceLight +PUBLIC tdSetLight +PUBLIC tdSetRotation +PUBLIC tdSetTranslation +PUBLIC tdTransform +PUBLIC tdTransformToImage +PUBLIC tdTransformLight +PUBLIC tdBackPlaneCull +PUBLIC tdSetPerspective + +;----------------------------------------------------------- +; +; Data segment +; +MATH_DATA SEGMENT USE16 PARA PUBLIC 'DATA' + ASSUME ds:MATH_DATA + +INCLUDE SINCOS.INC ; Fixed 8:24 sin/cos table + +XRotation TPOINT <> ; 3x3 rotation matrix +YRotation TPOINT <> +ZRotation TPOINT <> + +Translation TPOINT <> ; Translation vector + +Light TPOINT <> ; Light vector +AmbientLight DW 00 ; Ambient light + +XScale DD 10000h ; Scaling factor for X coordinate +YScale DD 10000h ; Scaling factor for Y coordinate +PerspectiveDistance DD 20000000h + +MATH_DATA ENDS + +;----------------------------------------------------------- +; +; Code segment +; +MATH_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MATH_TEXT, es:NOTHING, fs:NOTHING + +tdSetPerspective PROC PASCAL FAR + ARG Perspective:DWORD, \ + ScaleX:DWORD, \ + ScaleY:DWORD + USES ds + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + mov eax, [Perspective] + mov [PerspectiveDistance], eax + mov eax, [ScaleX] + mov [XScale], eax + mov eax, [ScaleY] + mov [YScale], eax + + ret +tdSetPerspective ENDP + + +;----------------------------------------------------------- +; +; Sets the rotation matrix. +; +; Input: +; RX = X-axis rotation angle +; RY = X-axis rotation angle +; RZ = X-axis rotation angle +; Output: +; none +; +tdSetRotation PROC PASCAL FAR + ARG RX:WORD, \ + RY:WORD, \ + RZ:WORD + USES ds, si, di + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + mov bx, [RZ] + mov si, [RY] + mov di, [RX] + shl bx, 2 + shl si, 2 + shl di, 2 + + push ebp ; We use EBP as a scratch register + +; Set X rotation + mov eax, tblCos[bx] + imul tblCos[si] + mov [XRotation.X], edx + + mov eax, tblSin[bx] + imul tblCos[si] + mov [XRotation.Y], edx + + mov eax, tblSin[si] + sar eax, 8 ; Convert fixed 8:24 to fixed 16:16 + mov [XRotation.Z], eax + +; Set Y rotation + mov eax, tblCos[bx] + imul tblSin[si] ; EDX:EAX = fixed 16:48 + shrd eax, edx, 24 ; EAX = fixed 8:24 + imul tblSin[di] ; EDX:EAX = fixed 16:48 + mov ebp, eax + mov ecx, edx + mov eax, tblSin[bx] + imul tblCos[di] + add eax, ebp + adc edx, ecx ; EDX:EAX = fixed 16:48 + neg edx + mov [YRotation.X], edx + + mov eax, tblSin[bx] + imul tblSin[si] + shrd eax, edx, 24 + imul tblSin[di] + mov ebp, eax + mov ecx, edx + mov eax, tblCos[bx] + imul tblCos[di] + sub eax, ebp + sbb edx, ecx + mov [YRotation.Y], edx + + mov eax, tblCos[si] + imul tblSin[di] + mov [YRotation.Z], edx + +; Set Z rotation + mov eax, tblCos[bx] + imul tblSin[si] + shrd eax, edx, 24 + imul tblCos[di] + mov ebp, eax + mov ecx, edx + mov eax, tblSin[bx] + imul tblSin[di] + sub eax, ebp + sbb edx, ecx + mov [ZRotation.X], edx + + mov eax, tblSin[bx] + imul tblSin[si] + shrd eax, edx, 24 + imul tblCos[di] + mov ebp, eax + mov ecx, edx + mov eax, tblCos[bx] + imul tblSin[di] + add eax, ebp + add edx, ecx + neg edx + mov [ZRotation.Y], edx + + mov eax, tblCos[si] + imul tblCos[di] + mov [ZRotation.Z], edx + + pop ebp ; Restore EBP + + ret +tdSetRotation ENDP + +;----------------------------------------------------------- +; +; Sets the translation vector. +; +; Input: +; TV = pointer to translation vector +; Output: +; none +; +tdSetTranslation PROC PASCAL FAR + ARG TV:DWORD + USES ds, es, di + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + les di, [TV] + mov eax, es:[di].X + mov [Translation.X], eax + mov eax, es:[di].Y + mov [Translation.Y], eax + mov eax, es:[di].Z + mov [Translation.Z], eax + + ret +tdSetTranslation ENDP + +;----------------------------------------------------------- +; +; Transforms an array of TPOINT. +; +; Input: +; Source = pointer to source array of TPOINT +; Dest = pointer to destination array of TPOINT +; Count = number of entries to transform +; Output: +; none +; +tdTransform PROC PASCAL FAR + ARG Source:DWORD, \ + Dest:DWORD, \ + Count:WORD + LOCAL Adjust:DWORD + USES ds, si, es, di, fs + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + lfs si, [Source] + les di, [Dest] + + ALIGN DWORD +@@Loop: +; Transform Z coordinate + mov eax, fs:[si].X + imul [ZRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [ZRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [ZRotation.Z] + add eax, ecx + adc edx, ebx + mov ebx, eax + shrd eax, edx, 16 + add eax, [Translation.Z] ; EAX = new Z coord (fixed 16:16) + mov es:[di].Z, eax +; Get perspective factor + mov ebx, [PerspectiveDistance] + sub eax, ebx + neg eax ; EAX = PD - Z + xor edx, edx + shld edx, eax, 16 + shl eax, 16 + idiv ebx ; EAX = fixed 16:16 result + mov [Adjust], eax + +; Transform X coordinate + mov eax, fs:[si].X + imul [XRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [XRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [XRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + add eax, [Translation.X] + imul [Adjust] + shrd eax, edx, 16 + mov es:[di].X, eax + +; Transform Y coordinate + mov eax, fs:[si].X + imul [YRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [YRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [YRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + add eax, [Translation.Y] + imul [Adjust] + shrd eax, edx, 16 + mov es:[di].Y, eax + + add si, SIZE TPOINT + add di, SIZE TPOINT + dec [Count] + jnz @@Loop + + ret +tdTransform ENDP + +;----------------------------------------------------------- +; +; Transforms an array of TPOINT into an array of TIMAGEPOINT. +; +; Input: +; Source = pointer to source array of TPOINT +; Dest = pointer to destination array of TIMAGEPOINT +; Count = number of entries to transform +; DeltaX = translation distance for the X coordinate +; DeltaY = translation distance for the Y coordinate +; Output: +; the maximum Z value +; +tdTransformToImage PROC PASCAL FAR + ARG Source:DWORD, \ + Dest:DWORD, \ + Count:WORD, \ + DeltaX:WORD, \ + DeltaY:WORD + LOCAL Adjust:DWORD, \ + Max:DWORD + USES ds, si, es, di, fs + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + lfs si, [Source] + les di, [Dest] + mov [Max], 80000000h + +@@Loop: +; Check max Z + mov eax, fs:[si].Z + cmp eax, [Max] + jle @@1 + mov [Max], eax +@@1: + +; Transform X coordinate + mov ax, WORD PTR fs:[si].X[2] + add ax, [DeltaX] + mov es:[di].IX, ax + +; Transform Y coordinate + mov ax, WORD PTR fs:[si].Y[2] + add ax, [DeltaY] + mov es:[di].IY, ax + + add si, SIZE TPOINT + add di, SIZE TIMAGEPOINT + dec [Count] + jnz @@Loop + + mov eax, [Max] + shld edx, eax, 16 + ret +tdTransformToImage ENDP + +;----------------------------------------------------------- +; +; Sets the light source. +; +; Input: +; Light = pointer to light vector +; Output: +; none +; +tdSetLight PROC PASCAL FAR + ARG L:DWORD + USES ds, es, di + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + les di, [L] + mov eax, es:[di].X + mov [Light.X], eax + mov eax, es:[di].Y + mov [Light.Y], eax + mov eax, es:[di].Z + mov [Light.Z], eax + + ret +tdSetLight ENDP + +;----------------------------------------------------------- +; +; Computes light intensity for an array of surfaces. +; +; Input: +; Normals = pointer to an array of surface normals +; Lights = pointer to an array of integer to be filled with +; light intensity +; Count = number of elements to transform +; Output: +; none +; +tdTransformLight PROC PASCAL FAR + ARG Normals:DWORD, \ + Lights:DWORD, \ + Count:WORD + USES ds, si, es, di, fs + + mov ax, SEG MATH_DATA + mov fs, ax + ASSUME fs:MATH_DATA + + lds si, [Normals] + les di, [Lights] + ASSUME ds:NOTHING + +; Intensity is given by the dot product between the Light vector and +; the surface normal +@@Loop: + mov eax, ds:[si].Z + imul [Light.Z] + mov ebx, eax + mov ecx, edx + mov eax, ds:[si].Y + imul [Light.Y] + add ebx, eax + adc ecx, edx + mov eax, ds:[si].X + imul [Light.X] + add eax, ebx + adc edx, ecx ; EDX:EAX = fixed 32:32 intensity + add dx, [AmbientLight] + test dx, dx + jg @@1 + xor dx, dx ; Return 0 for no light +@@1: + mov es:[di], dx + inc di + inc di + add si, SIZE TPOINT + dec [Count] + jnz @@Loop + + ASSUME fs:NOTHING + ret +tdTransformLight ENDP + +;----------------------------------------------------------- +; +; Returns the light value given the normal to a surface. +; +; Input: +; Normal = pointer to TPOINT surface normal vector +; Output: +; AX = light intensity (>=0) +; Notes: +; the normal is rotated according to the current setting. +; +tdGetSurfaceLight PROC PASCAL FAR + ARG Normal:DWORD + USES ds, esi, es, di + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + les di, [Normal] + +; Transform Z coordinate + mov eax, es:[di].X + imul [ZRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, es:[di].Y + imul [ZRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, es:[di].Z + imul [ZRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + imul [Light.Z] + shrd eax, edx, 16 + mov esi, eax + +; Transform X coordinate + mov eax, es:[di].X + imul [XRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, es:[di].Y + imul [XRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, es:[di].Z + imul [XRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + imul [Light.X] + shrd eax, edx, 16 + add esi, eax + +; Transform Y coordinate + mov eax, es:[di].X + imul [YRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, es:[di].Y + imul [YRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, es:[di].Z + imul [YRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + imul [Light.X] + shrd eax, edx, 16 + add eax, esi + shr eax, 16 + +; Add ambient light + add ax, [AmbientLight] + test ax, ax + jge @@Exit + xor ax, ax + +@@Exit: + ret +tdGetSurfaceLight ENDP + +;----------------------------------------------------------- +; +; Rotates an array of TPOINT. +; +; Input: +; Source = pointer to source array of TPOINT +; Dest = pointer to destination array of TPOINT +; Count = number of entries to transform +; Output: +; none +; +tdRotate PROC PASCAL FAR + ARG Source:DWORD, \ + Dest:DWORD, \ + Count:WORD + USES ds, si, es, di, fs + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + lfs si, [Source] + les di, [Dest] + +@@Loop: +; Transform Z coordinate + mov eax, fs:[si].X + imul [ZRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [ZRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [ZRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + mov es:[di].Z, eax + +; Transform X coordinate + mov eax, fs:[si].X + imul [XRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [XRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [XRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + mov es:[di].X, eax + +; Transform Y coordinate + mov eax, fs:[si].X + imul [YRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [YRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [YRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + mov es:[di].Y, eax + + add si, SIZE TPOINT + add di, SIZE TPOINT + dec [Count] + jnz @@Loop + + ret +tdRotate ENDP + +tdFixedMul PROC PASCAL FAR + ARG F1:DWORD, \ + F2:DWORD + + mov eax, [F1] + imul [F2] + shr eax, 16 + + ret +tdFixedMul ENDP + +;----------------------------------------------------------- +; +; Returns in EAX the square root of EDX:EAX. +; +subSqrt PROC NEAR + push esi + push edi + + add eax, eax + adc edx, 0 + mov eax, edx ; Just discard the low bits + + mov esi, eax + xor edi, edi + shld edi, esi, 16 + shl esi, 16 +@@Loop: + mov ebx, eax + mul eax + add eax, esi + adc edx, edi + shrd eax, edx, 1 + shr edx, 1 + div ebx + cmp eax, ebx + jne @@Loop + +; Adjust EAX + shl eax, 8 + + pop edi + pop esi + ret +subSqrt ENDP + +;----------------------------------------------------------- +; +; Finds the unitary normal to a given surface. +; +; Input: +; Dest = pointer to TPOINT (vector) result +; P1, P2, P3 = pointer to TPOINT points on surface +; Output: +; none +; Notes: +; the normal is given by the cross-product between (P3-P1) and +; (P2-P1), so its orientation depends on the parameters order. +; +tdGetNormal PROC PASCAL FAR + ARG Dest:DWORD, \ + P1:DWORD, \ + P2:DWORD, \ + P3:DWORD + LOCAL V1:TPOINT, \ + V2:TPOINT, \ + N:TPOINT + USES ds, si, es, di + +; Get vector V1 + lds si, [P1] + les di, [P3] + mov eax, es:[di].X + sub eax, ds:[si].X + mov [V1.X], eax + mov eax, es:[di].Y + sub eax, ds:[si].Y + mov [V1.Y], eax + mov eax, es:[di].Z + sub eax, ds:[si].Z + mov [V1.Z], eax + +; Get vector V2 + les di, [P2] + mov eax, es:[di].X + sub eax, ds:[si].X + mov [V2.X], eax + mov eax, es:[di].Y + sub eax, ds:[si].Y + mov [V2.Y], eax + mov eax, es:[di].Z + sub eax, ds:[si].Z + mov [V2.Z], eax + +; Get normal vector (V1 x V2) + mov eax, [V1.Z] + imul [V2.Y] + mov ebx, eax + mov ecx, edx + mov eax, [V1.Y] + imul [V2.Z] + sub eax, ebx + sbb edx, ecx + shrd eax, edx, 16 + mov [N.X], eax + + mov eax, [V1.X] + imul [V2.Z] + mov ebx, eax + mov ecx, edx + mov eax, [V1.Z] + imul [V2.X] + sub eax, ebx + sbb edx, ecx + shrd eax, edx, 16 + mov [N.Y], eax + + mov eax, [V1.Y] + imul [V2.X] + mov ebx, eax + mov ecx, edx + mov eax, [V1.X] + imul [V2.Y] + sub eax, ebx + sbb edx, ecx + shrd eax, edx, 16 + mov [N.Z], eax + +; Get normal length + mov eax, [N.X] + imul eax + mov ebx, eax + mov ecx, edx + mov eax, [N.Y] + imul eax + add ebx, eax + adc ecx, edx + mov eax, [N.Z] + imul eax + add eax, ebx + adc edx, ecx ; EDX:EAX = N.X*N.X + N.Y*N.Y + N.Z*N.Z + call subSqrt ; EAX = normal length + mov ebx, eax + +; Adjust vector and save it + les di, [Dest] + mov eax, [N.X] + cdq + shld edx, eax, 16 + shl eax, 16 + idiv ebx + mov es:[di].X, eax + mov eax, [N.Y] + cdq + shld edx, eax, 16 + shl eax, 16 + idiv ebx + mov es:[di].Y, eax + mov eax, [N.Z] + cdq + shld edx, eax, 16 + shl eax, 16 + idiv ebx + mov es:[di].Z, eax + + ret +tdGetNormal ENDP + +TPOLY STRUC + Vtx DW 4 DUP(?) +TPOLY ENDS + +;----------------------------------------------------------- +; +; Performs surface removal on an array of polygons. +; +; Input: +; Poly = pointer to an array of TPOLY +; Vertex = pointer to an array of TPOINT +; Dest = pointer to an array of integer +; Count = number of polygons to check +; Step = size of TPOLY structure +; Output: +; if the n-th polygon is invisible the n-th entry of the +; Dest array is set to -1, other entries are not modified +; (so it's possible to use the Light array for Dest, because +; the light intensity is always >= 0) +; +tdBackPlaneCull PROC PASCAL FAR + ARG Step:WORD, \ + Poly:DWORD, \ + Vertex:DWORD, \ + Dest:DWORD, \ + Count:WORD + USES ds, si, es, di, fs + ASSUME ds:NOTHING + + mov ds, WORD PTR Vertex[2] + les di, [Poly] + mov fs, WORD PTR Dest[2] + +@@Loop: + mov ax, es:[di].Vtx[2] ; Index of 2nd vertex + shl ax, 2 + mov bx, ax + shl ax, 1 + add bx, ax ; BX = index*SIZE TPOINT + add bx, WORD PTR [Vertex] ; BX = offset of 2nd vertex + mov ax, es:[di].Vtx[4] ; Index of 3rd vertex + shl ax, 2 + mov si, ax + shl ax, 1 + add si, ax + add si, WORD PTR [Vertex] ; SI = offset of 3rd vertex + mov ecx, ds:[si].X + sub ecx, ds:[bx].X ; ECX = V3.X-V2.X + mov edx, ds:[si].Y + sub edx, ds:[bx].Y ; EDX = V3.Y-V2.Y + mov ax, es:[di].Vtx[0] ; Index of 1st vertex + shl ax, 2 + mov si, ax + shl ax, 1 + add si, ax + add si, WORD PTR [Vertex] ; SI = offset of 1st vertex + mov eax, ds:[si].X + sub eax, ds:[bx].X ; EAX = V1.X-V2.X + mov esi, ds:[si].Y + sub esi, ds:[bx].Y ; ESI = V1.Y-V2.Y + imul edx + mov ebx, eax + xchg ecx, edx ; ECX:EBX = (V1.X-V2.X)*(V3.Y-V2.Y) + mov eax, esi + imul edx ; EDX:EAX = (V1.Y-V2.Y)*(V3.X-V2.X) + sub eax, ebx + sbb edx, ecx + jl @@Next ; Polygon is visible + mov bx, WORD PTR [Dest] ; FS:BX -> current Dest entry + mov WORD PTR fs:[bx], -1 ; Remove polygon +@@Next: + add WORD PTR [Dest], 2 ; Next entry for dest + add di, [Step] ; Next polygon + dec [Count] + jnz @@Loop + + ret +tdBackPlaneCull ENDP + +MATH_TEXT ENDS +END diff --git a/16/x_/modex/THREED.H b/16/x_/modex/THREED.H new file mode 100755 index 00000000..b993ef86 --- /dev/null +++ b/16/x_/modex/THREED.H @@ -0,0 +1,32 @@ +typedef struct { + long x, y, z; +} TVECTOR; + +#define PVECTOR TVECTOR far * + +#define TPOINT TVECTOR +#define PPOINT PVECTOR + +#define VPTR void far * + +#ifdef __cplusplus +extern "C" { +#endif + +long far pascal tdFixedMul( long, long ); +int far pascal tdGetSurfaceLight( PPOINT ); +long far pascal tdTransformToImage( VPTR, VPTR, short, short, short ); + +void far pascal tdBackPlaneCull( VPTR, VPTR, VPTR, short, short ); +void far pascal tdGetNormal( VPTR, PPOINT, PPOINT, PPOINT ); +void far pascal tdRotate( VPTR, VPTR, short ); +void far pascal tdSetLight( PVECTOR ); +void far pascal tdSetRotation( short, short, short ); +void far pascal tdSetTranslation( PVECTOR ); +void far pascal tdSetPerspective( long, long, long ); +void far pascal tdTransform( VPTR, VPTR, short ); +void far pascal tdTransformLight( VPTR, VPTR, short ); + +#ifdef __cplusplus +} +#endif diff --git a/16/x_/modex/THREED.PAS b/16/x_/modex/THREED.PAS new file mode 100755 index 00000000..8b712c9d --- /dev/null +++ b/16/x_/modex/THREED.PAS @@ -0,0 +1,40 @@ +unit ThreeD; +interface + +type + TVector = record + X, Y, Z : longint; + end; + TPoint = TVector; + +function tdFixedMul( F1, F2: longint ): longint; +function tdGetSurfaceLight( var Normal: TPoint ): integer; +function tdTransformToImage( var Source, Dest; Count, DeltaX, DeltaY: integer ): longint; + +procedure tdBackPlaneCull( var Poly, Vertex, Dest; Count, Step: word ); +procedure tdGetNormal( var Dest, P1, P2, P3: TVector ); +procedure tdRotate( var Source, Dest; Count: word ); +procedure tdSetLight( var Light: TVector ); +procedure tdSetRotation( RX, RY, RZ: word ); +procedure tdSetTranslation( var TV: TVector ); +procedure tdSetPerspective( PD, XF, YF: longint ); +procedure tdTransform( var Source, Dest; Count: word ); +procedure tdTransformLight( var Source, Dest; Count: word ); + +implementation + +function tdGetSurfaceLight; external; +procedure tdSetRotation( RX, RY, RZ: word ); external; +procedure tdGetNormal; external; +procedure tdSetTranslation( var TV: TVector ); external; +procedure tdTransform( var Source, Dest; Count: word ); external; +procedure tdRotate; external; +function tdTransformToImage; external; +procedure tdSetLight( var Light: TVector ); external; +procedure tdSetPerspective; external; +procedure tdTransformLight; external; +function tdFixedMul( F1, F2: longint ): longint; external; +procedure tdBackPlaneCull; external; +{$L THREED} + +end. diff --git a/16/x_/mxbb.asm b/16/x_/mxbb.asm new file mode 100755 index 00000000..ac6668ce --- /dev/null +++ b/16/x_/mxbb.asm @@ -0,0 +1,278 @@ +;----------------------------------------------------------- +; +; MXBB.ASM - Bit block transfer +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxBitBlt + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN subHorizontalLineInfo : NEAR + +EXTRN mx_VideoSegment : WORD +EXTRN mx_BytesPerLine : WORD + +;----------------------------------------------------------- +; +; Moves a block of video memory. +; +; Input: +; SX, SY = source coordinates +; Width = source width +; Height = source height +; DX, DY = destination coordinates +; Output: +; none +; +; Note: overlapping regions are not allowed. +; +mxBitBlt PROC FAR + ARG DestY:WORD, \ + DestX:WORD, \ + Height:WORD, \ + Width:WORD, \ + SY:WORD, \ + SX:WORD = ARG_SIZE + LOCAL PlaneWidth:WORD:4, \ + SourceOffset:WORD, \ + DestOffset:WORD, \ + Count:BYTE, \ + ReadPlane:BYTE, \ + WritePlane:BYTE, \ + LeftMask:BYTE, \ + RightMask:BYTE = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, es, di + +; Exit now if null width + cmp [Width], 0 + je @@Exit + +; Calls the proper procedure to handle transfer + mov ax, [SX] + and al, 03h ; AL = source plane + mov dx, [DestX] + and dl, 03h ; DL = destination plane + mov bx, OFFSET subPlaneBlt + cmp al, dl ; Same source and destination plane? + jne @@BitBlt ; No, use slow procedure + mov bx, OFFSET subMoveBlt +@@BitBlt: + call bx + +@@Exit: + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE + +;----------------------------------------------------------- +; Uses write mode 1 for maximum speed. Only works if source +; and destination are plane-aligned. +; +subMoveBlt PROC NEAR +; Get horizontal line info and address of destination + mov bx, [DestX] + mov ax, [DestY] + mov cx, [Width] + call subHorizontalLineInfo + mov [LeftMask], al + mov [RightMask], ah + mov [Width], cx + +; Setup segments + mov ax, [mx_VideoSegment] + mov ds, ax + mov es, ax + +; Get address of source pixel + mov ax, [SY] + mul [mx_BytesPerLine] + mov si, [SX] + .shr si, 2 + add si, ax + +; Set write mode 1 + mov dx, GDC + mov ax, 4105h + out dx, ax + cld + +; Move left block +@@L0: + mov ah, [LeftMask] + or ah, ah + jz @@C0 + mov dx, TS + mov al, 02h + out dx, ax ; Set write plane mask + mov ax, [mx_BytesPerLine] + dec ax + mov cx, [Height] + .push si, di +@@L1: + movsb + add si, ax + add di, ax + dec cx + jnz @@L1 + .pop si, di + inc si + inc di + +; Move center block +@@C0: + mov bx, [Width] + test bx, bx + jz @@R0 + mov dx, TS + mov ax, 0F02h + out dx, ax ; Enable all planes + mov ax, [mx_BytesPerLine] + sub ax, bx + mov dx, [Height] + .push si, di +@@C1: + mov cx, bx ; CX = image width + rep movsb ; Cannot use "movsw" here! + add si, ax ; Next scan line + add di, ax ; Next scan line + dec dx ; All lines processed? + jnz @@C1 ; No, continue + .pop si, di + add si, bx + add di, bx + +; Move right block +@@R0: + mov ah, [RightMask] + or ah, ah + jz @@Done + mov dx, TS + mov al, 02h + out dx, ax ; Set write plane mask + mov ax, [mx_BytesPerLine] + dec ax + mov cx, [Height] +@@R1: + movsb + add si, ax + add di, ax + dec cx + jnz @@R1 + +@@Done: + mov dx, GDC + mov ax, 4005h + out dx, ax ; Restore write mode 0 + +@@Exit: + ret +subMoveBlt ENDP + +;----------------------------------------------------------- +; Moves one plane at a time. +; +subPlaneBlt PROC NEAR +; Compute extra bytes and width count for each plane + mov cx, [Width] + mov bx, cx + shr bx, 1 + shr bx, 1 ; Width for each plane + and cl, 03h + mov al, 00001000b + shr al, cl + mov si, 3 SHL 1 +@@PatchLoop: + mov PlaneWidth[si], bx + shr al, 1 + adc bx, 0 + dec si + dec si + jge @@PatchLoop + +; Get pixel addresses + mov ax, [mx_VideoSegment] + mov ds, ax + mov es, ax + mov ax, [SY] + mul [mx_BytesPerLine] + mov si, [SX] + shr si, 1 + shr si, 1 + add si, ax ; DS:SI points to source + mov [SourceOffset], si + mov ax, [DestY] + mul [mx_BytesPerLine] + mov di, [DestX] + shr di, 1 + shr di, 1 + add di, ax ; ES:DI points to destination + mov [DestOffset], di + +; Adjust plane for output to VGA registers + mov ax, [SX] + and al, 03h + mov [ReadPlane], al + mov cx, [DestX] + and cl, 03h + mov al, 00010001b + shl al, cl + mov [WritePlane], al + +; Ready to move now + cld + mov [Count], 4 ; Four planes + lea bx, PlaneWidth ; SS:[BX] = width in bytes for plane +@@PlaneLoop: + cmp WORD PTR ss:[bx], 0 + je @@Done + mov ah, [WritePlane] + and ah, 0Fh + mov al, 02h + mov dx, TS + out dx, ax ; Select write plane + mov ah, [ReadPlane] + mov al, 04h + mov dx, GDC + out dx, ax ; Select read plane + mov dx, [Height] + mov ax, [mx_BytesPerLine] + sub ax, ss:[bx] ; AX = extra bytes per line +@@Loop: + mov cx, ss:[bx] + shr cx, 1 + rep movsw + rcl cx, 1 + rep movsb + add si, ax + add di, ax + dec dx + jnz @@Loop ; Repeat for all lines + inc bx + inc bx ; Select width for next plane + inc [ReadPlane] + and [ReadPlane], 03h ; Should be faster on 386 using + jnz @@ReadPlaneOk ; BTR and ADC... + inc [SourceOffset] +@@ReadPlaneOk: + rol [WritePlane], 1 + adc [DestOffset], 0 + mov si, [SourceOffset] + mov di, [DestOffset] + dec [Count] + jnz @@PlaneLoop ; Repeat for all planes + +@@Done: + ret +subPlaneBlt ENDP + +mxBitBlt ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxcc.asm b/16/x_/mxcc.asm new file mode 100755 index 00000000..4f78adb9 --- /dev/null +++ b/16/x_/mxcc.asm @@ -0,0 +1,644 @@ +;----------------------------------------------------------- +; +; MXCC.ASM - Fast clip line function +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC xsubClipLine + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD +EXTRN mx_VideoSegment : WORD + +EXTRN mx_ClipX1 : WORD +EXTRN mx_ClipY1 : WORD +EXTRN mx_ClipX2 : WORD +EXTRN mx_ClipY2 : WORD + +tblGroups LABEL WORD + DW 10, tbl00 + DW 10, tbl10 + DW 9, tbl20 + DW -1, 0 + DW 10, tbl40 + DW 10, tbl50 + DW 9, tbl60 + DW -1, 0 + DW 6, tbl80 + DW 6, tbl90 + DW 5, tblA0 + DW -1, 0 + DW -1, 0 + DW -1, 0 + DW -1, 0 + DW -1, 0 +tbl00 DW cc00, cc01, cc02, ccFF, cc04, cc05, cc06, ccFF, cc08, cc09, cc0A +tbl10 DW cc10, ccFF, cc12, ccFF, cc14, ccFF, cc16, ccFF, cc18, ccFF, cc1A +tbl20 DW cc20, cc21, ccFF, ccFF, cc24, cc25, ccFF, ccFF, cc28, cc29 +tbl40 DW cc40, cc41, cc42, ccFF, ccFF, ccFF, ccFF, ccFF, cc48, cc49, cc4A +tbl50 DW cc50, ccFF, cc52, ccFF, ccFF, ccFF, ccFF, ccFF, cc58, ccFF, cc5A +tbl60 DW cc60, cc61, ccFF, ccFF, ccFF, ccFF, ccFF, ccFF, cc68, cc69 +tbl80 DW cc80, cc81, cc82, ccFF, cc84, cc85, cc86 +tbl90 DW cc90, ccFF, cc92, ccFF, cc94, ccFF, cc96 +tblA0 DW ccA0, ccA1, ccFF, ccFF, ccA4, ccA5 + +ccTT: clc + ret +ccFF: stc + ret + +; Group 00 ------------------------------------------------- +; +cc00: + clc + ret +cc01: + jmp ClipQLeft +cc02: + jmp ClipQRight +cc04: + jmp ClipQTop +cc05: + call ClipQLeft + cmp si, [mx_ClipY1] + jge ccTT + jmp ClipQTop +cc06: + call ClipQRight + cmp si, [mx_ClipY1] + jge ccTT + jmp ClipQTop +cc08: + jmp ClipQBottom +cc09: + call ClipQLeft + cmp si, [mx_ClipY2] + jle ccTT + jmp ClipQBottom +cc0A: + call ClipQRight + cmp si, [mx_ClipY2] + jle ccTT + jmp ClipQBottom + +; Group 10 ------------------------------------------------- +; +cc10FF: + stc + ret +cc10TT: + clc + ret +cc10: + jmp ClipPLeft +cc12: + call ClipPLeft + jmp ClipQRight +cc14: + call ClipPLeft + cmp bx, [mx_ClipY1] + jl cc10FF + jmp ClipQTop +cc16: + call ClipPLeft + cmp bx, [mx_ClipY1] + jl cc10FF + call ClipQTop + cmp cx, [mx_ClipX2] + jle cc10TT + jmp ClipQRight +cc18: + call ClipPLeft + cmp bx, [mx_ClipY2] + jg cc10FF + jmp ClipQBottom +cc1A: + call ClipPLeft + cmp bx, [mx_ClipY2] + jg cc10FF + call ClipQBottom + cmp cx, [mx_ClipX2] + jle cc10TT + jmp ClipQRight + +; Group 20 ------------------------------------------------- +; +cc20TT: + clc + ret +cc20FF: + stc + ret +cc20: + jmp ClipPRight +cc21: + call ClipPRight + jmp ClipQLeft +cc24: + call ClipPRight + cmp bx, [mx_ClipY1] + jl cc20FF + jmp ClipQTop +cc25: + call ClipPRight + cmp bx, [mx_ClipY1] + jl cc20FF + call ClipQTop + cmp cx, [mx_ClipX1] + jge cc20TT + jmp ClipQLeft +cc28: + call ClipPRight + cmp bx, [mx_ClipY2] + jg cc20FF + jmp ClipQBottom +cc29: + call ClipPRight + cmp bx, [mx_ClipY2] + jg cc20FF + call ClipQBottom + cmp cx, [mx_ClipX1] + jge cc20TT + jmp ClipQLeft + +; Group 40 ------------------------------------------------- +; +cc40TT: + clc + ret +cc40FF: + stc + ret +cc40: + jmp ClipPTop +cc41: + call ClipPTop + cmp di, [mx_ClipX1] + jl cc40FF + call ClipQLeft + cmp si, [mx_ClipY1] + jge cc40TT + jmp ClipQTop +cc42: + call ClipPTop + cmp di, [mx_ClipX2] + jg cc40FF + jmp ClipQRight +cc48: + call ClipPTop + jmp ClipQBottom +cc49: + call ClipPTop + cmp di, [mx_ClipX1] + jl cc40FF + call ClipQLeft + cmp si, [mx_ClipY2] + jle cc40TT + jmp ClipQBottom +cc4A: + call ClipPTop + cmp di, [mx_ClipX2] + jg cc40FF + call ClipQRight + cmp si, [mx_ClipY2] + jle cc40TT + jmp ClipQBottom + + +; Group 50 ------------------------------------------------- +; +cc50TT: + clc + ret +cc50FF: + stc + ret +cc50: + call ClipPLeft + cmp bx, [mx_ClipY1] + jge cc50TT + jmp ClipPTop +cc52: + call ClipQRight + cmp si, [mx_ClipY1] + jl cc50FF + call ClipPTop + cmp di, [mx_ClipX1] + jge cc50TT + jmp ClipPLeft +cc58: + call ClipQBottom + cmp cx, [mx_ClipX1] + jl cc50FF + call ClipPTop + cmp di, [mx_ClipX1] + jge cc50TT + jmp ClipPLeft +cc5A: + call ClipPLeft + cmp bx, [mx_ClipY2] + jg cc50FF + call ClipQRight + cmp bx, [mx_ClipY1] + jl cc50FF + cmp si, [mx_ClipY2] + jle cc50TT + jmp ClipQBottom + +; Group 60 ------------------------------------------------- +; +cc60TT: + clc + ret +cc60FF: + stc + ret +cc60: + call ClipPRight + cmp bx, [mx_ClipY1] + jge cc60TT + jmp ClipPTop +cc61: + call ClipQLeft + cmp si, [mx_ClipY2] + jl cc60FF + call ClipPTop + cmp di, [mx_ClipX2] + jle cc60TT + jmp ClipPRight +cc68: + call ClipQBottom + cmp cx, [mx_ClipX2] + jg cc60FF + call ClipPRight + cmp bx, [mx_ClipY1] + jge cc60TT + jmp ClipPTop +cc69: + call ClipQLeft + cmp si, [mx_ClipY1] + jl cc60FF + call ClipPRight + cmp bx, [mx_ClipY2] + jg cc60FF + cmp si, [mx_ClipY2] + jle cc69_1 + call ClipQBottom +cc69_1: + cmp bx, [mx_ClipY1] + jge cc60TT + jmp ClipPTop + +; Group 80 ------------------------------------------------- +; +cc80TT: + clc + ret +cc80FF: + stc + ret +cc80: + jmp ClipPBottom +cc81: + call ClipPBottom + cmp di, [mx_ClipX1] + jl cc80FF + jmp ClipQLeft +cc82: + call ClipPBottom + cmp di, [mx_ClipX2] + jg cc80FF + jmp ClipQRight +cc84: + call ClipPBottom + jmp ClipQTop +cc85: + call ClipPBottom + cmp di, [mx_ClipX1] + jl cc80FF + call ClipQLeft + cmp si, [mx_ClipY1] + jge cc80FF + jmp ClipQTop +cc86: + call ClipPBottom + cmp di, [mx_ClipX2] + jg cc80FF + call ClipQRight + cmp si, [mx_ClipY1] + jge cc80TT + jmp ClipQTop + +; Group 90 ------------------------------------------------- +; +cc90TT: + clc + ret +cc90FF: + stc + ret +cc90: + call ClipPLeft + cmp bx, [mx_ClipY2] + jle cc90TT + jmp ClipPBottom +cc92: + call ClipQRight + cmp si, [mx_ClipY2] + jg cc90FF + call ClipPBottom + cmp di, [mx_ClipX1] + jge cc90TT + jmp ClipPLeft +cc94: + call ClipQTop + cmp cx, [mx_ClipX1] + jl cc90FF + call ClipPLeft + cmp bx, [mx_ClipY2] + jle cc90TT + jmp ClipPBottom +cc96: + call ClipPLeft + cmp bx, [mx_ClipY1] + jl cc90FF + call ClipQRight + cmp si, [mx_ClipY2] + jg cc90FF + cmp bx, [mx_ClipY2] + jle cc96_1 + call ClipPBottom +cc96_1: + cmp si, [mx_ClipY1] + jge cc90TT + jmp ClipQTop + +; Group A0 ------------------------------------------------- +; +ccA0TT: + clc + ret +ccA0FF: + stc + ret +ccA0: + call ClipPRight + cmp bx, [mx_ClipY2] + jle ccA0TT + jmp ClipPBottom +ccA1: + call ClipQLeft + cmp si, [mx_ClipY2] + jg ccA0FF + call ClipPBottom + cmp di, [mx_ClipX2] + jle ccA0TT + jmp ClipPRight +ccA4: + call ClipQTop + cmp cx, [mx_ClipX2] + jg ccA0FF + call ClipPRight + cmp bx, [mx_ClipY2] + jle ccA0TT + jmp ClipPBottom +ccA5: + call ClipQLeft + cmp si, [mx_ClipY2] + jg ccA0FF + call ClipPRight + cmp bx, [mx_ClipY1] + jl ccA0FF + cmp si, [mx_ClipY1] + jge ccA5_1 + call ClipQTop +ccA5_1: + cmp bx, [mx_ClipY2] + jle ccA0TT + jmp ClipPBottom + +; Y1 = (Y2-Y1)*(mx_ClipX1-X1)/(X2-X1)+Y1 = (SI-BX)*(mx_ClipX1-DI)/(CX-DI)+BX +; X1 = mx_ClipX1 +ClipPLeft: + mov ax, si + sub ax, bx + mov dx, [mx_ClipX1] + sub dx, di + imul dx + mov bp, cx + sub bp, di + idiv bp + add bx, ax + mov di, [mx_ClipX1] + clc + ret + +; Y1 = (Y2-Y1)*(mx_ClipX2-X1)/(X2-X1)+Y1 = (SI-BX)*(mx_ClipX2-DI)/(CX-DI)+BX +; X1 = mx_ClipX2 +ClipPRight: + mov ax, si + sub ax, bx + mov dx, [mx_ClipX2] + sub dx, di + imul dx + mov bp, cx + sub bp, di + idiv bp + add bx, ax + mov di, [mx_ClipX2] + clc + ret + +; X1 = (X2-X1)*(mx_ClipY2-Y1)/(Y2-Y1)+X1 = (CX-DI)*(mx_ClipY2-BX)/(SI-BX)+DI +; Y1 = mx_ClipY2 +ClipPBottom: + mov ax, cx + sub ax, di + mov dx, [mx_ClipY2] + sub dx, bx + imul dx + mov bp, si + sub bp, bx + idiv bp + add di, ax + mov bx, [mx_ClipY2] + clc + ret + +; X1 = (X2-X1)*(mx_ClipY1-Y1)/(Y2-Y1)+X1 = (CX-DI)*(mx_ClipY1-BX)/(SI-BX)+DI +; Y1 = mx_ClipY1 +ClipPTop: + mov ax, cx + sub ax, di + mov dx, [mx_ClipY1] + sub dx, bx + imul dx + mov bp, si + sub bp, bx + idiv bp + add di, ax + mov bx, [mx_ClipY1] + clc + ret + +; Y2 = (Y1-Y2)*(mx_ClipX1-X2)/(X1-X2)+Y2 = (BX-SI)*(mx_ClipX1-CX)/(DI-CX)+SI +; X2 = mx_ClipX1 +ClipQLeft: + mov ax, bx + sub ax, si + mov dx, [mx_ClipX1] + sub dx, cx + imul dx + mov bp, di + sub bp, cx + idiv bp + add si, ax + mov cx, [mx_ClipX1] + clc + ret + +; Y2 = (Y1-Y2)*(mx_ClipX2-X2)/(X1-X2)+Y2 = (BX-SI)*(mx_ClipX2-CX)/(DI-CX)+SI +; X2 = mx_ClipX1 +ClipQRight: + mov ax, bx + sub ax, si + mov dx, [mx_ClipX2] + sub dx, cx + imul dx + mov bp, di + sub bp, cx + idiv bp + add si, ax + mov cx, [mx_ClipX2] + clc + ret + +; X2 = (X1-X2)*(mx_ClipY2-Y2)/(Y1-Y2)+X2 = (DI-CX)*(mx_ClipY2-SI)/(BX-SI)+CX +; Y2 = mx_ClipY1 +ClipQBottom: + mov ax, di + sub ax, cx + mov dx, [mx_ClipY2] + sub dx, si + imul dx + mov bp, bx + sub bp, si + idiv bp + add cx, ax + mov si, [mx_ClipY2] + clc + ret + +; X2 = (X1-X2)*(mx_ClipY1-Y2)/(Y1-Y2)+X2 = (DI-CX)*(mx_ClipY1-SI)/(BX-SI)+CX +; Y2 = mx_ClipY1 +ClipQTop: + mov ax, di + sub ax, cx + mov dx, [mx_ClipY1] + sub dx, si + imul dx + mov bp, bx + sub bp, si + idiv bp + add cx, ax + mov si, [mx_ClipY1] + clc + ret + +;----------------------------------------------------------- +; +; Checks the coordinates of a line against the active +; clip region. +; Uses the Sobkow-Pospisil-Yang (SPY) algorithm: this was +; supposed to be twice as fast as Cohen-Sutherland, but my +; tests show only a very small increase in speed and a noticeable +; increase of the program size! Maybe this is caused by the +; slow speed of VGA cards, so probably a better test should +; be performed with lines drawn in RAM. +; +; Input: +; AX, BX = X1, Y1 +; CX, DX = X2, Y2 +; Output: +; CF = set if line is full clipped +; AX, BX = clipped X1, Y1 +; CX, DX = clipped X2, Y2 +; Note: +; destroys SI, DI +; +xsubClipLine PROC NEAR + push bp + xor si, si ; SPY code + + cmp dx, [mx_ClipY2] + jle @@1 + or si, 08h + jmp @@2 +@@1: + cmp dx, [mx_ClipY1] + jge @@2 + or si, 04h +@@2: + + cmp cx, [mx_ClipX2] + jle @@3 + or si, 02h + jmp @@4 +@@3: + cmp cx, [mx_ClipX1] + jge @@4 + or si, 01h +@@4: + + cmp bx, [mx_ClipY2] + jle @@5 + or si, 80h + jmp @@6 +@@5: + cmp bx, [mx_ClipY1] + jge @@6 + or si, 40h +@@6: + + cmp ax, [mx_ClipX2] + jle @@7 + or si, 20h + jmp @@8 +@@7: + cmp ax, [mx_ClipX1] + jge @@8 + or si, 10h +@@8: + + mov di, si + and di, 000Fh ; Index of procedure + and si, 00F0h + .shr si, 2 ; Index of group (times 4) + cmp di, cs:tblGroups[si] ; Is index within range? + jg @@Exit ; No, line is full clipped + mov si, cs:tblGroups[si+2] ; Get offset of group table + shl di, 1 ; We must index word elements + add si, di ; Make full offset + mov di, ax ; Move X1 to DI and free AX + mov si, cs:[si] ; Get subroutine address + xchg dx, si ; Move Y2 to SI and free DX + call dx ; Call the proper subroutine + mov ax, di ; Restore AX to X1 + mov dx, si ; Restore DX to Y2 + pop bp + ret + +@@Exit: + pop bp + stc + ret +xsubClipLine ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxcg.asm b/16/x_/mxcg.asm new file mode 100755 index 00000000..42163d7a --- /dev/null +++ b/16/x_/mxcg.asm @@ -0,0 +1,69 @@ +;----------------------------------------------------------- +; +; MXCG.ASM - Color to gray conversion +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxColorToGray + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Converts RGB colors to gray shades. +; +; Input: +; CPal = pointer to color palette +; GPal = pointer to destination (gray) palette +; Count = number of colors to convert +; Output: +; none +; +; Note: CPal and GPal may point to the same buffer. +; +mxColorToGray PROC FAR + ARG Count:WORD, \ + DPal:DWORD, \ + SPal:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si, es, di + + mov cx, [Count] + jcxz @@Exit + lds si, [SPal] + les di, [DPal] + cld +; We use the standard formula +; gray=(red*30 + green*59 + blue*11)/100 +; in the equivalent form +; gray=(red*77 + green*151 + blue*28)/256 +; which doesn't need the last divide. + mov bx, 77 SHL 8 + 151 +@@Loop: + lodsb ; Red + mul bh + mov dx, ax + lodsb ; Green + mul bl + add dx, ax + lodsb ; Blue + mov ah, 28 + mul ah + add ax, dx + mov al, ah + stosw ; Save new RGB + stosb + loop @@Loop + +@@Exit: + .pop ds, si, es, di + .leave ARG_SIZE +mxColorToGray ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxcl.asm b/16/x_/mxcl.asm new file mode 100755 index 00000000..aaa0bac3 --- /dev/null +++ b/16/x_/mxcl.asm @@ -0,0 +1,151 @@ +;----------------------------------------------------------- +; +; MXCL.ASM - Bresenham circle +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxCircle + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD +EXTRN mx_VideoSegment : WORD +EXTRN mx_ClipX1 : WORD +EXTRN mx_ClipY1 : WORD +EXTRN mx_ClipX2 : WORD +EXTRN mx_ClipY2 : WORD + +;----------------------------------------------------------- +; +; Draws a circle using the Bresenham algorithm. +; +; Input: +; XC, YC = center coordinates +; Radius = circle radius +; Color = circle color +; Output: +; none +; Note: +; computes only points in the first octant, all other +; points are obtained by symmetry. +; +mxCircle PROC FAR + ARG Color:BYTE:2, \ + Radius:WORD, \ + YC:WORD, \ + XC:WORD = ARG_SIZE + LOCAL Delta:WORD = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, di + + xor si, si ; X + mov di, [Radius] ; Y + mov ax, 3 + sub ax, di + sub ax, di + mov [Delta], ax ; Delta = 3-R*2 + + mov ds, [mx_VideoSegment] + +@@Loop: + cmp si, di ; + jg @@Done ; Exit when X > Y +; Draw points + mov ax, si + mov bx, di + call @@subPutPixel + mov ax, si + neg ax + mov bx, di + call @@subPutPixel + mov ax, si + mov bx, di + neg bx + call @@subPutPixel + mov ax, si + neg ax + mov bx, di + neg bx + call @@subPutPixel + mov ax, di + mov bx, si + call @@subPutPixel + mov ax, di + neg ax + mov bx, si + call @@subPutPixel + mov ax, di + mov bx, si + neg bx + call @@subPutPixel + mov ax, di + neg ax + mov bx, si + neg bx + call @@subPutPixel +; Moves coordinates to next point + mov ax, [Delta] + test ax, ax + jl @@Next + mov ax, di + .shl ax, 2 + sub ax, 4 + sub [Delta], ax + dec di +@@Next: + mov ax, si + .shl ax, 2 + add ax, 6 + add [Delta], ax + inc si + jmp @@Loop + +@@Done: + xor ax, ax + .pop ds, si, di + .leave ARG_SIZE + +;--------------------------------------- +; Put pixel function. +; Input: +; BX = X coordinate (relative to center) +; AX = Y coordinate (relative to center) +; DS = video segment +@@subPutPixel: + add bx, [XC] ; Get absolute coordinates + add ax, [YC] + + cmp bx, [mx_ClipX1] ; Clip pixel + jl @@subExit + cmp bx, [mx_ClipX2] + jg @@subExit + cmp ax, [mx_ClipY1] + jl @@subExit + cmp ax, [mx_ClipY2] + jg @@subExit + + mul [mx_BytesPerLine] ; Get pixel offset + mov cx, bx ; Save X coordinate + .shr bx, 2 + add bx, ax ; DS:BX = pixel offset + + and cl, 3 ; Set write plane + mov ax, 0102h + shl ah, cl + mov dx, TS + out dx, ax + + mov al, [Color] ; Write pixel + mov ds:[bx], al + +@@subExit: + retn +mxCircle ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxcr.asm b/16/x_/mxcr.asm new file mode 100755 index 00000000..ca1fa7bb --- /dev/null +++ b/16/x_/mxcr.asm @@ -0,0 +1,380 @@ +;----------------------------------------------------------- +; +; MXCR.ASM - Clip functions +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxSetSysClipRegion +PUBLIC mxGetClipRegion +PUBLIC mxSetClipRegion +PUBLIC mxSetClip +PUBLIC mxGetClip + +PUBLIC subClipBox +PUBLIC subClipImage + +PUBLIC mx_ClipX1 +PUBLIC mx_ClipY1 +PUBLIC mx_ClipX2 +PUBLIC mx_ClipY2 + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_CodeSegment : WORD + +mx_ClipX1 DW ? ; Clip coordinates +mx_ClipY1 DW ? +mx_ClipX2 DW ? +mx_ClipY2 DW ? + +mx_SysClipX1 DW ? ; System clip coordinates +mx_SysClipY1 DW ? ; (active when mx_ClipStatus is FALSE) +mx_SysClipX2 DW ? +mx_SysClipY2 DW ? + +mx_UserClipX1 DW ? ; User clip coordinates +mx_UserClipY1 DW ? ; (active when mx_ClipStatus is TRUE) +mx_UserClipX2 DW ? +mx_UserClipY2 DW ? + +mx_ClipStatus DB ? + +;----------------------------------------------------------- +; +; Toggles clipping between user and system regions. +; +; Input: +; ClipStatus = TRUE (FALSE) to enable (disable) clipping +; Output: +; AX = old clip status +; +mxSetClip PROC FAR + ARG ClipStatus:BYTE:2 = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, [mx_UserClipX1] + mov bx, [mx_UserClipY1] + mov cx, [mx_UserClipX2] + mov dx, [mx_UserClipY2] + cmp [ClipStatus], TRUE + je @@Done + mov ax, [mx_SysClipX1] + mov bx, [mx_SysClipY1] + mov cx, [mx_SysClipX2] + mov dx, [mx_SysClipY2] +@@Done: + mov [mx_ClipX1], ax + mov [mx_ClipY1], bx + mov [mx_ClipX2], cx + mov [mx_ClipY2], dx + + mov al, [ClipStatus] + xchg al, [mx_ClipStatus] + xor ah, ah + + .pop ds + .leave ARG_SIZE +mxSetClip ENDP + +;----------------------------------------------------------- +; +; Returns the current clipping status. +; +; Input: +; none +; Output: +; TRUE (FALSE) if clipping enabled (disabled) +; +mxGetClip PROC FAR + ASSUME ds:NOTHING + mov al, [mx_ClipStatus] + xor ah, ah + ret +mxGetClip ENDP + +;----------------------------------------------------------- +; +; Sets the system clip region and disables user clipping. +; +; Input: +; Width = width in pixels of clip region +; Height = height in pixels of clip region +; Output: +; old clip status. +; +mxSetSysClipRegion PROC FAR + ARG Height:WORD, \ + Width:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + xor ax, ax ; Sys clip region always starts at (0,0) + mov [mx_SysClipX1], ax + mov [mx_SysClipY1], ax + mov ax, [Width] + dec ax + mov [mx_SysClipX2], ax + mov ax, [Height] + dec ax + mov [mx_SysClipY2], ax + + IF USE286 EQ TRUE + push FALSE + ELSE + mov ax, FALSE + push ax + ENDIF + call mxSetClip + + .pop ds + .leave ARG_SIZE +mxSetSysClipRegion ENDP + +;----------------------------------------------------------- +; +; Sets the clip region. +; +; Input: +; X, Y = coordinates of top left corner of clip region +; Width = width in pixels of clip region +; Height = height in pixels of clip region +; Output: +; none (no checking on parameters) +; +mxSetClipRegion PROC FAR + ARG Height:WORD, \ + Width:WORD, \ + Y:WORD, \ + X:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, [X] + mov [mx_UserClipX1], ax + mov ax, [Y] + mov [mx_UserClipY1], ax + mov ax, [Width] + add ax, [X] + dec ax + mov [mx_UserClipX2], ax + mov ax, [Height] + add ax, [Y] + dec ax + mov [mx_UserClipY2], ax + + mov al, [mx_ClipStatus] + cmp al, TRUE + jne @@Exit + push ax + call mxSetClip + +@@Exit: + xor ax, ax + .pop ds + .leave ARG_SIZE +mxSetClipRegion ENDP + +;----------------------------------------------------------- +; +; Returns the current user clip region. +; +; Input: +; X, Y = pointers to integer coordinates of top left corner +; Width = pointer to word width of clip region +; Height = pointer to word height of clip region +; Output: +; AX = current clip status +; +mxGetClipRegion PROC FAR + ARG Height:DWORD, \ + Width:DWORD, \ + Y:DWORD, \ + X:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push es, di + + mov ax, [mx_UserClipX1] + les di, [X] + mov es:[di], ax + mov ax, [mx_UserClipY1] + les di, [Y] + mov es:[di], ax + + mov ax, [mx_UserClipX2] + sub ax, [mx_UserClipX1] + inc ax + les di, [Width] + mov es:[di], ax + mov ax, [mx_UserClipY2] + sub ax, [mx_UserClipY1] + inc ax + les di, [Height] + mov es:[di], ax + + mov al, [mx_ClipStatus] + xor ah, ah + .pop es, di + .leave ARG_SIZE +mxGetClipRegion ENDP + +;----------------------------------------------------------- +; +; Internal use: checks the coordinates of a rectangle against +; the active clip region. +; This function assumes that a "raw" image has to be clipped, +; so it returns in SI the number of "raw" bytes to skip if +; X, Y were clipped. +; +; Input: +; BX, AX = X, Y coordinates of rectangle (signed) +; CX = box width +; DX = box height +; Output: +; CF = set if rectangle is full clipped +; BX, AX = new X, Y coordinates of rectangle +; CX, DX = clipped width and height +; SI = number of bytes to skip before copying a buffer +; DI destroyed +; +subClipImage PROC NEAR + ASSUME ds:NOTHING + xor si, si + +; Check clip height + mov di, [mx_ClipY1] + cmp ax, di + jge @@CheckBottom + sub di, ax ; Number of lines to clip + sub dx, di ; New box height + jle @@Exit + mov ax, di + mov di, dx ; Save box height into DI + mul cx ; DX:AX = number of bytes to skip + mov si, ax + mov dx, di ; Restore box height + mov ax, [mx_ClipY1] +@@CheckBottom: + mov di, [mx_ClipY2] + cmp ax, di + jg @@Exit + inc di + sub di, dx + sub di, ax + jge @@DoneHeight ; None, continue + add dx, di ; Clip lines +@@DoneHeight: + +; Check clip width +@@CheckLeft: + mov di, [mx_ClipX1] + cmp bx, di + jge @@CheckRight + sub di, bx ; Number of columns to clip left + sub cx, di + jle @@Exit + add si, di ; Update skip count + mov bx, [mx_ClipX1] +@@CheckRight: + mov di, [mx_ClipX2] + cmp bx, di + jg @@Exit + inc di + sub di, bx + sub di, cx + jge @@DoneWidth ; None, exit + add cx, di ; New box width +@@DoneWidth: + +; Set return flag and exit +@@Done: + clc + ret +@@Exit: + stc + ret +subClipImage ENDP + +;----------------------------------------------------------- +; +; Internal use: checks the coordinates of a rectangle against +; the active clip region. +; +; Input: +; BX, AX = X, Y coordinates of rectangle (signed) +; CX = box width +; DX = box height +; Output: +; CF = set if rectangle is full clipped +; BX, AX = new X, Y coordinates of rectangle +; CX, DX = clipped width and height +; DI destroyed +; +subClipBox PROC NEAR + ASSUME ds:NOTHING + +; Check clip height + mov di, [mx_ClipY1] + cmp ax, di + jge @@CheckBottom + sub di, ax ; Number of lines to clip + sub dx, di ; New box height + jle @@Exit + mov ax, [mx_ClipY1] +@@CheckBottom: + mov di, [mx_ClipY2] + cmp ax, di + jg @@Exit + inc di + sub di, dx + sub di, ax ; Clipped some point? + jge @@DoneHeight ; No, continue + add dx, di ; Clip lines (DI is negative) +@@DoneHeight: + +; Check clip width +@@CheckLeft: + mov di, [mx_ClipX1] + cmp bx, di + jge @@CheckRight + sub di, bx ; Number of columns to clip left + sub cx, di + jle @@Exit + mov bx, [mx_ClipX1] +@@CheckRight: + mov di, [mx_ClipX2] + cmp bx, di + jg @@Exit + inc di + sub di, bx + sub di, cx ; Clipped some point? + jge @@DoneWidth ; No, exit + add cx, di ; New box width (DI is negative) +@@DoneWidth: + +; Set return flag and exit +@@Done: + clc + ret +@@Exit: + stc + ret +subClipBox ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxel.asm b/16/x_/mxel.asm new file mode 100755 index 00000000..2c9dda2a --- /dev/null +++ b/16/x_/mxel.asm @@ -0,0 +1,167 @@ +;----------------------------------------------------------- +; +; MXEL.ASM - Mid-point ellipse +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxEllipse + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD +EXTRN mx_VideoSegment : WORD +EXTRN mx_ClipX1 : WORD +EXTRN mx_ClipY1 : WORD +EXTRN mx_ClipX2 : WORD +EXTRN mx_ClipY2 : WORD + +;----------------------------------------------------------- +; +; Draws an ellipse using the mid-point algorithm. +; +; Input: +; XC, YC = center coordinates +; A = horizontal radius +; B = vertical radius +; Color = ellipse color +; Output: +; none +; Note: +; computes only points in the first quadrant, all other +; points are obtained by symmetry. +; +mxEllipse PROC FAR + ARG Color:BYTE:2, \ + B:WORD, \ + A:WORD, \ + YC:WORD, \ + XC:WORD = ARG_SIZE + LOCAL A2:DWORD, \ + B2:DWORD, \ + CC:DWORD, \ + DD:DWORD, \ + X:DWORD, \ + Y:DWORD = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, di + + .chk386 mxEllipse, @@Exit + +; Initialize variables + xor eax, eax + mov [X], ax ; X = 0 + mov ax, [A] + mul eax ; EAX = A*A + mov [DD], eax ; DD = A*A + shl eax, 1 + mov [CC], eax ; CC = 2*A*A + shl eax, 1 + mov [A2], eax ; A2 = 4*A*A + movzx edx, [B] + mov [Y], edx + mul edx ; EAX = 4*A*A*B + sub [DD], eax ; DD = A*A - 4*A*A*B + movzx eax, [B] + mul eax ; EAX = B*B + shl eax, 2 ; EAX = 4*B*B + mov [B2], eax ; B2 = 4*B*B + add [CC], eax ; CC = 2*A*A + 4*B*B + add [D1], eax ; DD = A*A - 4*A*A*B + 4*B*B + +; Draw initial points + call subPlot4 + +; First loop +@@Loop1: + mov eax, [X] ; Check slope + mul [B2] + mov ecx, eax + mov eax, [Y] + mul [A2] + sub eax, ecx + sub eax, [CC] ; EAX = Y*A2 - X*B2 - CC + jle @@Done1 ; Crossed critical point, jump to next loop + + mov ecx, [DD] ; Get error + test ecx, ecx ; Positive? + jl @@Draw1 ; No, use default step + + mov eax, 1 + sub eax, [Y] + mul [A2] + shl eax, 1 + add ecx, eax ; Bump error + dec WORD PTR [Y] ; Decrement Y coordinate + +@@Draw1: + mov eax, [X] + shl eax, 1 + add eax, 3 + mul [B2] + add ecx, eax ; Bump error + mov [DD], ecx ; Save error + inc WORD PTR [X] ; Increment X coordinate + + call subPlot4 ; Draw points + jmp @@Loop1 +@@Done1: + +; Initialize variables + shr [B2], 2 + mov eax, [X] + mul eax + add [X] + shl eax, 2 + inc eax + mul [B2] + mov [DD], eax + mov eax, [Y] + mul eax + add [Y] + dec eax + add [Y] + sub eax, [B2] + add [DD], eax + shl [B2], 3 + inc WORD PTR [X] + +; Second loop +@@Loop2: + cmp WORD PTR [Y], 0 + ja @@Done2 + + mov ecx, [DD] + test ecx, ecx + jge @@Draw2 + + mov eax, [X] + inc eax + mul [B2] + add ecx, eax + inc WORD PTR [X] + +@@Draw2: + mov eax, [Y] + shl eax, 1 + sub eax, 3 + neg eax + imul [A2] + add ecx, eax + dec WORD PTR [Y] + + call subPlot4 + jmp @@Loop2 +@@Done2: + +@@Exit: + xor ax, ax + .leave ARG_SIZE +mxEllipse ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxfb.asm b/16/x_/mxfb.asm new file mode 100755 index 00000000..41ea5deb --- /dev/null +++ b/16/x_/mxfb.asm @@ -0,0 +1,194 @@ +;----------------------------------------------------------- +; +; MXFB.ASM - Fill box function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxFillBox + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD +EXTRN mx_VideoSegment : WORD +EXTRN subClipBox : NEAR +EXTRN subHorizontalLineInfo : NEAR + +;----------------------------------------------------------- +; +; Raster op functions. Raster op is limited to OP_MOVE, +; OP_AND, OP_OR and OP_XOR. The VGA hardware is used to +; perform the selected logical functions on up to four +; pixel at a time. +; +subRepFill PROC NEAR + mov ah, al + shr cx, 1 + rep stosw + rcl cx, 1 + rep stosb + ret +subRepFill ENDP +; +subFill PROC NEAR +@@Loop: + mov ds:[bx], al + add bx, dx + loop @@Loop + ret +subFill ENDP +; +subRepMove PROC NEAR + mov si, di +@@Loop: + mov ah, ds:[si] ; Dummy read to latch the data + mov ds:[si], al + inc si + loop @@Loop + ret +subRepMove ENDP +; +subMove PROC NEAR +@@Loop: + mov ah, ds:[bx] ; Dummy read to latch the data + mov ds:[bx], al + add bx, dx + loop @@Loop + ret +subMove ENDP + +;----------------------------------------------------------- +; +; Fills a rectangle with a specified color. +; +; Input: +; X, Y = X, Y coordinates of rectangle +; Width = width of rectangle +; Height = height of rectangle +; Color = fill color +; Op = raster operator +; Output: +; none +; +; Note: raster op is limited to OP_MOVE, OP_AND, OP_OR and OP_XOR. +; +mxFillBox PROC FAR + ARG Op:WORD, \ + Color:BYTE:2, \ + Height:WORD, \ + Width:WORD, \ + Y:WORD, \ + X:WORD = ARG_SIZE + LOCAL LeftMask:BYTE, \ + RightMask:BYTE, \ + FillFunction:WORD, \ + RepFillFunction:WORD = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, es, di + ASSUME ds:NOTHING + +; Clip rectangle + mov bx, [X] + mov ax, [Y] + mov cx, [Width] + mov dx, [Height] + call subClipBox + jc @@Exit ; Full clipped + + mov [Height], dx ; Save clipped height + call subHorizontalLineInfo ; Get additional info, init DI + mov [Width], cx + mov [LeftMask], al + mov [RightMask], ah + +; Initialize segments + mov ax, [mx_VideoSegment] + mov es, ax ; ES:DI points to pixel + mov ds, ax + cld ; Clear direction flag + +; Select fill functions + mov [FillFunction], OFFSET subFill + mov [RepFillFunction], OFFSET subRepFill + mov ax, [Op] ; Get raster op + cmp al, OP_XOR + ja @@1 ; Assume it's a fill + cmp al, OP_MOVE + je @@1 + .shl al, 3 + mov ah, al + mov al, 03h + mov dx, GDC + out dx, ax ; Set GDC logical function + mov [FillFunction], OFFSET subMove + mov [RepFillFunction], OFFSET subRepMove +@@1: + +; Fill left block +@@L0: + mov ah, [LeftMask] + or ah, ah + jz @@C0 ; Nothing to do, go to center block + mov dx, TS + mov al, 02h + out dx, ax ; Set write plane mask + mov dx, [mx_BytesPerLine] + mov cx, [Height] + mov bx, di + mov al, [Color] + call [FillFunction] ; Fill this column + inc di ; Update starting video offset + +; Fill center block +@@C0: + mov cx, [Width] + jcxz @@R0 ; Nothing to do, go to right block + mov dx, TS + mov ax, 0F02h + out dx, ax ; Write to all planes + mov al, [Color] + mov bx, di + mov dx, [Height] + push di ; Save pixel address +@@C1: + mov di, bx ; Update video offset + call [RepFillFunction] ; Fill current scan line + mov cx, [Width] ; Restore byte count + add bx, [mx_BytesPerLine] ; Bump to next scan line + dec dx ; Done all lines? + jnz @@C1 ; No, continue + pop di ; Restore pixel address + add di, [Width] ; Go to right block + +; Fill right block +@@R0: + mov ah, [RightMask] + or ah, ah + jz @@Done ; Nothing to do, exit + mov dx, TS + mov al, 02h + out dx, ax ; Set write plane mask + mov dx, [mx_BytesPerLine] + mov cx, [Height] + mov bx, di + mov al, [Color] + call [FillFunction] ; Fill this column + +; Restore VGA registers +@@Done: + mov dx, GDC + mov ax, 0003h + out dx, ax ; Set logical function to "move" + +@@Exit: + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxFillBox ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxfp.asm b/16/x_/mxfp.asm new file mode 100755 index 00000000..8eea25be --- /dev/null +++ b/16/x_/mxfp.asm @@ -0,0 +1,326 @@ +;----------------------------------------------------------- +; +; MXFP.ASM - Fade palette function +; Copyright (c) 1992-1994 ARTIS s.r.l. +; Author: Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxFadePalette + +MAXCOLOR EQU 256 +FADE_IN EQU 0 +FADE_OUT EQU 1 + +; The actual speed of fading depends on the number of passes (FADE_SPEED) and +; the delay between two consecutive passes (FADE_DELAY). Below are the +; default values, used when no parameters are specified. +; +FADE_DELAY EQU 1 ; Vert. retraces between video updates +FADE_SPEED EQU 48 ; Speed of effect (max 127) + +; Bit field record for fade commands +; +FADE_COMMAND RECORD fpDELAY:8,fpSPEED:7,fpDIRECTION:1 + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +DB 'Copyright (c) 1992-1994 ARTIS s.r.l. All rights reserved.' + +;----------------------------------------------------------- +; +; Fades a VGA palette. +; +; Input: +; Buffer = pointer to source/destination palette +; Command = fading direction and optional parameters +; Start = index of first color to fade +; Count = number of color to fade +; Red = destination red +; Green = destination green +; Blue = destination blue +; Output: +; none +; Notes: +; - about 1.5 Kbytes of stack space are needed for internal buffers; +; - the Command argument usually is 0 to fade in and 1 to fade out, +; however additional parameters may be specified. To set the effect +; speed, i.e. the number of iterations needed to completely fade a +; palette, shift the value one bit left and "or" it with the +; direction bit (range is 0..127). To set the delay between two +; consecutive passes, shift it eight bits left (range is 0..255). +; +mxFadePalette PROC FAR + ARG bBlue:WORD, \ + bGreen:WORD, \ + bRed:WORD, \ + wCount:WORD, \ + wStartIdx:WORD, \ + wCommand:WORD, \ + vfpPalette:DWORD = ARG_SIZE + LOCAL bSPalette:BYTE:MAXCOLOR*3, \ + bDPalette:BYTE:MAXCOLOR*3, \ + bLoopIndex:BYTE, \ + bLoopStep:BYTE, \ + bLoopCount:BYTE, \ + wDelay:WORD, \ + wSpeed:WORD = AUTO_SIZE + ASSUME ds:NOTHING + .enter AUTO_SIZE + .push si, di, ds, es ; Save registers +; +; Check parameters and setup variables +; +@@GetDelay: + mov [wDelay], FADE_DELAY ; Set default delay + mov ax, [wCommand] ; Get command word + and ax, MASK fpDELAY ; Mask delay command + jz @@GetSpeed ; No command, get speed + IF USE286 EQ TRUE + shr ax, fpDELAY + ELSE + mov cl, fpDELAY ; Get size of delay field + shr ax, cl ; Right justify the field + ENDIF + mov [wDelay], ax ; Set new delay + +@@GetSpeed: + mov ax, [wCommand] ; Get command + and ax, MASK fpSPEED ; Mask speed + IF USE286 EQ TRUE + shr ax, fpSPEED + ELSE + mov cl, fpSPEED ; Get size of speed field + shr ax, cl ; Right justify the field + ENDIF + or ax, ax ; Any speed specified? + jnz @@SetVariables ; Yes, set variables + mov ax, FADE_SPEED ; Set default speed + +@@SetVariables: + mov [wSpeed], ax ; Set speed + inc ax ; Number of iterations + mov [bLoopCount], al ; Set loop count + mov [bLoopStep], 1 ; Assume we're fading in + mov [bLoopIndex], 0 +; +; Check bounds for bad values +; + mov ax, [wStartIdx] ; Get first index + cmp ax, MAXCOLOR ; Is in the valid range? + jae @@Exit ; No, exit + add ax, [wCount] ; Get last index + cmp ax, MAXCOLOR ; Is in the valid range? + jbe @@BoundsOk ; Yes, continue + mov ax, MAXCOLOR + sub ax, [wStartIdx] + mov [wCount], ax ; Set count to maximum value + or ax, ax + jz @@Exit ; Nothing to do, exit +@@BoundsOk: +; +; Copy the source palette in a local array: if we fade in it's ready to +; use, otherwise we'll overwrite it later +; + mov cx, [wCount] + mov ax, cx + shl ax, 1 + add cx, ax ; CX = wCount * 3 + mov ax, ss + mov es, ax + lea di, [bSPalette] ; ES:DI points to local palette + mov ax, [wStartIdx] + mov si, ax + shl ax, 1 + add ax, si + lds si, [vfpPalette] ; DS:SI points to user palette + add si, ax ; Skip unused entries + cld + shr cx, 1 + rep movsw + rcl cx, 1 + rep movsb +; +; Check direction +; + test [wCommand], MASK fpDIRECTION ; Are we fading in? + jz @@Main ; Yes, ok to continue + mov ax, [wSpeed] ; Get speed + mov [bLoopIndex], al ; Exchange first and last index + mov [bLoopStep], -1 ; Move backward + mov ax, ss ; Overwrite our copy of + mov ds, ax ; user palette with the + mov es, ax ; current active palette + lea di, [bSPalette] + mov ax, [wStartIdx] + mov cx, [wCount] + call ReadPalette ; Read current palette +; +; Prepare variables and registers for fading +; +@@Main: + mov bh, BYTE PTR [bRed] ; Destination red + and bh, 00111111b ; Be sure it's a valid VGA value + mov bl, BYTE PTR [bGreen] ; Destination green + and bl, 00111111b ; Be sure it's a valid VGA value + mov dh, BYTE PTR [bBlue] ; Destination blue + and dh, 00111111b ; Be sure it's a valid VGA value + mov dl, [bLoopIndex] ; Loop index + mov ax, ss ; All tables are stored + mov ds, ax ; in the stack segment, + mov es, ax ; set DS and ES +; +; Main loop +; +@@Loop: + mov ax, [wCount] ; Store count in AX + mov cx, [wSpeed] ; Set maximum speed in CX + lea si, [bSPalette] ; DS:SI points to source palette + lea di, [bDPalette] ; ES:DI points to dest. palette + call RecalcPalette ; Build a faded palette + + .push bx, dx ; Save registers we need + lea si, [bDPalette] ; DS:SI points to palette + mov ax, [wStartIdx] ; First index to write + mov bx, [wCount] ; Total entries to write + mov cx, [wDelay] ; Fade delay between updates + call WritePalette ; Write palette + .pop bx, dx ; Restore BX and DX + + add dl, [bLoopStep] ; Change fade intensity + dec [bLoopCount] ; Done? + jnz @@Loop ; No, loop again + +@@Exit: + .pop si, di, ds, es ; Restore registers + .leave ARG_SIZE +mxFadePalette ENDP + +;------- INTERNAL USE ONLY ------------------------------------------------ +; +; Calculates a partially faded palette. +; +; Input: +; AX = number of entries in palette +; CX = maximum fade intensity (same as fade speed) +; DS:SI = pointer to source palette +; ES:DI = pointer to destination palette +; BH = destination red +; BL = destination green +; DH = destination blue +; DL = relative intensity of destination palette +; Note: +; it's important that a new palette can be calculated in less +; than 1/70th of second. Fading to any RGB value requires use +; of "imul" instructions: "idiv" may be replaced with faster +; "sar", but only when the number of passes is a power of two, +; thus reducing the range of selectable speeds. +; In both cases an extimate of CPU cycles required by this +; procedure shows that it's too slow to run on a 4.77 Mhz 8086 +; CPU and a 256 color palette, so we keep "idiv" and hope +; the target machine to be at least a 6 Mhz 80286 (that's not +; asking too much...). +; +RecalcPalette PROC NEAR + cld + push bp ; Save BP + mov bp, ax ; Copy counter in BP +@@Loop: + lodsb ; Red: read value + sub al, bh ; Subtract destination value + imul dl ; Scale to desired weight + idiv cl ; Put value in AL + add al, bh ; Add destination value... + stosb ; ...and store it + lodsb ; Green: read value + sub al, bl ; Subtract destination value + imul dl ; Scale to desired weight + idiv cl ; Put value in AL + add al, bl ; Add destination value... + stosb ; ...and store it + lodsb ; Blue: read value + sub al, dh ; Subtract destination value + imul dl ; Scale to desired weight + idiv cl ; Put value in AL + add al, dh ; Add destination value... + stosb ; ...and store it + dec bp + jnz @@Loop + pop bp ; Restore BP + ret +RecalcPalette ENDP + +;------- INTERNAL USE ONLY ------------------------------------------------ +; +; Writes a 256 color palette. +; +; Input: +; AX = index of first color to write +; BX = number of colors to write (each color is an RGB triplet) +; CX = number of vertical retraces to wait before writing to DACs +; DS:SI = pointer to first entry of palette +; +WritePalette PROC NEAR + ASSUME ds:NOTHING + mov ah, al ; Save index + mov dx, 03DAh ; Input status register +@@Delay1: + in al, dx + test al, 08h + jnz @@Delay1 ; Wait for display mode +@@Delay2: + in al, dx + test al, 08h + jz @@Delay2 ; Wait for vertical retrace mode + loop @@Delay1 ; Repeat CX times +@@Write: + mov cx, bx ; Get number of colors + mov dx, 03C8h ; PEL write address register + mov al, ah ; Restore index + out dx, al ; Select index of first color + inc dx ; PEL data register + cld ; Move forward + cli ; Disable interrupts +@@Loop: + lodsb + out dx, al ; Red + lodsb + out dx, al ; Green + lodsb + out dx, al ; Blue + loop @@Loop ; Loop until done + sti ; Enable interrupts + ret +WritePalette ENDP + +;------- INTERNAL USE ONLY ------------------------------------------------ +; +; Reads the current palette. +; +; Input: +; AX = index of first color to read +; CX = number of colors +; ES:DI = pointer to destination buffer +; +ReadPalette PROC NEAR + mov dx, 03C7h + out dx, al + inc dx + inc dx + cld +@@Loop: + in al, dx + stosb + in al, dx + stosb + in al, dx + stosb + loop @@Loop + ret +ReadPalette ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxgc.asm b/16/x_/mxgc.asm new file mode 100755 index 00000000..85edf7a6 --- /dev/null +++ b/16/x_/mxgc.asm @@ -0,0 +1,54 @@ +;----------------------------------------------------------- +; +; MXGC.ASM - Get color function +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxGetColor + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Returns the current setting of the selected DAC register. +; +; Input: +; Index = color index (0-255) +; R, G, B = byte pointers to red, green and blue +; Output: +; none +; +mxGetColor PROC FAR + ARG B:DWORD, \ + G:DWORD, \ + R:DWORD, \ + Index:WORD = ARG_SIZE + .enter 0 + .push ds, si + + mov ax, [Index] + mov dx, 3C7h ; PEL read address register + out dx, al + inc dx + inc dx + + lds si, [R] + in al, dx + mov ds:[si], al + lds si, [G] + in al, dx + mov ds:[si], al + lds si, [B] + in al, dx + mov ds:[si], al + + .pop ds, si + .leave ARG_SIZE +mxGetColor ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxgi.asm b/16/x_/mxgi.asm new file mode 100755 index 00000000..7037d411 --- /dev/null +++ b/16/x_/mxgi.asm @@ -0,0 +1,132 @@ +;----------------------------------------------------------- +; +; MXGI.ASM - Get image +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxGetImage + +EXTRN subClipImage : NEAR + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_VideoSegment : WORD +EXTRN mx_BytesPerLine : WORD + +;----------------------------------------------------------- +; +; Copies an image from screen to memory. +; +; Input: +; Image = pointer to buffer for image +; X, Y = coordinates of image on screen +; Width = width of image in pixels +; Height = height of image in pixels +; Output: +; none +; +mxGetImage PROC FAR + ARG Height:WORD, \ + Width:WORD, \ + Y:WORD, \ + X:WORD, \ + Image:DWORD = ARG_SIZE + LOCAL PlaneWidth:WORD:4, \ + PixelOffset:WORD, \ + MoveFunction:WORD, \ + ReadPlane:BYTE, \ + Count:BYTE = AUTO_SIZE + ASSUME ds:NOTHING + .enter AUTO_SIZE + .push ds, si, es, di + +; Clip image + mov bx, [X] + mov ax, [Y] + mov cx, [Width] + mov dx, [Height] + call subClipImage + jc @@Exit ; Full clipped + mov [Height], dx + add WORD PTR Image[0], si ; Skip clipped pixels + +; Get pixel address + mul [mx_BytesPerLine] + mov si, bx + shr si, 1 + shr si, 1 + add si, ax + mov [PixelOffset], si + mov ds, [mx_VideoSegment] ; DS:SI points to pixel + and bl, 03h + mov [ReadPlane], bl + +; Compute extra bytes and width count for each plane + mov bx, cx + shr bx, 1 + shr bx, 1 ; Width for each plane + and cl, 03h + mov al, 00001000b + shr al, cl + mov di, 3 SHL 1 +@@PatchLoop: + mov PlaneWidth[di], bx + shr al, 1 + adc bx, 0 + dec di + dec di + jge @@PatchLoop + +; Get image + cld + mov [Count], 4 ; Four planes + lea bx, PlaneWidth ; SS:[BX] = width in bytes for plane + mov es, WORD PTR Image[2] ; ES:DI will point to image + mov ah, [ReadPlane] +@@PlaneLoop: + cmp WORD PTR ss:[bx], 0 ; Exit if nothing more to do + je @@Exit ; (also, never try to move zero bytes!) + mov di, WORD PTR Image[0] + mov al, 04h + mov dx, GDC + out dx, ax ; Select read plane + mov dx, [Height] + mov si, [PixelOffset] ; DS:SI points to video memory +@@Loop: + .push si, di + mov cx, WORD PTR ss:[bx] ; Number of bytes to move +@@MoveLoop: + movsb + add di, 3 + dec cx + jnz @@MoveLoop + .pop si, di + add di, [Width] ; Go to next image line + add si, [mx_BytesPerLine] ; Go to next screen row + dec dx + jnz @@Loop ; Repeat for all lines + inc bx + inc bx ; Select width for next plane + inc ah + test ah, 04h ; Plane wraparound? + jz @@PlaneOk ; No + inc [PixelOffset] ; Yes, bump video pointer + and ah, 03h +@@PlaneOk: + inc WORD PTR Image[0] + dec [Count] + jnz @@PlaneLoop ; Repeat for all planes + +@@Exit: + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxGetImage ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxgm.asm b/16/x_/mxgm.asm new file mode 100755 index 00000000..a67476a0 --- /dev/null +++ b/16/x_/mxgm.asm @@ -0,0 +1,63 @@ +;----------------------------------------------------------- +; +; MXGM.ASM - Gamma correction +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxGammaCorrect + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +mx_tblGamma LABEL BYTE + DB 00, 10, 14, 17, 19, 21, 23, 24, 26, 27, 28, 29, 31, 32, 33, 34 + DB 35, 36, 37, 37, 38, 39, 40, 41, 41, 42, 43, 44, 44, 45, 46, 46 + DB 47, 48, 48, 49, 49, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55 + DB 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63 + +;----------------------------------------------------------- +; +; Correct palette colors (gamma is 2.3). +; +; Input: +; CPal = pointer to color palette +; GPal = pointer to destination (gamma corrected) palette +; Count = number of colors to convert +; Output: +; none +; +; Note: CPal and GPal may point to the same buffer. +; +mxGammaCorrect PROC FAR + ARG Count:WORD, \ + DPal:DWORD, \ + SPal:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si, es, di + + mov cx, [Count] + jcxz @@Exit ; Exit now if nothing to do + lds si, [SPal] + les di, [DPal] + mov bx, OFFSET mx_tblGamma ; Setup BX for XLAT instruction + cld + mov ax, cx ; AX = Count + add cx, cx ; CX = Count*2 + add cx, ax ; CX = Count*3 +@@Loop: + lodsb + xlat mx_tblGamma + stosb + loop @@Loop + +@@Exit: + .pop ds, si, es, di + .leave ARG_SIZE +mxGammaCorrect ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxgp.asm b/16/x_/mxgp.asm new file mode 100755 index 00000000..6c143173 --- /dev/null +++ b/16/x_/mxgp.asm @@ -0,0 +1,56 @@ +;----------------------------------------------------------- +; +; MXGP.ASM - Get palette function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxGetPalette + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Returns the current setting of the VGA palette. +; +; Input: +; Buffer = pointer to palette data (R,G,B) +; Start = index of first color to get +; Count = number of color to get +; Output: +; none +; +mxGetPalette PROC FAR + ARG Count:WORD, \ + Start:WORD, \ + Buffer:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push es, di + + les di, [Buffer] + mov cx, [Count] + mov ax, [Start] + mov dx, 3C7h ; PEL read address register + out dx, al + inc dx + inc dx + cld +@@Loop: + in al, dx + stosb + in al, dx + stosb + in al, dx + stosb + loop @@Loop ; Loop until done + + .pop es, di + .leave ARG_SIZE +mxGetPalette ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxgv.asm b/16/x_/mxgv.asm new file mode 100755 index 00000000..2a54b1d0 --- /dev/null +++ b/16/x_/mxgv.asm @@ -0,0 +1,25 @@ +;----------------------------------------------------------- +; +; MXGV.ASM - Get version function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxGetVersion + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Returns the library version. +; +mxGetVersion PROC FAR + mov ax, MXVERSION + ret +mxGetVersion ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxhl.asm b/16/x_/mxhl.asm new file mode 100755 index 00000000..049a0566 --- /dev/null +++ b/16/x_/mxhl.asm @@ -0,0 +1,76 @@ +;----------------------------------------------------------- +; +; MXHL.ASM - Horizontal line mask utility +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC subHorizontalLineInfo + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD + +tblLeftSize DW 00h, 03h, 02h, 01h +tblLeftMask DB 00h, 0Eh, 0Ch, 08h +tblRightMask DB 00h, 01h, 03h, 07h +tblPatchMask DB 02h, 06h + +;----------------------------------------------------------- +; +; Prepares register for fast horizontal line drawing. +; +; Input: +; BX, AX = X, Y address of left pixel +; CX = line width +; Output: +; DI = left pixel offset in video memory +; AL = left block write plane mask (0 = none) +; AH = right block write plane mask (0 = none) +; CX = center block width in 4-pixel blocks +; +subHorizontalLineInfo PROC NEAR + ASSUME ds:NOTHING + + mul [mx_BytesPerLine] + mov di, bx + shr di, 1 + shr di, 1 + add di, ax ; Offset of left pixel + + and bx, 03h + mov al, tblLeftMask[bx] + shl bx, 1 + sub cx, tblLeftSize[bx] + jge @@1 ; Ok to continue + +; Special case: start and end in the middle of a 4-pixel block. +; There are only three cases: +; Pixels Left mask CX CX+2 Patch mask Result +; 1) ..o. ..xx -1 1 .xx. ..x. +; 2) .oo. .xxx -1 1 .xx. .xx. +; 3) .o.. .xxx -2 0 .x.. .x.. +; All other cases are automatically handled with the standard masks. + mov bx, cx + inc bx + inc bx + and al, tblPatchMask[bx] ; Combine masks + xor ah, ah ; No right block + xor cx, cx ; No center block + jmp @@Exit + +@@1: + mov bx, cx + and bx, 03h + mov ah, tblRightMask[bx] + shr cx, 2 + +@@Exit: + ret +subHorizontalLineInfo ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxit.asm b/16/x_/mxit.asm new file mode 100755 index 00000000..c0d9cedd --- /dev/null +++ b/16/x_/mxit.asm @@ -0,0 +1,98 @@ +;----------------------------------------------------------- +; +; MXIT.ASM - Initialization/termination functions +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxInit +PUBLIC mxTerm + +PUBLIC mx_VideoSegment +PUBLIC mx_CodeSegment + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +DB 'MODEX library - Copyright (c) 1992-1994 Alessandro Scotti' + +mx_VideoSegment DW 0A000h +mx_CodeSegment DW SEG MX_TEXT + +;----------------------------------------------------------- +; +; Initialization. +; +; Input: +; none +; Output: +; AX = 0 on success +; +mxInit PROC FAR + LOCAL Result:WORD, \ + VideoSeg:WORD, \ + CStoDSalias:WORD = AUTO_SIZE + ASSUME ds:NOTHING + .enter AUTO_SIZE + .push ds, si, es, di + + mov [Result], -1 ; Assume an error + mov [VideoSeg], 0A000h ; Real mode video segment + mov [CStoDSalias], cs ; Real mode data alias for CS + +; Check if running in protected mode under DPMI + mov ax, 1686h + int 2Fh + or ax, ax + jnz @@1 ; DPMI not found, continue in real mode + +; Get a data alias for CS + mov ax, 000Ah ; DMPI: create data alias + mov bx, cs + int 31h + jc @@Exit ; Exit if service failed + mov [CStoDSalias], ax ; Save data alias for CS +; Get a protected-mode selector for the video segment + mov ax, 0002h + mov bx, 0A000h ; Real mode segment of video + int 31h ; DPMI: get segment selector + jc @@Exit ; Exit if service failed + mov [VideoSeg], ax ; Save protected mode video selector + +; Initialize variables +@@1: + mov ds, [CStoDSalias] + ASSUME ds:MX_TEXT + mov [mx_CodeSegment], ds + mov ax, [VideoSeg] + mov [mx_VideoSegment], ax + +; Don't bother with VGA check for now... + + mov [Result], 0 + +@@Exit: + mov ax, [Result] + .pop ds, si, es, di + .leave +mxInit ENDP + +;----------------------------------------------------------- +; +; Termination. +; +; Input: +; none +; Output: +; always 0. +; +mxTerm PROC FAR + ASSUME ds:NOTHING + xor ax, ax + ret +mxTerm ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxll.asm b/16/x_/mxll.asm new file mode 100755 index 00000000..34fec043 --- /dev/null +++ b/16/x_/mxll.asm @@ -0,0 +1,82 @@ +;----------------------------------------------------------- +; +; MXLL.ASM - Load latches +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxLoadLatches + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_VideoSegment : WORD + +;----------------------------------------------------------- +; +; Loads the specified value into the VGA latches. +; +; Input: +; BL = value to load into latches +; Output: +; none +; Changes: +; bit mask register to FFh; +; function select register to "move"; +; write mode to 00h. +; Note: +; this is for internal use only. +; +mxLoadLatches PROC NEAR + ASSUME ds:NOTHING + + .push ds, si + mov dx, GDC + mov ax, 0FF08h + out dx, ax ; Set bit mask to FFh + mov ax, 0003h + out dx, ax ; Set function to "move" + mov ax, 0005h + out dx, ax ; Set write mode + mov ax, [mx_VideoSegment] + mov ds, ax + mov si, 0FFFFh + mov bh, 8 ; BH = write plane mask + mov cx, 3 ; CX = count = read plane +; Saves old values and force BL into latches +@@SetLoop: + mov dx, GDC + mov al, 04h + mov ah, cl + out dx, ax ; Select read plane + mov dx, TS + mov al, 02h + mov ah, bh + out dx, ax ; Select write plane + mov al, ds:[si] + push ax + mov ds:[si], bl + mov al, ds:[di] ; Force value into latch + shr bh, 1 ; Next write plane + loop @@SetLoop +; Restore previous values + mov cx, 3 + mov bh, 8 + mov dx, TS +@@ResetLoop: + mov al, 02h + mov ah, bh + out dx, ax ; Select write plane + pop ax + mov ds:[si], al + shr bh, 1 ; Next write plane + loop @@ResetLoop +; Exit + .pop ds, si + ret +mxLoadLatches ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxln.asm b/16/x_/mxln.asm new file mode 100755 index 00000000..fbc4ab94 --- /dev/null +++ b/16/x_/mxln.asm @@ -0,0 +1,414 @@ +;----------------------------------------------------------- +; +; MXLN.ASM - Line function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxLine + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD +EXTRN mx_VideoSegment : WORD + +EXTRN mx_ClipX1 : WORD +EXTRN mx_ClipY1 : WORD +EXTRN mx_ClipX2 : WORD +EXTRN mx_ClipY2 : WORD + +tblDrawFunc LABEL WORD + DW subWidthMove + DW subHeightMove + DW subWidthOp + DW subHeightOp + +;----------------------------------------------------------- +; +; Draws a line from (X1,Y1) to (X2,Y2) using the Bresenham +; algorithm. +; +; Input: +; X1, Y1 = start point +; X2, Y2 = end point +; Color = line color +; Op = raster operator +; Output: +; none +; +; Note: the end point (X2,Y2) *IS* drawed. I don't like this very much +; but clipping is much simpler. +; +mxLine PROC FAR + ARG Op:WORD, \ + Color:WORD, \ + Y2:WORD, \ + X2:WORD, \ + Y1:WORD, \ + X1:WORD = ARG_SIZE + LOCAL Width:WORD, \ + Height:WORD, \ + ErrorAdd:WORD, \ + ErrorSub:WORD, \ + DeltaX:WORD, \ + DeltaY:WORD, \ + P1:BYTE, \ + P2:BYTE, \ + WritePlane:BYTE = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, di + ASSUME ds:NOTHING + + mov ax, [X1] + mov bx, [Y1] + mov cx, [X2] + mov dx, [Y2] + call subClipLine + jc @@Exit ; Line is full clipped + +; Get width + mov si, cx + xchg ax, si ; SI = X1, AX = X2 + sub ax, si + jge @@1 +; Swap points, we want X1 < X2 + xchg si, cx ; Swap X1 and X2 + xchg bx, dx ; Swap Y1 and Y2 + neg ax +@@1: + mov [Width], ax + +; Get height + mov cx, [mx_BytesPerLine] ; We don't need X2 anymore + mov ax, dx + sub ax, bx + jge @@2 + neg cx ; Move from bottom to top + neg ax ; Get absolute value of AX +@@2: + mov [Height], ax + mov [DeltaY], cx + +; Get pixel address and write plane + mov ax, bx + mul [mx_BytesPerLine] + mov cx, si ; CX = X1 + shr si, 1 + shr si, 1 + add si, ax ; SI = pixel offset + and cl, 03h + mov ax, 1102h + shl ah, cl + mov [WritePlane], ah + mov dx, TS + out dx, ax ; Set write plane + mov ax, [mx_VideoSegment] + mov ds, ax ; DS:SI points to (X1,Y1) + +; Select the function to handle the drawing loop + xor bx, bx + mov al, BYTE PTR [Op] + cmp al, OP_MOVE + je @@3 + and al, 03h + shl al, 1 + shl al, 1 + shl al, 1 + mov ah, al + mov al, 03h + mov dx, GDC + out dx, ax ; Set logical function + inc bx + inc bx +@@3: + mov ax, [Width] + mov cx, [Height] +; Horizontal, vertical and diagonal lines are not optimized yet + cmp ax, cx + jae @@4 + inc bx +@@4: + shl bx, 1 + call tblDrawFunc[bx] + +; Reset logical function if needed + cmp BYTE PTR [Op], OP_MOVE + je @@Exit + mov ax, 0003h + mov dx, GDC + out dx, ax + +@@Exit: + xor ax, ax + .pop ds, si, di + .leave ARG_SIZE + +;----------------------------------------------------------- +; +; Checks the coordinates of a line against the active +; clip region. +; Uses a variation of the Cohen-Sutherland algorithm developed +; by Victor Duvanenko. +; +; Input: +; AX, BX = X1, Y1 +; CX, DX = X2, Y2 +; Output: +; CF = set if line is full clipped +; AX, BX = clipped X1, Y1 +; CX, DX = clipped X2, Y2 +; Note: +; destroys SI, DI +; +subClipLine PROC NEAR + mov di, ax ; Copy X1 to DI and free AX + mov si, dx ; Copy Y2 to SI and free DX +; Compute clip codes for point (X2,Y2)=(CX,SI) + xor al, al +@@P2X1: cmp cx, [mx_ClipX1] + jge @@P2X2 + or al, 1 +@@P2X2: cmp cx, [mx_ClipX2] + jle @@P2Y1 + or al, 2 +@@P2Y1: cmp si, [mx_ClipY1] + jge @@P2Y2 + or al, 4 +@@P2Y2: cmp si, [mx_ClipY2] + jle @@P2XY + or al, 8 +@@P2XY: mov [P2], al +; Compute clip codes for point (X1,Y1)=(DI,BX) + xor al, al +@@P1X1: cmp di, [mx_ClipX1] + jge @@P1X2 + or al, 1 +@@P1X2: cmp di, [mx_ClipX2] + jle @@P1Y1 + or al, 2 +@@P1Y1: cmp bx, [mx_ClipY1] + jge @@P1Y2 + or al, 4 +@@P1Y2: cmp bx, [mx_ClipY2] + jle @@P1XY + or al, 8 +@@P1XY: mov [P1], al +; Check codes for trivial cases + mov ah, [P2] + test al, ah ; Is line invisible? + jnz @@FullClip ; Yes, exit + or ah, al ; Both points clipped? + jz @@Done ; Yes, exit +; Calculate deltas + mov ax, cx + sub ax, di + mov [DeltaX], ax + mov ax, si + sub ax, bx + mov [DeltaY], ax + mov al, [P1] ; Init clipping code +; Clipping loop +@@ClipLoop: + test al, al ; Is first point clipped? + jnz @@ClipX1 ; No, continue + xchg cx, di ; Swap points... + xchg bx, si + xchg al, [P2] ; ...and codes +; Clip left: Y1 = Y1 + DeltaY*(mx_ClipX1-X1)/DeltaX +@@ClipX1: + test al, 1 + jz @@ClipX2 + mov ax, [mx_ClipX1] + sub ax, di + mov di, [mx_ClipX1] + jmp @@ClipX1X2 +; Clip right: Y1 = Y1 + DeltaY*(mx_ClipX2-X1)/DeltaX +@@ClipX2: + test al, 2 + jz @@ClipY1 + mov ax, [mx_ClipX2] + sub ax, di + mov di, [mx_ClipX2] +@@ClipX1X2: + imul [DeltaY] + idiv [DeltaX] + add bx, ax + mov al, 8 + cmp bx, [mx_ClipY2] + jg @@CheckLoop + mov al, 4 + cmp bx, [mx_ClipY1] + jl @@CheckLoop + xor al, al + jmp @@CheckLoop +; Clip top: X1 = X1 + DeltaX*(mx_ClipY1-Y1)/DeltaY +@@ClipY1: + test al, 4 + jz @@ClipY2 + mov ax, [mx_ClipY1] + sub ax, bx + mov bx, [mx_ClipY1] + jmp @@ClipY1Y2 +; Clip bottom: X1 = X1 + DeltaX*(mx_ClipY2-Y1)/DeltaY +@@ClipY2: + mov ax, [mx_ClipY2] + sub ax, bx + mov bx, [mx_ClipY2] +@@ClipY1Y2: + imul [DeltaX] + idiv [DeltaY] + add di, ax + mov al, 1 + cmp di, [mx_ClipX1] + jl @@CheckLoop + mov al, 2 + cmp di, [mx_ClipX2] + jg @@CheckLoop + xor al, al +@@CheckLoop: + mov ah, [P2] + test al, ah + jnz @@FullClip + or ah, al + jnz @@ClipLoop + +@@Done: + mov ax, di + mov dx, si + clc + ret +@@FullClip: + stc + ret +subClipLine ENDP + +; Called when Width >= Height and Op = OP_MOVE +subWidthMove PROC NEAR + mov di, ax + neg di ; Initialize error term + shl cx, 1 + mov [ErrorAdd], cx + mov cx, ax + shl ax, 1 + mov [ErrorSub], ax + mov al, 02h + mov ah, [WritePlane] + mov bl, BYTE PTR [Color] + mov dx, TS + inc cx +@@Loop: + mov ds:[si], bl + dec cx + jz @@Exit + rol ah, 1 + adc si, 0 + out dx, ax + add di, [ErrorAdd] + jl @@Loop + add si, [DeltaY] + sub di, [ErrorSub] + jmp @@Loop +@@Exit: + ret +subWidthMove ENDP + +; Called when Width < Height and Op = OP_MOVE +subHeightMove PROC NEAR + mov di, cx + neg di ; Initialize error term + shl ax, 1 + mov [ErrorAdd], ax + mov ax, cx + shl ax, 1 + mov [ErrorSub], ax + mov bl, BYTE PTR [Color] + mov ah, [WritePlane] + mov al, 02h + mov dx, TS + inc cx +@@Loop: + mov ds:[si], bl + dec cx + jz @@Exit + add si, [DeltaY] + add di, [ErrorAdd] + jl @@Loop + rol ah, 1 ; Next write plane + adc si, 0 ; Bump video offset if plane overflows + out dx, ax + sub di, [ErrorSub] ; Adjust error down + jmp @@Loop +@@Exit: + ret +subHeightMove ENDP + +; Called when Width >= Height and Op <> OP_MOVE +subWidthOp PROC NEAR + mov di, ax + neg di ; Initialize error term + shl cx, 1 + mov [ErrorAdd], cx + mov cx, ax + shl ax, 1 + mov [ErrorSub], ax + mov al, 02h + mov ah, [WritePlane] + mov bl, BYTE PTR [Color] + mov dx, TS + inc cx +@@Loop: + mov bh, ds:[si] ; Latch data + mov ds:[si], bl + dec cx + jz @@Exit + rol ah, 1 + adc si, 0 + out dx, ax + add di, [ErrorAdd] + jl @@Loop + add si, [DeltaY] + sub di, [ErrorSub] + jmp @@Loop +@@Exit: + ret +subWidthOp ENDP + +; Called when Width < Height and Op <> OP_MOVE +subHeightOp PROC NEAR + mov di, cx + neg di ; Initialize error term + shl ax, 1 + mov [ErrorAdd], ax + mov ax, cx + shl ax, 1 + mov [ErrorSub], ax + mov bl, BYTE PTR [Color] + mov ah, [WritePlane] + mov al, 02h + mov dx, TS + inc cx +@@Loop: + mov bh, ds:[si] + mov ds:[si], bl + dec cx + jz @@Exit + add si, [DeltaY] + add di, [ErrorAdd] + jl @@Loop + rol ah, 1 ; Next write plane + adc si, 0 ; Bump video offset if plane overflows + out dx, ax + sub di, [ErrorSub] ; Adjust error down + jmp @@Loop +@@Exit: + ret +subHeightOp ENDP + +mxLine ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxot.asm b/16/x_/mxot.asm new file mode 100755 index 00000000..62547665 --- /dev/null +++ b/16/x_/mxot.asm @@ -0,0 +1,330 @@ +;----------------------------------------------------------- +; +; MXOT.ASM - Text functions +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES ; We use the reserved name 'WIDTH' +INCLUDE MODEX.DEF + +PUBLIC mxOutChar +PUBLIC mxOutText +PUBLIC mxSetFont +PUBLIC mxSetTextColor +PUBLIC mxGetTextStep +PUBLIC mxSetTextStep + +MAX_WIDTH EQU 16 ; Must be <= 16 +MAX_HEIGHT EQU 32 + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_CodeSegment : WORD +EXTRN mxPutImage : FAR + +; Default 8x8 font +fnt_Default LABEL + 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 OP_MOVE ; Raster op +mx_DeltaX DW 8 ; Horizontal step +mx_DeltaY DW 0 ; Vertical step + +;----------------------------------------------------------- +; +; Sets the current font. +; +; Input: +; Font = pointer to font data +; Width = width of font character in pixels +; Height = height of font character in pixels +; Output: +; AX = 0 on success, else invalid parameters +; +; Note: when the high word of Font (i.e. the segment) is zero, the low +; word is used to select one of the system fonts. +; +mxSetFont PROC FAR + ARG Height:WORD, \ + Width:WORD, \ + Font:DWORD = ARG_SIZE + .enter 0 + .push ds + + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, WORD PTR Font[2] ; Get font segment + test ax, ax ; Null segment? + jnz @@UserFont ; No, install user font + +; Install system font + mov ax, WORD PTR Font[0] ; Get font number + cmp ax, MX_MAXSYSFONT ; Check range + jb @@SystemFont + xor ax, ax ; Out of range, use default font +@@SystemFont: + shl ax, 1 + shl ax, 1 + mov bx, ax + mov ax, tbl_SystemFont[bx] ; Get font offset + mov WORD PTR mx_FontPtr[0], ax + mov WORD PTR mx_FontPtr[2], cs + mov al, BYTE PTR tbl_SystemFont[bx+2] + xor ah, ah + mov [mx_FontWidth], ax + mov [mx_DeltaX], ax + mov dl, BYTE PTR tbl_SystemFont[bx+3] + xor dh, dh + mov [mx_FontHeight], dx + mul dx + mov [mx_FontCharSize], ax + mov [mx_DeltaX], ax + xor ax, ax + mov [mx_DeltaY], ax + jmp @@Exit + +; Install user font +@@UserFont: + mov ax, -1 ; Assume an error + mov bx, [Width] + cmp bx, MAX_WIDTH + ja @@Exit ; Invalid character width + mov dx, [Height] + cmp dx, MAX_HEIGHT + ja @@Exit ; Invalid character height + mov [mx_FontWidth], bx + mov [mx_FontHeight], dx + mov ax, bx + add ax, 7 + .shr ax, 3 + mul dx + mov [mx_FontCharSize], ax + mov ax, WORD PTR Font[0] + mov WORD PTR mx_FontPtr[0], ax + mov ax, WORD PTR Font[2] + mov WORD PTR mx_FontPtr[2], ax + xor ax, ax + +@@Exit: + .pop ds + ASSUME ds:NOTHING + .leave ARG_SIZE +mxSetFont ENDP + +;----------------------------------------------------------- +; +; Sets the text color and raster op. +; +; Input: +; Color = text color (foreground + background*256) +; Op = raster op +; Output: +; none +; +mxSetTextColor PROC FAR + ARG Op:WORD, \ + Color:WORD = ARG_SIZE + .enter 0 + .push ds + + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, [Color] + mov [mx_FontColor], ax + mov ax, [Op] + mov [mx_FontOp], ax + + xor ax, ax + .pop ds + ASSUME ds:NOTHING + .leave ARG_SIZE +mxSetTextColor ENDP + +;----------------------------------------------------------- +; +; Writes a character using the current font and attributes. +; +; Input: +; X, Y = video coordinates +; C = character to print +; Output: +; none +; +mxOutChar PROC FAR + ARG C:BYTE:2, \ + Y:WORD, \ + X:WORD = ARG_SIZE + LOCAL Image:BYTE:MAX_WIDTH*MAX_HEIGHT, \ + Count:WORD = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, es, di + ASSUME ds:NOTHING + +; Gets the pointer to font data for the selected character + lds si, DWORD PTR [mx_FontPtr] + mov al, [C] + xor ah, ah + mul [mx_FontCharSize] ; Offset into font + add si, ax ; DS:SI -> font data for character + +; Converts font data into a 256-color linear image + mov ax, ss + mov es, ax + lea di, [Image] + mov dx, [mx_FontColor] + mov ax, [mx_FontHeight] + mov [Count], ax +@@HeightLoop: + mov cx, [mx_FontWidth] + mov bh, ds:[si] + inc si ; Get a byte from font data + cmp cx, 8 + jbe @@WidthLoop ; Ok for width <= 8 + mov bl, ds:[si] ; Get another byte + inc si +@@WidthLoop: + mov al, dl ; Assume foreground color + shl bx, 1 ; Is font bit set? + jc @@1 ; Yes, foreground is just great + mov al, dh ; Get background color +@@1: + mov es:[di], al ; Put pixel into image + inc di + dec cx + jnz @@WidthLoop + dec [Count] + jnz @@HeightLoop + +; Now pass image to mx_PutImage + lea ax, [Image] + push es + push ax ; Pointer to image + push [X] + push [Y] ; Image coordinates + push [mx_FontWidth] + push [mx_FontHeight] ; Image size + push [mx_FontOp] ; Raster op + call mxPutImage ; Write character + + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxOutChar ENDP + +;----------------------------------------------------------- +; +; Writes a string at the coordinates specified. +; +; Input: +; X, Y = text coordinates +; S = pointer to ASCIIZ string +; Output: +; none +; +mxOutText PROC FAR + ARG S:DWORD, \ + Y:WORD, \ + X:WORD = ARG_SIZE + .enter 0 + .push ds, si + ASSUME ds:NOTHING + + lds si, [S] +@@Loop: + mov al, ds:[si] + test al, al ; End of string? + jz @@Exit ; Yes, exit + inc si + push [X] ; Display character + push [Y] + push ax + call mxOutChar + mov ax, [mx_DeltaX] + add [X], ax ; Bump X coordinate + mov ax, [mx_DeltaY] + add [Y], ax ; Bump Y coordinate + dec [Count] + jnz @@Loop + +@@Exit: + xor ax, ax + .pop ds, si + .leave ARG_SIZE + ret +mxOutText ENDP + +;----------------------------------------------------------- +; +; Sets the distance between characters. +; +; Input: +; DeltaX = horizontal distance in pixels +; DeltaY = vertical distance in pixels +; Output: +; none +; +; Note: this function may be used to set the text direction. +; +mxSetTextStep PROC FAR + ARG DeltaY:WORD, \ + DeltaX:WORD = ARG_SIZE + .enter 0 + .push ds + + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, [DeltaX] + mov [mx_DeltaX], ax + mov ax, [DeltaY] + mov [mx_DeltaY], ax + + .pop ds + .leave ARG_SIZE +mxSetTextStep ENDP + +;----------------------------------------------------------- +; +; Gets the current distance between characters. +; +; Input: +; DeltaX = pointer to horizontal distance in pixels (integer) +; DeltaY = pointer to vertical distance in pixels (integer) +; Output: +; none +; +mxGetTextStep PROC FAR + ARG DeltaY:DWORD, \ + DeltaX:DWORD = ARG_SIZE + .enter 0 + .push ds, si + ASSUME ds:NOTHING + + mov ax, [mx_DeltaX] + lds si, [DeltaX] + mov ds:[si], ax + mov ax, [mx_DeltaY] + lds si, [DeltaY] + mov ds:[si], ax + + .pop ds, si + .leave ARG_SIZE +mxGetTextStep ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxpb.asm b/16/x_/mxpb.asm new file mode 100755 index 00000000..8c6aa449 --- /dev/null +++ b/16/x_/mxpb.asm @@ -0,0 +1,22 @@ +;----------------------------------------------------------- +; +; MXPB.ASM - Scan buffer for convex polygon fills +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mx_ScanBuffer + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +ALIGN 4 + +mx_ScanBuffer LABEL + DW POLYSCANBUFSIZE DUP(?) + +MX_TEXT ENDS +END diff --git a/16/x_/mxpf.asm b/16/x_/mxpf.asm new file mode 100755 index 00000000..db0da898 --- /dev/null +++ b/16/x_/mxpf.asm @@ -0,0 +1,420 @@ +;----------------------------------------------------------- +; +; MXPG.ASM - Convex polygon fill +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxFillPoly + +;----------------------------------------------------------- +; +; "Local" definitions +; +TPOINT STRUC + X DW ? + Y DW ? +TPOINT ENDS + +; Do NOT change order! +TSCAN STRUC + Y1 DW ? + Y2 DW ? +TSCAN ENDS + +MAXSCANCOLUMNS EQU POLYSCANBUFSIZE / SIZE TSCAN + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_VideoSegment : WORD +EXTRN mx_CodeSegment : WORD +EXTRN mx_BytesPerLine : WORD +EXTRN mx_ClipX1 : WORD +EXTRN mx_ClipY1 : WORD +EXTRN mx_ClipX2 : WORD +EXTRN mx_ClipY2 : WORD +EXTRN mx_ScanBuffer : NEAR + +;----------------------------------------------------------- +; +; Scans an edge using the DDA (digital differential analyzer) algorithm. +; +; Input: +; DS:BX = pointer to start point (X1, Y1) +; DS:SI = pointer to end point (X2, Y2) +; ES:DI = pointer to edge buffer +; Output: +; ES:DI = updated pointer to edge buffer +; Notes: +; must preserve DS:SI. +; +subScan PROC NEAR + mov cx, ds:[si].X + sub cx, ds:[bx].X ; Get width + jg @@1 + ret +@@1: + push bp ; Save BP + + mov ax, ds:[si].Y + mov bx, ds:[bx].Y + sub ax, bx ; Get height + jg @@T2B ; Scan top to bottom + jl @@B2T ; Scan bottom to top + +; Special case: vertical line + mov ax, bx +@@V: + mov es:[di].Y1, ax + add di, SIZE TSCAN + dec cx + jnz @@V + jmp @@Exit + +; Scan top to bottom +@@T2B: + cwd + div cx + mov bp, ax + xor ax, ax + div cx + xchg ax, bx ; BP:BX = fixed 16:16 step + mov dx, 8000h +@@T2BLoop: + mov es:[di].Y1, ax + add di, SIZE TSCAN + add dx, bx + adc ax, bp + dec cx + jnz @@T2BLoop + jmp @@Exit + +; Scan bottom to top +@@B2T: + neg ax + cwd + div cx + mov bp, ax + xor ax, ax + div cx + xchg ax, bx + mov dx, 8000h +@@B2TLoop: + mov es:[di].Y1, ax + add di, SIZE TSCAN + sub dx, bx + sbb ax, bp + dec cx + jnz @@B2TLoop + +@@Exit: + pop bp ; Restore BP + ret +subScan ENDP + +;----------------------------------------------------------- +; +; Fills a convex polygon with the specified color. +; +; Input: +; Count = number of vertexes +; Map = indexes of points and colors (integer) +; Points = array of points (integer X, Y coordinates) +; Color = base color +; Output: +; none +; Notes: +; vertexes must be in counterclockwise order, arrays are 0-based. +; +mxFillPoly PROC FAR + ARG Color:WORD, \ + Points:DWORD, \ + Map:DWORD, \ + Count:WORD = ARG_SIZE + LOCAL WritePlane:BYTE:2, \ + ScanOffsetT:WORD, \ + ScanOffsetB:WORD, \ + ScanCount:WORD, \ + Holder:WORD, \ + Height:WORD, \ + MinIdxT:WORD, \ + MinIdxB:WORD, \ + MaxIdx:WORD, \ + Width:WORD, \ + BoxX1:WORD, \ + BoxY1:WORD, \ + BoxX2:WORD, \ + BoxY2::WORD = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, es, di + ASSUME ds:NOTHING + +; Check that at least three vertexes are specified + mov cx, [Count] + cmp cx, 3 + jb @@Exit + +;------------------------------ +; Find bounding box for polygon + les di, [Map] + lds si, [Points] ; Pointer to vertex array + mov [BoxX1], 32767 + mov [BoxX2], -32768 + mov [BoxY1], 32767 + mov [BoxY2], -32768 + + xor dx, dx +@@MinMaxLoop: + mov bx, es:[di] ; Get index of vertex + .shl bx, 2 ; Get offset in point array + add bx, si + +; Check X range +@@CheckMinX: + mov ax, ds:[bx].X ; Get X coordinate + cmp ax, [BoxX1] + jge @@CheckMaxX + mov [BoxX1], ax + mov [MinIdxT], dx + mov [MinIdxB], dx +@@CheckMaxX: + cmp ax, [BoxX2] + jle @@CheckMinY + mov [BoxX2], ax + mov [MaxIdx], dx + +; Check Y range +@@CheckMinY: + mov ax, ds:[bx].Y + cmp ax, [BoxY1] + jge @@CheckMaxY + mov [BoxY1], ax +@@CheckMaxY: + cmp ax, [BoxY2] + jle @@CheckDone + mov [BoxY2], ax + +; Repeat thru all points +@@CheckDone: + inc di ; Next map entry + inc dx + inc di + inc dx + dec cx + jnz @@MinMaxLoop + +;--------------------------------- +; Check if polygon is full clipped + mov ax, [BoxX2] + cmp ax, [mx_ClipX1] ; Is poly full clipped? + jl @@Exit + mov bx, [BoxX1] + cmp bx, [mx_ClipX2] ; Is poly full clipped? + jg @@Exit + sub ax, bx ; Get width + jle @@Exit ; Exit if not positive + mov ax, [BoxY2] + cmp ax, [mx_ClipY1] ; Is poly full clipped? + jl @@Exit + mov bx, [BoxY1] + cmp bx, [mx_ClipY2] ; Is poly full clipped? + jg @@Exit + sub ax, bx ; Get height + jle @@Exit ; Exit if not positive + + dec [Count] + shl [Count], 1 ; We'll work with word offsets + mov es, [mx_CodeSegment] + +;-------------- +; Scan top edge + mov ax, OFFSET mx_ScanBuffer + mov [ScanOffsetT], ax + mov si, [MinIdxT] ; Offset of bottom point index +@@STLoop: + lds bx, [Map] ; DS:BX -> map table + mov di, ds:[bx+si] ; Index of top point #1 + dec si ; Next point + dec si + test si, si + jnl @@ST1 + mov si, [Count] +@@ST1: + mov [MinIdxT], si ; Save new index of top point + mov si, ds:[bx+si] ; Get index of top point #2 + .shl di, 2 ; Convert indexes to offsets + .shl si, 2 + lds bx, [Points] ; DS:BX -> point array + add si, bx ; DS:SI -> top point #2 + add bx, di ; DS:BX -> top point #1 + mov di, [ScanOffsetT] + call subScan ; Scan edge + mov [ScanOffsetT], di + mov si, [MinIdxT] + cmp si, [MaxIdx] ; End of edge? + jne @@STLoop ; No, continue + +;----------------- +; Scan bottom edge + mov ax, OFFSET mx_ScanBuffer + OFFSET Y2 + mov [ScanOffsetB], ax + mov si, [MinIdxB] ; Offset of bottom point index +@@SBLoop: + lds bx, [Map] ; DS:BX -> map table + mov di, ds:[bx+si] ; Index of bottom point #1 + inc si ; Next bottom point + inc si + cmp si, [Count] + jbe @@SB1 + xor si, si +@@SB1: + mov [MinIdxB], si ; Save new index of bottom point + mov si, ds:[bx+si] ; Get index of bottom point #2 + .shl di, 2 ; Convert indexes to offsets + .shl si, 2 + lds bx, [Points] ; DS:BX -> point array + add si, bx ; DS:SI -> top point #2 + add bx, di ; DS:BX -> top point #1 + mov di, [ScanOffsetB] + call subScan ; Scan edge + mov [ScanOffsetB], di + mov si, [MinIdxB] + cmp si, [MaxIdx] ; End of edge? + jne @@SBLoop ; No, continue + +;-------------------- +; Clip left and right + mov si, OFFSET mx_ScanBuffer + mov ax, [BoxX1] + mov cx, [BoxX2] + sub cx, ax ; CX = bounding box width + mov bx, [mx_ClipX1] + sub bx, ax + jle @@ClipL1 ; No need to clip left + sub cx, bx ; Update width + add ax, bx ; BoxX1 = mx_ClipX1 + mov [BoxX1], ax + .shl bx, 2 ; Warning!!! This is an hand-coded + add si, bx ; multiply by the size of TSCAN +@@ClipL1: + mov bx, ax + add bx, cx ; Last scan column + sub bx, [mx_ClipX2] + jle @@ClipL2 ; No need to clip right + sub cx, bx ; Clip right +@@ClipL2: + test cx, cx ; Is clipped width positive? + jle @@Exit ; No, exit + mov [ScanCount], cx ; Save number of columns to draw + mov [ScanOffsetT], si ; Remember offset of (clipped) buffer + mov ds, [mx_CodeSegment] ; DS:SI -> scan buffer + +;------------------------------ +; Check if Y clipping is needed + mov ax, [BoxY1] + cmp ax, [mx_ClipY1] + jl @@ClipTB ; Need to clip top + mov ax, [BoxY2] + cmp ax, [mx_ClipY2] + jg @@ClipTB ; Need to clip bottom + jmp @@ClipYExit ; Skip Y clipping + +;-------------------- +; Clip top and bottom +@@ClipTB: + mov di, cx ; DI = scan count + inc di ; Increment count for pre-loop test + sub si, SIZE TSCAN +@@ClipYLoop: + dec di ; Any column left? + jz @@ClipYExit ; No, exit + add si, SIZE TSCAN + mov ax, ds:[si].Y1 ; Y1 + mov cx, ds:[si].Y2 ; Y2 + mov dx, [mx_ClipY2] + cmp ax, dx ; Full clipped? + jg @@ClipYClip ; Yes, skip this column + cmp cx, dx ; Need to clip bottom? + jle @@ClipY1 ; No, continue +; Clip bottom + mov ds:[si].Y2, dx + mov bx, cx + sub bx, dx ; Clip distance + sub cx, ax ; Height + jle @@ClipYClip + mov cx, ds:[si].Y2 +@@ClipY1: + mov dx, [mx_ClipY1] + cmp cx, dx ; Full top clipped? + jl @@ClipYClip ; Yes, skip + sub cx, ax ; Get height + jle @@ClipYClip ; Skip if not positive + cmp ax, dx ; Need to clip top? + jge @@ClipYLoop ; No, continue +; Clip top + mov ds:[si].Y1, dx ; Y1 = mx_ClipY1 + sub dx, ax ; DX = number of pixels clipped + cmp cx, dx + ja @@ClipYLoop ; Not clipped, continue +@@ClipYClip: + mov ds:[si].Y1, -1 ; Mark column as clipped + jmp @@ClipYLoop +@@ClipYExit: + +;------------- +; Draw columns + mov es, [mx_VideoSegment] + mov si, [ScanOffsetT] + mov cl, BYTE PTR [BoxX1] ; Init write plane + and cl, 03h + mov al, 11h + shl al, cl + mov [WritePlane], al + .shr [BoxX1], 2 +@@DrawLoop: + mov ax, ds:[si].Y1 + test ax, ax ; Was column clipped? + js @@DrawNext ; Yes, skip + mov cx, ds:[si].Y2 + sub cx, ax ; CX = height + jle @@DrawNext + mul [mx_BytesPerLine] ; Get pixel address + add ax, [BoxX1] + mov di, ax + mov ah, [WritePlane] + mov dx, TS + mov al, 02h + out dx, ax + mov ax, [Color] + mov dx, [mx_BytesPerLine] + shr cx, 1 + jnc @@FillScan + mov es:[di], al + add di, dx + jcxz @@DrawNext +@@FillScan: + mov es:[di], al + add di, dx + mov es:[di], al + add di, dx + dec cx + jnz @@FillScan +@@DrawNext: + rol [WritePlane], 1 + adc [BoxX1], 0 ; Bump pointer to video memory if needed + add si, SIZE TSCAN + dec [ScanCount] + jnz @@DrawLoop + +@@Exit: + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxFillPoly ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxpg.asm b/16/x_/mxpg.asm new file mode 100755 index 00000000..caa7cf1b --- /dev/null +++ b/16/x_/mxpg.asm @@ -0,0 +1,589 @@ +;----------------------------------------------------------- +; +; MXPG.ASM - Convex polygon fill with Gouraud shading +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxGouraudPoly + +;----------------------------------------------------------- +; +; "Local" definitions +; +TPOINT STRUC + X DW ? + Y DW ? +TPOINT ENDS + +; Do NOT change order! +TSCAN STRUC + Y1 DW ? + E1 DB ? + C1 DB ? + Y2 DW ? + E2 DB ? + C2 DB ? +TSCAN ENDS + +MAXSCANCOLUMNS EQU POLYSCANBUFSIZE / SIZE TSCAN + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_VideoSegment : WORD +EXTRN mx_CodeSegment : WORD +EXTRN mx_BytesPerLine : WORD +EXTRN mx_ClipX1 : WORD +EXTRN mx_ClipY1 : WORD +EXTRN mx_ClipX2 : WORD +EXTRN mx_ClipY2 : WORD +EXTRN mx_ScanBuffer : NEAR + +;----------------------------------------------------------- +; +; Scans an edge using the DDA (digital differential analyzer) algorithm. +; Also interpolates color for shading. +; +; Input: +; DS:BX = pointer to start point (X1, Y1) +; DS:SI = pointer to end point (X2, Y2) +; ES:DI = pointer to edge buffer +; DX = start color +; AX = end color +; Output: +; ES:DI = updated pointer to edge buffer +; Notes: +; must preserve DS:SI. +; +subScan PROC NEAR + mov cx, ds:[si].X + sub cx, ds:[bx].X ; Get width + jg @@1 + ret +@@1: + push bp ; Save BP + push di ; Save scan info offset + push cx ; Save height + push ax ; Save colors + push dx + + mov ax, ds:[si].Y + mov bx, ds:[bx].Y + sub ax, bx ; Get height + jg @@T2B ; Scan top to bottom + jl @@B2T ; Scan bottom to top + +; Special case: vertical line + mov ax, bx +@@V: + mov es:[di].Y1, ax + add di, SIZE TSCAN + dec cx + jnz @@V + jmp @@GetColorInfo + +; Scan top to bottom +@@T2B: + cwd + div cx + mov bp, ax + xor ax, ax + div cx + xchg ax, bx ; BP:BX = fixed 16:16 step + mov dx, 8000h +@@T2BLoop: + mov es:[di].Y1, ax + add di, SIZE TSCAN + add dx, bx + adc ax, bp + dec cx + jnz @@T2BLoop + jmp @@GetColorInfo + +; Scan bottom to top +@@B2T: + neg ax + cwd + div cx + mov bp, ax + xor ax, ax + div cx + xchg ax, bx + mov dx, 8000h +@@B2TLoop: + mov es:[di].Y1, ax + add di, SIZE TSCAN + sub dx, bx + sbb ax, bp + dec cx + jnz @@B2TLoop + +; Now get the color info +@@GetColorInfo: + pop bx ; Restore colors + pop ax + pop cx ; Height + pop di ; ES:DI -> scan info + + sub ax, bx ; Get color range + jg @@CL2R + jl @@CR2L + +; Special case: same color + mov ah, bl + mov al, 80h +@@CV: + mov WORD PTR es:[di].E1, ax + add di, SIZE TSCAN + dec cx + jnz @@CV + jmp @@Exit + +; Scan left to right +@@CL2R: + cwd + div cx + mov bp, ax + xor ax, ax + div cx + xchg ax, bx ; BP:BX = fixed 16:16 step + mov dx, 8000h +@@CL2RLoop: + mov es:[di].C1, al + mov es:[di].E1, dh + add di, SIZE TSCAN + add dx, bx + adc ax, bp + dec cx + jnz @@CL2RLoop + jmp @@Exit + +; Scan right to left +@@CR2L: + neg ax + cwd + div cx + mov bp, ax + xor ax, ax + div cx + xchg ax, bx + mov dx, 8000h + +@@CR2LLoop: + mov es:[di].C1, al + mov es:[di].E1, dh + add di, SIZE TSCAN + sub dx, bx + sbb ax, bp + dec cx + jnz @@CR2LLoop + +@@Exit: + pop bp + ret +subScan ENDP + +;----------------------------------------------------------- +; +; Fills a scan column. +; +; Input: +; DS:SI = current TSCAN +; ES:DI = address of top pixel +; CX = number of pixels to write +; DX = base color +; Output: +; none +; +subFillScan PROC NEAR + mov ax, WORD PTR ds:[si].E2 + mov bx, WORD PTR ds:[si].E1 + cmp ah, bh + jg @@L2R ; Color increases + jl @@R2L ; Color decreases + +; Special case: color doesn't change + add ax, dx + mov dx, [mx_BytesPerLine] +@@V: + mov es:[di], ah + add di, dx + dec cx + jnz @@V + ret + +; Color increases +@@L2R: + .push bp, si + mov si, bx + add si, dx ; Relocate color + sub ax, bx + xor dx, dx + div cx + mov bp, ax ; BP = color step, integer part + xor ax, ax + div cx + mov bx, ax ; BX = color step, fractional part + mov dx, 8000h + mov ax, [mx_BytesPerLine] + xchg si, ax +@@L2RLoop: + mov es:[di], ah + add dx, bx + adc ax, bp + add di, si + dec cx + jnz @@L2RLoop + .pop bp, si + ret + +; Color decreases +@@R2L: + .push bp, si + mov si, bx + add si, dx ; Relocate color + sub ax, bx + neg ax + xor dx, dx + div cx + mov bp, ax ; BP = color step, integer part + xor ax, ax + div cx + mov bx, ax ; BX = color step, fractional part + mov dx, 8000h + mov ax, [mx_BytesPerLine] + xchg si, ax +@@R2LLoop: + mov es:[di], ah + sub dx, bx + sbb ax, bp + add di, si + dec cx + jnz @@R2LLoop + .pop bp, si + ret +subFillScan ENDP + +;----------------------------------------------------------- +; +; Fills a convex polygon with the specified color. +; Interpolates pixel colors using the Gouraud algorithm. +; +; Input: +; Count = number of vertexes +; Map = indexes of points and colors (integer) +; Points = array of points (integer X, Y coordinates) +; Colors = array of colors (integer) +; Color = base color +; Output: +; none +; Notes: +; vertexes must be in counterclockwise order, arrays are 0-based. +; +mxGouraudPoly PROC FAR + ARG Color:WORD, \ + Colors:DWORD, \ + Points:DWORD, \ + Map:DWORD, \ + Count:WORD = ARG_SIZE + LOCAL WritePlane:BYTE:2, \ + ScanOffsetT:WORD, \ + ScanOffsetB:WORD, \ + ScanCount:WORD, \ + Holder:WORD, \ + Height:WORD, \ + MinIdxT:WORD, \ + MinIdxB:WORD, \ + MaxIdx:WORD, \ + Width:WORD, \ + BoxX1:WORD, \ + BoxY1:WORD, \ + BoxX2:WORD, \ + BoxY2::WORD = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, es, di + ASSUME ds:NOTHING + +; Check that at least three vertexes are specified + mov cx, [Count] + cmp cx, 3 + jb @@Exit + +;------------------------------ +; Find bounding box for polygon + les di, [Map] + lds si, [Points] ; Pointer to vertex array + mov [BoxX1], 32767 + mov [BoxX2], -32768 + mov [BoxY1], 32767 + mov [BoxY2], -32768 + + xor dx, dx +@@MinMaxLoop: + mov bx, es:[di] ; Get index of vertex + .shl bx, 2 ; Get offset in point array + add bx, si + +; Check X range +@@CheckMinX: + mov ax, ds:[bx].X ; Get X coordinate + cmp ax, [BoxX1] + jge @@CheckMaxX + mov [BoxX1], ax + mov [MinIdxT], dx + mov [MinIdxB], dx +@@CheckMaxX: + cmp ax, [BoxX2] + jle @@CheckMinY + mov [BoxX2], ax + mov [MaxIdx], dx + +; Check Y range +@@CheckMinY: + mov ax, ds:[bx].Y + cmp ax, [BoxY1] + jge @@CheckMaxY + mov [BoxY1], ax +@@CheckMaxY: + cmp ax, [BoxY2] + jle @@CheckDone + mov [BoxY2], ax + +; Repeat thru all points +@@CheckDone: + inc di ; Next map entry + inc di + inc dx + inc dx + dec cx + jnz @@MinMaxLoop + +;--------------------------------- +; Check if polygon is full clipped + mov ax, [BoxX2] + cmp ax, [mx_ClipX1] ; Is poly full clipped? + jl @@Exit + mov bx, [BoxX1] + cmp bx, [mx_ClipX2] ; Is poly full clipped? + jg @@Exit + sub ax, bx ; Get width + jle @@Exit ; Exit if not positive + mov ax, [BoxY2] + cmp ax, [mx_ClipY1] ; Is poly full clipped? + jl @@Exit + mov bx, [BoxY1] + cmp bx, [mx_ClipY2] ; Is poly full clipped? + jg @@Exit + sub ax, bx ; Get height + jle @@Exit ; Exit if not positive + + dec [Count] + shl [Count], 1 ; We'll work with word offsets + mov es, [mx_CodeSegment] + +;-------------- +; Scan top edge + mov ax, OFFSET mx_ScanBuffer + mov [ScanOffsetT], ax + mov si, [MinIdxT] ; Offset of bottom point index +@@STLoop: + lds bx, [Map] ; DS:BX -> map table + mov di, ds:[bx+si] ; Index of top point #1 + dec si ; Next point + dec si + test si, si + jnl @@ST1 + mov si, [Count] +@@ST1: + mov [MinIdxT], si ; Save new index of top point + mov si, ds:[bx+si] ; Get index of top point #2 + lds bx, [Colors] ; Get pointer to color array + shl di, 1 ; Convert indexes to offsets + shl si, 1 + mov ax, ds:[bx+si] ; Get colors + mov dx, ds:[bx+di] + lds bx, [Points] ; DS:BX -> point array + shl si, 1 + shl di, 1 + add si, bx ; DS:SI -> top point #2 + add bx, di ; DS:BX -> top point #1 + mov di, [ScanOffsetT] + call subScan ; Scan edge + mov [ScanOffsetT], di + mov si, [MinIdxT] + cmp si, [MaxIdx] ; End of edge? + jne @@STLoop ; No, continue + +;----------------- +; Scan bottom edge + mov ax, OFFSET mx_ScanBuffer + OFFSET Y2 + mov [ScanOffsetB], ax + mov si, [MinIdxB] ; Offset of bottom point index +@@SBLoop: + lds bx, [Map] ; DS:BX -> map table + mov di, ds:[bx+si] ; Index of bottom point #1 + inc si ; Next bottom point + inc si + cmp si, [Count] + jbe @@SB1 + xor si, si +@@SB1: + mov [MinIdxB], si ; Save new index of bottom point + mov si, ds:[bx+si] ; Get index of bottom point #2 + lds bx, [Colors] ; Get pointer to color array + shl di, 1 ; Convert indexes to offsets + shl si, 1 + mov ax, ds:[bx+si] ; Get colors + mov dx, ds:[bx+di] + lds bx, [Points] ; DS:BX -> point array + shl si, 1 + shl di, 1 + add si, bx ; DS:SI -> top point #2 + add bx, di ; DS:BX -> top point #1 + mov di, [ScanOffsetB] + call subScan ; Scan edge + mov [ScanOffsetB], di + mov si, [MinIdxB] + cmp si, [MaxIdx] ; End of edge? + jne @@SBLoop ; No, continue + +;-------------------- +; Clip left and right + mov si, OFFSET mx_ScanBuffer + mov ax, [BoxX1] + mov cx, [BoxX2] + sub cx, ax ; CX = bounding box width + mov bx, [mx_ClipX1] + sub bx, ax + jle @@ClipL1 ; No need to clip left + sub cx, bx ; Update width + add ax, bx ; BoxX1 = mx_ClipX1 + mov [BoxX1], ax + .shl bx, 3 ; Warning!!! This is an hand-coded + add si, bx ; multiply by the size of TSCAN +@@ClipL1: + mov bx, ax + add bx, cx ; Last scan column + sub bx, [mx_ClipX2] + jle @@ClipL2 ; No need to clip right + sub cx, bx ; Clip right +@@ClipL2: + test cx, cx ; Is clipped width positive? + jle @@Exit ; No, exit + mov [ScanCount], cx ; Save number of columns to draw + mov [ScanOffsetT], si ; Remember offset of (clipped) buffer + mov ds, [mx_CodeSegment] ; DS:SI -> scan buffer + +;------------------------------ +; Check if Y clipping is needed + mov ax, [BoxY1] + cmp ax, [mx_ClipY1] + jl @@ClipTB ; Need to clip top + mov ax, [BoxY2] + cmp ax, [mx_ClipY2] + jg @@ClipTB ; Need to clip bottom + jmp @@ClipYExit ; Skip Y clipping + +;-------------------- +; Clip top and bottom +@@ClipTB: + mov di, cx ; DI = scan count + inc di ; Increment count for pre-loop test + sub si, SIZE TSCAN +@@ClipYLoop: + dec di ; Any column left? + jz @@ClipYExit ; No, exit + add si, SIZE TSCAN + mov ax, ds:[si].Y1 ; Y1 + mov cx, ds:[si].Y2 ; Y2 + mov dx, [mx_ClipY2] + cmp ax, dx ; Full clipped? + jg @@ClipYClip ; Yes, skip this column + cmp cx, dx ; Need to clip bottom? + jle @@ClipY1 ; No, continue +; Clip bottom, need to scale colors too + mov ds:[si].Y2, dx + mov bx, cx + sub bx, dx ; Clip distance + sub cx, ax ; Height + jle @@ClipYClip + mov ax, WORD PTR ds:[si].E1 + sub ax, WORD PTR ds:[si].E2 + imul bx + idiv cx + add WORD PTR ds:[si].E2, ax + mov ax, ds:[si].Y1 ; Restore AX and CX + mov cx, ds:[si].Y2 +@@ClipY1: + mov dx, [mx_ClipY1] + cmp cx, dx ; Full top clipped? + jl @@ClipYClip ; Yes, skip + sub cx, ax ; Get height + jle @@ClipYClip ; Skip if not positive + cmp ax, dx ; Need to clip top? + jge @@ClipYLoop ; No, continue +; Clip top, need to scale colors too + mov ds:[si].Y1, dx ; Y1 = mx_ClipY1 + sub dx, ax ; DX = number of pixels clipped + cmp cx, dx + jbe @@ClipYClip ; Full clipped, skip + mov ax, WORD PTR ds:[si].E2 + sub ax, WORD PTR ds:[si].E1 ; AX = color distance + imul dx + idiv cx + add WORD PTR ds:[si].E1, ax ; Update starting color + jmp @@ClipYLoop +@@ClipYClip: + mov ds:[si].Y1, -1 ; Mark column as clipped + jmp @@ClipYLoop +@@ClipYExit: + +;------------- +; Draw columns + mov es, [mx_VideoSegment] + mov si, [ScanOffsetT] + mov cl, BYTE PTR [BoxX1] ; Init write plane + and cl, 03h + mov al, 11h + shl al, cl + mov [WritePlane], al + .shr [BoxX1], 2 + mov ax, [Color] ; Make 8:8 fixed color + mov ah, al + xor al, al + mov [Color], ax +@@DrawLoop: + mov ax, ds:[si].Y1 + test ax, ax ; Was column clipped? + js @@DrawNext ; Yes, skip + mov cx, ds:[si].Y2 + sub cx, ax ; CX = height + jle @@DrawNext + mul [mx_BytesPerLine] ; Get pixel address + add ax, [BoxX1] + mov di, ax + mov ah, [WritePlane] + mov al, 02h + mov dx, TS + out dx, ax + mov dx, [Color] + call subFillScan +@@DrawNext: + rol [WritePlane], 1 + adc [BoxX1], 0 ; Bump pointer to video memory if needed + add si, SIZE TSCAN + dec [ScanCount] + jnz @@DrawLoop + +@@Exit: + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxGouraudPoly ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxpi.asm b/16/x_/mxpi.asm new file mode 100755 index 00000000..9e8525f5 --- /dev/null +++ b/16/x_/mxpi.asm @@ -0,0 +1,267 @@ +;----------------------------------------------------------- +; +; MXPI.ASM - Put image +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxPutImage + +EXTRN subClipImage : NEAR + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_VideoSegment : WORD +EXTRN mx_BytesPerLine : WORD + +mxTable LABEL WORD ; Raster ops + DW subMove + DW subAnd + DW subOr + DW subXor + DW subTrans + DW subAdd + +;----------------------------------------------------------- +; +; Move functions. +; Note: loops unrolled and optimized for CX even, no check for CX = 0. +; +subMove PROC NEAR + shr cx, 1 ; Make CX even + jc @@Odd ; Special case if odd byte +@@Loop: movsb + add si, 3 + movsb + add si, 3 + dec cx + jnz @@Loop +@@Exit: ret +@@Odd: movsb + add si, 3 + jcxz @@Exit + jmp @@Loop +subMove ENDP +; +subAnd PROC NEAR + shr cx, 1 + jc @@Odd +@@Loop: mov al, ds:[si] + mov ah, ds:[si+4] + and es:[di], ax + inc di + inc di + add si, 8 + dec cx + jnz @@Loop +@@Exit: ret +@@Odd: lodsb + and es:[di], al + inc di + add si, 3 + jcxz @@Exit + jmp @@Loop +subAnd ENDP +; +subOr PROC NEAR + shr cx, 1 + jc @@Odd +@@Loop: mov al, ds:[si] + mov ah, ds:[si+4] + or es:[di], ax + inc di + inc di + add si, 8 + dec cx + jnz @@Loop +@@Exit: ret +@@Odd: lodsb + or es:[di], al + inc di + add si, 3 + jcxz @@Exit + jmp @@Loop +subOr ENDP +; +subXor PROC NEAR + shr cx, 1 + jc @@Odd +@@Loop: mov al, ds:[si] + mov ah, ds:[si+4] + xor es:[di], ax + inc di + inc di + add si, 8 + dec cx + jnz @@Loop +@@Exit: ret +@@Odd: lodsb + xor es:[di], al + inc di + add si, 3 + jcxz @@Exit + jmp @@Loop +subXor ENDP +; +subTrans PROC NEAR +@@Loop: mov al, ds:[si] + cmp al, ah + je @@Skip + mov es:[di], al +@@Skip: inc di + add si, 4 + dec cx + jnz @@Loop +@@Exit: ret +subTrans ENDP +; +subAdd PROC NEAR +@@Loop: mov al, ds:[si] + add es:[di], al + inc di + add si, 4 + dec cx + jnz @@Loop + ret +subAdd ENDP + +;----------------------------------------------------------- +; +; Copies a "raw" image from memory to screen. +; +; Input: +; Image = pointer to image +; X, Y = coordinates of destination +; Width = width of image in pixels +; Height = height of image in pixels +; Op = raster op (OP_xxx) +; Output: +; none +; +mxPutImage PROC FAR + ARG Op:WORD, \ + Height:WORD, \ + Width:WORD, \ + Y:WORD, \ + X:WORD, \ + Image:DWORD = ARG_SIZE + LOCAL PlaneWidth:WORD:4, \ + PixelOffset:WORD, \ + MoveFunction:WORD, \ + Count:BYTE, \ + ReadPlane:BYTE, \ + OpInfo:BYTE, \ + WritePlane:BYTE = AUTO_SIZE + ASSUME ds:NOTHING + .enter AUTO_SIZE + .push ds, si, es, di + +; Clip image + mov bx, [X] + mov ax, [Y] + mov cx, [Width] + mov dx, [Height] + call subClipImage + jc @@Exit ; Full clipped + mov [Height], dx + add WORD PTR Image[0], si ; Skip clipped pixels + +; Get pixel address + mul [mx_BytesPerLine] + mov di, bx + shr di, 1 + shr di, 1 + add di, ax + mov [PixelOffset], di + mov es, [mx_VideoSegment] ; ES:DI points to pixel + and bl, 03h + mov [ReadPlane], bl + +; Compute extra bytes and width count for each plane + mov bx, cx + shr bx, 1 + shr bx, 1 ; Width for each plane + and cl, 03h + mov al, 00001000b + shr al, cl + mov si, 3 SHL 1 +@@PatchLoop: + mov PlaneWidth[si], bx + shr al, 1 + adc bx, 0 + dec si + dec si + jge @@PatchLoop + +; Setup planes for output to VGA registers + mov cl, [ReadPlane] + mov al, 00010001b + shl al, cl + mov [WritePlane], al + +; Install move function + mov bx, [Op] + mov [OpInfo], bh ; Remember additional info if needed + xor bh, bh + cmp bl, OP_ADD + jbe @@SetMoveFunction + xor bl, bl +@@SetMoveFunction: + shl bx, 1 + mov ax, mxTable[bx] + mov [MoveFunction], ax + +; Put image + cld + mov [Count], 4 ; Four planes + lea bx, PlaneWidth ; SS:[BX] = width in bytes for plane + mov ds, WORD PTR Image[2] +@@PlaneLoop: + cmp WORD PTR ss:[bx], 0 ; Exit if nothing more to do + je @@Exit ; (also, never try to move zero bytes!) + mov si, WORD PTR Image[0] + mov ah, [WritePlane] + and ah, 0Fh + mov al, 02h + mov dx, TS + out dx, ax ; Select write plane + mov ah, [ReadPlane] + and ah, 03h + mov al, 04h + mov dx, GDC + out dx, ax ; Select read plane + mov dx, [Height] + mov di, [PixelOffset] +@@Loop: + push si + push di + mov cx, WORD PTR ss:[bx] ; Number of bytes to move + mov ah, [OpInfo] ; Transparent color for subTrans + call [MoveFunction] + pop di + pop si + add si, [Width] ; Go to next image line + add di, [mx_BytesPerLine] ; Go to next screen row + dec dx + jnz @@Loop ; Repeat for all lines + inc bx + inc bx ; Select width for next plane + inc [ReadPlane] + rol [WritePlane], 1 + adc [PixelOffset], 0 + inc WORD PTR Image[0] + dec [Count] + jnz @@PlaneLoop ; Repeat for all planes + +@@Exit: + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxPutImage ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxpn.asm b/16/x_/mxpn.asm new file mode 100755 index 00000000..eaaf61b4 --- /dev/null +++ b/16/x_/mxpn.asm @@ -0,0 +1,60 @@ +;----------------------------------------------------------- +; +; MXPN.ASM - Panning function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxPan + +EXTRN mxWaitDisplay : FAR +EXTRN mxStartAddress : FAR + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD + +;----------------------------------------------------------- +; +; Moves the screen. +; +; Input: +; X, Y = new X, Y coordinates of view screen +; Output: +; none +; +mxPan PROC FAR + ARG Y:WORD, \ + X:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + + mov ax, [Y] + mul [mx_BytesPerLine] + mov dx, [X] + shr dx, 1 + shr dx, 1 + add ax, dx + push ax ; Push the start address + call mxWaitDisplay + call mxStartAddress + + mov dx, 03DAh ; Set the pixel pan register + in al, dx + mov dx, 03C0h + mov al, 33h + out dx, al + mov al, BYTE PTR [X] + and al, 3 + shl al, 1 + out dx, al + + xor ax, ax + .leave ARG_SIZE +mxPan ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxpp.asm b/16/x_/mxpp.asm new file mode 100755 index 00000000..fc1755a3 --- /dev/null +++ b/16/x_/mxpp.asm @@ -0,0 +1,121 @@ +;----------------------------------------------------------- +; +; MXPP.ASM - Get/put pixel functions +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxGetPixel +PUBLIC mxPutPixel + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD +EXTRN mx_VideoSegment : WORD +EXTRN mx_ClipX1 : WORD +EXTRN mx_ClipY1 : WORD +EXTRN mx_ClipX2 : WORD +EXTRN mx_ClipY2 : WORD + +;----------------------------------------------------------- +; +; Gets a pixel. +; +; Input: +; X, Y = pixel coordinates +; Output: +; pixel color +; +mxGetPixel PROC FAR + ARG Y:WORD, \ + X:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si + + xor ax, ax + mov si, [X] + cmp si, [mx_ClipX1] + jl @@Exit + cmp si, [mx_ClipX2] + jg @@Exit + mov bx, [Y] + cmp bx, [mx_ClipY1] + jl @@Exit + cmp bx, [mx_ClipY2] + jg @@Exit + + mov al, 04h ; Set read plane + mov ah, BYTE PTR [X] + and ah, 3 + mov dx, GDC + out dx, ax + + mov ds, [mx_VideoSegment] + mov ax, bx + mul [mx_BytesPerLine] + .shr si, 2 + add si, ax + + mov al, ds:[si] ; Get pixel value + xor ah, ah + +@@Exit: + .pop ds, si + .leave ARG_SIZE +mxGetPixel ENDP + +;----------------------------------------------------------- +; +; Puts a pixel of the specified color. +; +; Input: +; X, Y = pixel coordinates +; Color = pixel color +; Output: +; none +; +mxPutPixel PROC FAR + ARG Color:BYTE:2, \ + Y:WORD, \ + X:WORD = ARG_SIZE + .enter 0 + .push ds, si + + mov si, [X] + cmp si, [mx_ClipX1] + jl @@Exit + cmp si, [mx_ClipX2] + jg @@Exit + mov ax, [Y] + cmp ax, [mx_ClipY1] + jl @@Exit + cmp ax, [mx_ClipY2] + jg @@Exit + + mov ds, [mx_VideoSegment] + mul [mx_BytesPerLine] + .shr si, 2 + add si, ax + + mov cl, BYTE PTR [X] ; Set write plane + and cl, 3 + mov ax, 0102h + shl ah, cl + mov dx, TS + out dx, ax + + mov al, [Color] ; Write pixel + mov ds:[si], al + +@@Exit: + xor ax, ax + .pop ds, si + .leave ARG_SIZE +mxPutPixel ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxra.asm b/16/x_/mxra.asm new file mode 100755 index 00000000..dd8e6839 --- /dev/null +++ b/16/x_/mxra.asm @@ -0,0 +1,37 @@ +;----------------------------------------------------------- +; +; MXRA.ASM - Row address +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxRowAddress + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Sets the row address register. +; +; Input: +; RowAddress = row size in words +; Output: +; none +; +mxRowAddress PROC FAR + ARG RowAddress:BYTE:2 = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + mov dx, CRTC + mov al, 13h + mov ah, [RowAddress] + out dx, ax + xor ax, ax + .leave ARG_SIZE +mxRowAddress ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxrp.asm b/16/x_/mxrp.asm new file mode 100755 index 00000000..de820c16 --- /dev/null +++ b/16/x_/mxrp.asm @@ -0,0 +1,101 @@ +;----------------------------------------------------------- +; +; MXRP.ASM - Rotate palette function +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxRotatePalette + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Rotates the palette of the specified number of colors. +; +; Input: +; Palette = pointer to palette +; Count = number of colors to rotate +; Step = step size +; Output: +; none +; +; Note: if Step is positive palette is rotated left to right, otherwise +; right to left. +; +mxRotatePalette PROC FAR + ARG Step:WORD, \ + Count:WORD, \ + Palette:DWORD = ARG_SIZE + LOCAL Holder:BYTE:768 = AUTO_SIZE + ASSUME ds:NOTHING + .enter AUTO_SIZE + .push ds, si, es, di + + mov bx, [Count] + add bx, bx + add bx, [Count] ; BX = Count*3 + + lds si, [Palette] ; DS:SI -> palette + push ss + pop es + lea di, Holder ; ES:DI -> local space + cld + + mov ax, [Step] + mov dx, ax + test ax, ax + jz @@Exit ; Nothing to do, exit + jl @@RightToLeft + +@@LeftToRight: + add ax, ax + add dx, ax ; DX = Step*3 + sub bx, dx ; BX = (Count-Step)*3 + add si, bx + push si + mov cx, dx + rep movsb + mov es, WORD PTR Palette[2] + mov di, si + dec di ; ES:DI -> last byte of palette + pop si + dec si + mov cx, bx + std + rep movsb + push ss + pop ds + lea si, Holder + les di, [Palette] + mov cx, dx + cld + rep movsb + jmp @@Exit + +@@RightToLeft: + add ax, ax + add dx, ax + neg dx ; DX = Step*3 + sub bx, dx ; BX = (Count-Step)*3 + mov cx, dx + rep movsb + les di, [Palette] + mov cx, bx + rep movsb + push ss + pop ds + lea si, Holder + mov cx, dx + rep movsb + +@@Exit: + .pop ds, si, es, di + .leave ARG_SIZE +mxRotatePalette ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxsa.asm b/16/x_/mxsa.asm new file mode 100755 index 00000000..3ebae67d --- /dev/null +++ b/16/x_/mxsa.asm @@ -0,0 +1,44 @@ +;----------------------------------------------------------- +; +; MXSA.ASM - Start address function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxStartAddress + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Modifies the starting address of video memory. +; +; Input: +; StartAddr = new start address of video memory +; Output: +; none +; +mxStartAddress PROC FAR + ARG StartAddr:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + + mov bx, [StartAddr] + mov dx, CRTC + mov al, 0Ch ; Linear Starting Address high + mov ah, bh + cli + out dx, ax + mov al, 0Dh ; Linear Starting Address low + mov ah, bl + out dx, ax + sti + + .leave ARG_SIZE +mxStartAddress ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxsc.asm b/16/x_/mxsc.asm new file mode 100755 index 00000000..bcae45e6 --- /dev/null +++ b/16/x_/mxsc.asm @@ -0,0 +1,50 @@ +;----------------------------------------------------------- +; +; MXSC.ASM - Set color function +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxSetColor + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Updates the selected DAC register. +; +; Input: +; Index = index of color to set +; R, G, B = color components +; Output: +; none +; +mxSetColor PROC FAR + ARG B:BYTE:2, \ + G:BYTE:2, \ + R:BYTE:2, \ + Index:WORD = ARG_SIZE + .enter 0 + .push ds, si + + mov ax, [Index] + mov dx, 3C8h ; PEL write address register + out dx, al + inc dx + + mov al, [R] + out dx, al + mov al, [G] + out dx, al + mov al, [B] + out dx, al + + .pop ds, si + .leave ARG_SIZE +mxSetColor ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxsi.asm b/16/x_/mxsi.asm new file mode 100755 index 00000000..b88d3b11 --- /dev/null +++ b/16/x_/mxsi.asm @@ -0,0 +1,317 @@ +;----------------------------------------------------------- +; +; MXPI.ASM - Stretch image +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxStretchImage + +EXTRN subClipBox : NEAR + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_VideoSegment : WORD +EXTRN mx_BytesPerLine : WORD + +mxTable LABEL WORD ; Raster ops + DW subMove + DW subAnd + DW subOr + DW subXor + DW subTrans + DW subAdd + +;----------------------------------------------------------- +; +; Stretches and copies a "raw" image from memory to screen. +; +; Input: +; Image = pointer to image +; X, Y = coordinates of destination +; Width = width of image in pixels +; Height = height of image in pixels +; NewWidth = new width of image in pixels +; NewHeight = new height of image in pixels +; Op = raster op (OP_xxx) +; Output: +; none +; +mxStretchImage PROC FAR + ARG Op:WORD, \ + NewHeight:WORD, \ + NewWidth:WORD, \ + Height:WORD, \ + Width:WORD, \ + Y:WORD, \ + X:WORD, \ + Image:DWORD = ARG_SIZE + LOCAL PixelOffset:WORD, \ + MoveFunction:WORD, \ + ReadPlane:BYTE, \ + OpInfo:BYTE, \ + WidthStep:DWORD, \ + HeightStep:DWORD, \ + ImageLo:WORD, \ + WritePlane:BYTE = AUTO_SIZE + ASSUME ds:NOTHING + .enter AUTO_SIZE + .push ds, si, es, di + +; Get width stretch factor + IF USE386 EQ TRUE + movzx edx, [Width] + xor eax, eax + movzx ebx, [NewWidth] + shl ebx, 16 + idiv ebx + mov [WidthStep], eax + ELSE + xor dx, dx ; Width stretch factor + mov ax, [Width] + mov bx, [NewWidth] + div bx + mov WORD PTR WidthStep[2], ax + xor ax, ax + div bx + mov WORD PTR WidthStep[0], ax + ENDIF +; Get height stretch factor + IF USE386 EQ TRUE + movzx edx, [Height] + xor eax, eax + movzx ebx, [NewHeight] + shl ebx, 16 + idiv ebx + mov [HeightStep], eax + ELSE + xor dx, dx + mov ax, [Height] + mov bx, [NewHeight] + div bx + mov WORD PTR HeightStep[2], ax + xor ax, ax + div bx + mov WORD PTR HeightStep[0], ax + ENDIF + +; Clip image + mov bx, [X] + mov ax, [Y] + mov cx, [NewWidth] + mov dx, [NewHeight] + call subClipBox + jc @@Exit ; Full clipped + mov [NewWidth], cx + mov [NewHeight], dx + sub [X], bx + sub [Y], ax + +; Get pixel address + mul [mx_BytesPerLine] + mov di, bx + shr di, 1 + shr di, 1 + add di, ax + mov [PixelOffset], di + mov es, [mx_VideoSegment] ; ES:DI points to pixel + and bl, 03h + mov [ReadPlane], bl ; Set read plane + mov cl, bl + mov al, 00010001b + shl al, cl + mov [WritePlane], al ; Set write plane + +; Relocate image origin if previously clipped + mov ax, [Y] + test ax, ax + jz @@OriginYDone + IF USE386 EQ TRUE + shl eax, 16 + imul [HeightStep] + mov ax, [Width] + mul dx + ELSE + mov bx, ax + mul WORD PTR HeightStep[0] + mov cx, dx + mov ax, bx + mul WORD PTR HeightStep[2] + add ax, cx + mul [Width] + ENDIF + add WORD PTR [Image], ax +@@OriginYDone: + mov ax, [X] + test ax, ax + jz @@OriginXDone + IF USE386 EQ TRUE + shl eax, 16 + imul [WidthStep] + add WORD PTR [Image], dx + ELSE + mov bx, ax + mul WORD PTR WidthStep[0] + mov cx, dx + mov ax, bx + mul WORD PTR WidthStep[2] + add ax, cx + add WORD PTR [Image], ax + ENDIF +@@OriginXDone: + mov ax, WORD PTR HeightStep[2] + mul [Width] + mov WORD PTR HeightStep[2], ax + +; Install move function + mov bx, [Op] + mov [OpInfo], bh ; Remember additional info if needed + xor bh, bh + cmp bl, OP_ADD + jbe @@SetMoveFunction + xor bl, bl +@@SetMoveFunction: + shl bx, 1 + mov ax, mxTable[bx] + mov [MoveFunction], ax + +; Put image + mov ds, WORD PTR Image[2] + xor ax, ax + mov [ImageLo], ax +@@Loop: + mov si, WORD PTR Image[0] ; Get pointer to image + mov ah, [WritePlane] + and ah, 0Fh + mov al, 02h + mov dx, TS + out dx, ax ; Select write plane + mov ah, [ReadPlane] + and ah, 03h + mov al, 04h + mov dx, GDC + out dx, ax ; Select read plane + mov cx, [NewHeight] + mov di, [PixelOffset] ; ES:DI points to video memory + mov ah, [OpInfo] ; Additional raster op info + xor bx, bx + mov dx, [mx_BytesPerLine] + call [MoveFunction] ; Draw column + inc [ReadPlane] ; Next read plane + rol [WritePlane], 1 ; Next write plane + adc [PixelOffset], 0 ; Update video offset if needed + mov dx, WORD PTR WidthStep[0] + mov ax, WORD PTR WidthStep[2] + add [ImageLo], dx + adc WORD PTR Image[0], ax ; Next image column + dec [NewWidth] + jnz @@Loop ; Repeat for all columns + +@@Exit: + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE + +;----------------------------------------------------------- +; +; Move functions, on entry: +; AH = additional raster op info (e.g. transparent color) +; BX = 0, +; CX = pixel count, +; DX = mx_BytesPerLine. +; +subMove PROC NEAR +@@Loop: mov al, ds:[si] + mov es:[di], al + add di, dx + dec cx + jz @@Exit + add si, WORD PTR HeightStep[2] + add bx, WORD PTR HeightStep[0] + jnc @@Loop + add si, [Width] + jmp @@Loop +@@Exit: ret +subMove ENDP +; +subAnd PROC NEAR +@@Loop: mov al, ds:[si] + and es:[di], al + add di, dx + dec cx + jz @@Exit + add si, WORD PTR HeightStep[2] + add bx, WORD PTR HeightStep[0] + jnc @@Loop + add si, [Width] + jmp @@Loop +@@Exit: ret +subAnd ENDP +; +subOr PROC NEAR +@@Loop: mov al, ds:[si] + or es:[di], al + add di, dx + dec cx + jz @@Exit + add si, WORD PTR HeightStep[2] + add bx, WORD PTR HeightStep[0] + jnc @@Loop + add si, [Width] + jmp @@Loop +@@Exit: ret +subOr ENDP +; +subXor PROC NEAR +@@Loop: mov al, ds:[si] + xor es:[di], al + add di, dx + dec cx + jz @@Exit + add si, WORD PTR HeightStep[2] + add bx, WORD PTR HeightStep[0] + jnc @@Loop + add si, [Width] + jmp @@Loop +@@Exit: ret +subXor ENDP +; +subTrans PROC NEAR +@@Loop: mov al, ds:[si] + cmp al, ah + je @@Skip + mov es:[di], al +@@Skip: + add di, dx + dec cx + jz @@Exit + add si, WORD PTR HeightStep[2] + add bx, WORD PTR HeightStep[0] + jnc @@Loop + add si, [Width] + jmp @@Loop +@@Exit: ret +subTrans ENDP +; +subAdd PROC NEAR +@@Loop: mov al, ds:[si] + add es:[di], al + add di, dx + dec cx + jz @@Exit + add si, WORD PTR HeightStep[2] + add bx, WORD PTR HeightStep[0] + jnc @@Loop + add si, [Width] + jmp @@Loop +@@Exit: ret +subAdd ENDP + +mxStretchImage ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxsl.asm b/16/x_/mxsl.asm new file mode 100755 index 00000000..d7908855 --- /dev/null +++ b/16/x_/mxsl.asm @@ -0,0 +1,62 @@ +;----------------------------------------------------------- +; +; MXLN.ASM - Start line function +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxStartLine + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD + +;----------------------------------------------------------- +; +; Changes the video start address to the specified line. +; +; Input: +; Line = new start line +; Output: +; none +; +mxStartLine PROC FAR + ARG Line:WORD = ARG_SIZE + .enter 0 + ASSUME ds:NOTHING + + mov ax, [Line] ; Get video offset + mul [mx_BytesPerLine] + xchg ax, bx ; Copy it into BX + +; Wait display + mov dx, STATUS +@@1: in al, dx + test al, 08h + jnz @@1 + +; Set starting address + mov dx, CRTC + mov al, 0Ch ; Linear Starting Address high + mov ah, bh + cli + out dx, ax + mov al, 0Dh ; Linear Starting Address low + mov ah, bl + out dx, ax + sti + +; Wait retrace + mov dx, STATUS +@@2: in al,dx + test al, 08h + jz @@2 + + xor ax, ax + .leave ARG_SIZE +MX_TEXT ENDS +END diff --git a/16/x_/mxsm.asm b/16/x_/mxsm.asm new file mode 100755 index 00000000..183fba1e --- /dev/null +++ b/16/x_/mxsm.asm @@ -0,0 +1,508 @@ +;----------------------------------------------------------- +; +; MXSM.ASM - Set/change mode functions +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxChangeMode +PUBLIC mxGetAspect +PUBLIC mxGetScreenSize +PUBLIC mxSetMode + +PUBLIC mx_ScreenWidth +PUBLIC mx_ScreenHeight +PUBLIC mx_BytesPerLine + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mxSetSysClipRegion : FAR + +EXTRN mx_VideoSegment : WORD +EXTRN mx_CodeSegment : WORD + +mx_ScreenWidth DW ? ; Current screen width +mx_ScreenHeight DW ? +mx_AspectX DW ? ; Aspect ratio for current mode +mx_AspectY DW ? +mx_BytesPerLine DW 0 ; Bytes per line + +; +; Tables for setting video modes, sources: +; - MODEX.ASM, Matt Pritchard +; - Dr. Dobb's Journal, Michael Abrash +; - Fractint VIDEO.ASM module +; +TBL_SingleLine LABEL WORD ; CRTC + DW 04009h ; Cell height: 1 scan line + DW 00014h ; Double word mode off + DW 0E317h ; Byte mode on + DW 0 +TBL_DoubleLine LABEL WORD ; CRTC + DW 04109h ; Cell height: 2 scan lines + DW 00014h + DW 0E317h + DW 0 +TBL_Width320 LABEL WORD ; CRTC + DW 05F00h ; Horizontal total + DW 04F01h ; Horizontal displayed + DW 05002h ; Start horizontal blanking + DW 08203h ; End horizontal blanking + DW 05404h ; Start horizontal sync + DW 08005h ; End horizontal sync + DW 02813h ; Row address + DW 0 +TBL_Width360 LABEL WORD ; CRTC + DW 06B00h ; Horizontal total + DW 05901h ; Horizontal displayed + DW 05A02h ; Start horizontal blanking + DW 08E03h ; End horizontal blanking + DW 05E04h ; Start horizontal sync + DW 08A05h ; End horizontal sync + DW 02D13h ; Row address + DW 0 +TBL_Height175 LABEL WORD ; CRTC + DW 0BF06h ; Vertical total + DW 01F07h ; Overflow + DW 08310h ; Start vertical sync + DW 08511h ; End vertical sync + DW 05D12h ; Vertical displayed + DW 06315h ; Start vertical blanking + DW 0BA16h ; End vertical blanking + DW 0 +TBL_Height200 LABEL WORD ; CRTC + DW 0BF06h ; Vertical total + DW 01F07h ; Overflow + DW 09C10h ; Start vertical sync + DW 08E11h ; End vertical sync + DW 08F12h ; Vertical displayed + DW 09615h ; Start vertical blanking + DW 0B916h ; End vertical blanking + DW 0 +TBL_Height240 LABEL WORD ; CRTC + DW 00D06h ; Vertical total + DW 03E07h ; Overflow + DW 0EA10h ; Start vertical sync + DW 08C11h ; End vertical sync + DW 0DF12h ; Vertical displayed + DW 0E715h ; Start vertical blanking + DW 00616h ; End vertical blanking + DW 0 +TBL_Tweak400x600: + DW 07400h + DW 06301h + DW 06402h + DW 09703h + DW 06804h + DW 09505h + DW 08606h + DW 0F007h + DW 06009h + DW 0310Fh + DW 05B10h + DW 08D11h + DW 05712h + DW 03213h + DW 00014h + DW 06015h + DW 08016h + DW 0E317h + DW 0 + +TBL_320x200: + DB 63h ; 400 scan lines, 25 MHz clock + DW 6, 5 ; Aspect: 6/5 = 1.2:1 + DW 320, 200 ; Size + DW TBL_Width320, TBL_Height200, TBL_DoubleLine, 0 + DW 819 ; Max height +TBL_320x240: + DB 0E3h ; 400 scan lines, 25 MHz clock + DW 1, 1 ; Aspect: 1/1 = 1:1 + DW 320, 240 ; Size + DW TBL_Width320, TBL_Height240, TBL_DoubleLine, 0 + DW 819 ; Max height +TBL_320x400: + DB 63h ; 480 scan lines, 25 MHz clock + DW 6, 10 ; Aspect: 6/10 = 0.6:1 + DW 320, 400 ; Size + DW TBL_Width320, TBL_Height200, TBL_SingleLine, 0 + DW 819 ; Max height +TBL_320x480: + DB 0E3h ; 480 scan lines, 25 MHz clock + DW 1, 2 ; Aspect: 1/2 = 0.5:1 + DW 320, 480 ; Size + DW TBL_Width320, TBL_Height240, TBL_SingleLine, 0 + DW 819 ; Max height +TBL_360x200: + DB 067h ; 400 scan lines, 28 MHz clock + DW 27, 20 ; Aspect: 27/20 = 1.35:1 + DW 360, 200 ; Size + DW TBL_Width360, TBL_Height200, TBL_DoubleLine, 0 + DW 728 ; Max height +TBL_360x240: + DB 0E7h ; 480 scan lines, 28 MHz clock + DW 9, 8 ; Aspect: 9/8 = 1.125:1 + DW 360, 240 ; Size + DW TBL_Width360, TBL_Height240, TBL_DoubleLine, 0 + DW 728 ; Max height +TBL_360x400: + DB 067h ; 400 scan lines, 28 MHz clock + DW 27, 40 ; Aspect: 27/40 = 0.675:1 + DW 360, 400 ; Size + DW TBL_Width360, TBL_Height200, TBL_SingleLine, 0 + DW 728 ; Max height +TBL_360x480: + DB 0E7h ; 480 scan lines, 28 MHz clock + DW 9, 16 ; Aspect: 9/16 = 0.5625:1 + DW 360, 480 ; Size + DW TBL_Width360, TBL_Height240, TBL_SingleLine, 0 + DW 728 ; Max height +TBL_320x175: + DB 0A3h + DW 0, 0 ; Aspect: + DW 320, 175 + DW TBL_Width320, TBL_Height175, TBL_DoubleLine, 0 + DW 819 +TBL_320x350: + DB 0A3h + DW 0, 0 ; Aspect: + DW 320, 175 + DW TBL_Width320, TBL_Height175, TBL_SingleLine, 0 + DW 819 +TBL_360x175: + DB 0A7h + DW 0, 0 ; Aspect: + DW 360, 480 ; Size + DW TBL_Width360, TBL_Height175, TBL_DoubleLine, 0 + DW 728 ; Max height +TBL_360x350: + DB 0A7h + DW 0, 0 ; Aspect: + DW 360, 480 ; Size + DW TBL_Width360, TBL_Height175, TBL_SingleLine, 0 + DW 728 ; Max height +TBL_400x600: + DB 0E7h ; 28 MHz clock + DW 1, 2 ; Aspect: 1/2 = 0.5:1 + DW 400, 600 ; Size + DW TBL_Tweak400x600, 0 + DW 655 ; Max height + +TBL_Mode LABEL WORD + DW TBL_320x175 + DW TBL_320x200 + DW TBL_320x240 + DW TBL_320x350 + DW TBL_320x400 + DW TBL_320x480 + DW TBL_360x175 + DW TBL_360x200 + DW TBL_360x240 + DW TBL_360x350 + DW TBL_360x400 + DW TBL_360x480 + DW TBL_400x600 + +MAXVMODE EQU ($-OFFSET TBL_Mode) / 2 + +;----------------------------------------------------------- +; +; Enables 80x25 color text mode +; +subText PROC NEAR + ASSUME ds:MX_TEXT + mov ax, 0003h + int 10h ; Call BIOS set mode + + mov [mx_ScreenHeight], 0 + mov [mx_BytesPerLine], 0 + ret +subText ENDP + +;----------------------------------------------------------- +; +; Enables the selected graphics mode. +; +; Input: +; Mode = mode to select (MX_???x???) +; Output: +; none +; +mxSetMode PROC FAR + ARG Mode:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si, es, di + +; Set DS to code segment alias + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov si, [Mode] + cmp si, MAXVMODE ; Is it a valid mode? + ja @@Exit ; No, exit + test si, si ; Text mode? + jnz @@Set ; No, handle it + + call subText ; Back to text mode + jmp @@Exit ; Exit now + +; Set video mode +@@Set: + dec si ; Skip text mode + shl si, 1 + mov si, TBL_Mode[si] + cld + +; Use BIOS to set 320x200x256 linear mode + push si ; Save SI + mov ax, 0013h + int 10h ; Use BIOS to set 320x200 linear mode + pop si ; Restore SI + + mov dx, TS + mov ax, 0604h + out dx, ax ; Disable chain-4 mode + mov ax, 0100h + out dx, ax ; Reset + mov dx, MISC + lodsb + out dx, al ; New timing/size + mov dx, TS + mov ax, 0300h + out dx, ax ; Restart sequencer + +; Unlock CRTC registers 0-7 + mov dx, CRTC + mov al, 11h + out dx, al ; Vertical sync end register + inc dx + in al, dx + and al, 7Fh ; Clear write protect bit + out dx, al + + lodsw ; Get X aspect + mov [mx_AspectX], ax + lodsw ; Get Y aspect + mov [mx_AspectY], ax + lodsw ; Get screen width + mov [mx_ScreenWidth], ax + shr ax, 1 + shr ax, 1 ; Divide by four to get bytes per line + mov [mx_BytesPerLine], ax + lodsw ; Get screen height + mov [mx_ScreenHeight], ax + +; Set CRTC registers + mov bx, si + mov dx, CRTC +@@TableLoop: + mov si, ds:[bx] ; DS:SI -> table of CRTC registers + inc bx + inc bx ; DS:BX -> offset of next table + test si, si ; Last table? + jz @@EndLoop ; Yes, exit loop +@@Loop: + lodsw ; Get CRTC register index and value + test ax, ax ; End of table? + jz @@TableLoop ; Yes, go to next table + out dx, ax ; Set register AL to value AH + jmp @@Loop ; Get next register/value +@@EndLoop: + +; Set virtual screen and system clip region + push [mx_ScreenWidth] + push WORD PTR ds:[bx] + call mxSetSysClipRegion + +; Clear video memory + mov dx, TS + mov ax, 0F02h + out dx, ax ; Enable all planes + mov es, [mx_VideoSegment] + xor di, di + mov cx, 8000h + xor ax, ax + rep stosw + +@@Done: +; Lock CRTC registers 0-7 (some cards need this) + mov dx, CRTC + mov al, 11h + out dx, al ; Vertical sync end register + inc dx + in al, dx + or al, 80h ; Set write protect bit + out dx, al + +@@Exit: + xor ax, ax + mov ax, [mx_ScreenWidth] + .pop ds, si, es, di + .leave ARG_SIZE +mxSetMode ENDP + +;----------------------------------------------------------- +; +; Changes from the current mode the selected graphics mode. +; +; Input: +; Mode = mode to select (MX_???x???) +; Output: +; none +; Notes: +; this function assumes that mxSetMode and mxSetVirtualScreen +; have been called first. View size is rearranged to match the +; specified mode, but video memory is not cleared. +; Differences from mxSetMode: +; - video BIOS is not called to initialize graphics; +; - row address register is not modified; +; - video memory is not cleared; +; - mx_BytesPerLine is not modified; +; - system clip region is not modified. +; +mxChangeMode PROC FAR + ARG Mode:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si, es, di + +; Set DS to code segment alias + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov si, [Mode] + cmp si, MAXVMODE ; Is it a valid mode? + ja @@Exit ; No, exit + test si, si ; Text mode? + jz @@Exit ; Yes, exit + + dec si ; Skip text mode + shl si, 1 + mov si, TBL_Mode[si] + cld + + mov dx, TS + mov ax, 0604h + out dx, ax ; Disable chain-4 mode + mov ax, 0100h + out dx, ax ; Reset + mov dx, MISC + lodsb + out dx, al ; New timing/size + mov dx, TS + mov ax, 0300h + out dx, ax ; Restart sequencer + +; Unlock CRTC registers 0-7 + mov dx, CRTC + mov al, 11h + out dx, al ; Vertical sync end register + inc dx + in al, dx + and al, 7Fh ; Clear write protect bit + out dx, al + + lodsw ; Get X aspect + mov [mx_AspectX], ax + lodsw ; Get Y aspect + mov [mx_AspectY], ax + lodsw ; Get screen width + mov [mx_ScreenWidth], ax + lodsw ; Get screen height + mov [mx_ScreenHeight], ax + +; Set CRTC registers + mov bx, si + mov dx, CRTC +@@TableLoop: + mov si, ds:[bx] ; DS:SI -> table of CRTC registers + inc bx + inc bx ; DS:BX -> offset of next table + test si, si ; Last table? + jz @@EndLoop ; Yes, exit loop +@@Loop: + lodsw ; Get CRTC register index and value + test ax, ax ; End of table? + jz @@TableLoop ; Yes, go to next table + cmp al, 13h ; Row address register? + je @@Loop ; Yes, ignore it + out dx, ax ; Set register AL to value AH + jmp @@Loop ; Get next register/value +@@EndLoop: + +; Lock CRTC registers 0-7 (some cards need this) + mov dx, CRTC + mov al, 11h + out dx, al ; Vertical sync end register + inc dx + in al, dx + or al, 80h ; Set write protect bit + out dx, al + +@@Exit: + xor ax, ax + mov ax, [mx_ScreenWidth] + .pop ds, si, es, di + .leave ARG_SIZE +mxChangeMode ENDP + +;----------------------------------------------------------- +; +; Returns the aspect ratio for the current mode. +; +; Input: +; AspectX = pointer to aspect X +; AspectY = pointer to aspect Y +; +; A rectangle of width AspectX and height AspectY looks like a square. +; +mxGetAspect PROC FAR + ARG AspectY:DWORD, \ + AspectX:DWORD = ARG_SIZE + .enter 0 + .push ds, si + ASSUME ds:NOTHING + + lds si, [AspectX] + mov ax, [mx_AspectX] + mov ds:[si], ax + lds si, [AspectY] + mov ax, [mx_AspectY] + mov ds:[si], ax + + .pop ds, si + .leave ARG_SIZE +mxGetAspect ENDP + +;----------------------------------------------------------- +; +; Returns the current screen size. +; +; Input: +; Width = pointer to screen width +; Height = pointer to screen height +; +mxGetScreenSize PROC FAR + ARG SizeY:DWORD, \ + SizeX:DWORD = ARG_SIZE + .enter 0 + .push ds, si + ASSUME ds:NOTHING + + lds si, [SizeX] + mov ax, [mx_ScreenWidth] + mov ds:[si], ax + lds si, [SizeY] + mov ax, [mx_ScreenHeight] + mov ds:[si], ax + + .pop ds, si + .leave ARG_SIZE +mxGetScreenSize ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxsp.asm b/16/x_/mxsp.asm new file mode 100755 index 00000000..1d08e711 --- /dev/null +++ b/16/x_/mxsp.asm @@ -0,0 +1,57 @@ +;----------------------------------------------------------- +; +; MXSP.ASM - Set palette function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxSetPalette + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Updates the VGA palette. +; +; Input: +; Buffer = pointer to palette data (R,G,B) +; Start = index of first color to set +; Count = number of color to set +; Output: +; none +; +mxSetPalette PROC FAR + ARG Count:WORD, \ + Start:WORD, \ + Buffer:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si + + lds si, [Buffer] + mov cx, [Count] + mov ax, [Start] + mov dx, 3C8h ; PEL write address register + out dx, al + inc dx + cld + cli ; Disable interrupts +@@Loop: + lodsb + out dx, al ; Red + lodsb + out dx, al ; Green + lodsb + out dx, al ; Blue + loop @@Loop ; Loop until done + sti ; Enable interrupts + + .pop ds, si + .leave ARG_SIZE +mxSetPalette ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxss.asm b/16/x_/mxss.asm new file mode 100755 index 00000000..97df7366 --- /dev/null +++ b/16/x_/mxss.asm @@ -0,0 +1,72 @@ +;----------------------------------------------------------- +; +; MXSS.ASM - Split screen function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxSplitScreen + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Splits the screen. +; +; Input: +; Line = scan line at which screen has to be splitted +; Output: +; none +; +mxSplitScreen PROC FAR + ARG Line:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + +; Modify the line compare value: bits 0-7 are in the Line Compare +; register (CRTC #18), bit 8 is in the Overflow Low register (CRTC #7) +; and bit 9 is in the Maximum Row Address register (CRTC #9) + mov ax, [Line] + shl ax, 1 ; Adjust line for mode "X" + mov bh, ah + mov bl, ah + and bx, 0201h + mov cl, 4 + shl bx, cl + shl bh, 1 + mov dx, CRTC +; Write bits 0-7 to line compare register + mov ah, al + mov al, 18h + out dx, ax +; Write bit 8 to overflow register + mov al, 07h + out dx, al + inc dx + in al, dx + dec dx + mov ah, al + and ah, 11101111b + or ah, bl + mov al, 07h + out dx, ax +; Write bit 9 to maximum row address register + mov al, 09h + out dx, al + inc dx + in al, dx + dec dx + mov ah, al + and ah, 10111111b + or ah, bh + mov al, 09h + out dx, ax + + .leave ARG_SIZE +mxSplitScreen ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxtl.asm b/16/x_/mxtl.asm new file mode 100755 index 00000000..69900c88 --- /dev/null +++ b/16/x_/mxtl.asm @@ -0,0 +1,169 @@ +;----------------------------------------------------------- +; +; MXTL.ASM - Put tile +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxPutTile +PUBLIC mxTransPutTile + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_VideoSegment : WORD +EXTRN mx_BytesPerLine : WORD + +;----------------------------------------------------------- +; +; Copies a "mode-x" tile from memory to screen. +; +; Input: +; Image = pointer to tile +; X, Y = coordinates of destination +; Width = width of image in pixels (Width and 3 = 0) +; Height = height of image in pixels +; Output: +; none +; Note: +; no clipping is performed on tiles! +; +mxPutTile PROC FAR + ARG Height:WORD, \ + Width:WORD, \ + Y:WORD, \ + X:WORD, \ + Image:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si, es, di + + mov ax, [Y] ; Get pixel address + mul [mx_BytesPerLine] + mov di, [X] + .shr di, 2 + add di, ax + mov es, [mx_VideoSegment] + + lds si, [Image] ; Get tile address + .shr [Width], 2 ; Number of bytes per plane + mov cl, BYTE PTR [X] + and cl, 3 + mov ah, 11h ; AH = plane mask + shl ah, cl ; Align mask to first plane + + mov [Y], 4 ; Number of planes + mov bx, [mx_BytesPerLine] + sub bx, [Width] ; Extra bytes per line +@@Loop: + mov al, 02h + mov dx, TS + out dx, ax ; Set write plane + mov [X], di ; Save video offset + mov dx, [Height] +@@Loop2: + mov cx, [Width] ; Number of bytes to move + + shr cx, 1 ; Move line + rep movsw + rcl cx, 1 + rep movsb + + add di, bx ; Move video offset to next line + dec dx ; Done all lines? + jnz @@Loop2 ; No, continue + mov di, [X] ; Restore video offset + rol ah, 1 ; Next plane + adc di, 0 ; Bump video offset if needed + dec [Y] ; Any plane left? + jnz @@Loop ; Yes, keep looping + + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxPutTile ENDP + +;----------------------------------------------------------- +; +; Copies a "mode-x" tile from memory to screen. +; Skips over color 0. +; +; Input: +; Image = pointer to tile +; X, Y = coordinates of destination +; Width = width of image in pixels (Width and 3 = 0) +; Height = height of image in pixels +; Output: +; none +; Note: +; no clipping is performed on tiles! +; +mxTransPutTile PROC FAR + ARG Height:WORD, \ + Width:WORD, \ + Y:WORD, \ + X:WORD, \ + Image:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si, es, di + + mov ax, [Y] ; Get pixel address + mul [mx_BytesPerLine] + mov di, [X] + .shr di, 2 + add di, ax + mov es, [mx_VideoSegment] + + lds si, [Image] ; Get tile address + .shr [Width], 2 ; Number of bytes per plane + mov cl, BYTE PTR [X] + and cl, 3 + mov ah, 11h ; AH = plane mask + shl ah, cl ; Align mask to first plane + + mov [Y], 4 ; Number of planes + mov bx, [mx_BytesPerLine] + sub bx, [Width] ; Extra bytes per line +@@Loop: + mov al, 02h + mov dx, TS + out dx, ax ; Set write plane + mov [X], di ; Save video offset + mov dx, [Height] +@@Loop2: + mov cx, [Width] ; Number of bytes to move + +; Move one line + jcxz @@MoveLineDone +@@MoveLineLoop: + mov al, ds:[si] + test al, al + jz @@MoveLineNext + mov es:[di], al +@@MoveLineNext: + inc si + inc di + dec cx + jnz @@MoveLineLoop +@@MoveLineDone: + + add di, bx ; Move video offset to next line + dec dx ; Done all lines? + jnz @@Loop2 ; No, continue + mov di, [X] ; Restore video offset + rol ah, 1 ; Next plane + adc di, 0 ; Bump video offset if needed + dec [Y] ; Any plane left? + jnz @@Loop ; Yes, keep looping + + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxTransPutTile ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxvs.asm b/16/x_/mxvs.asm new file mode 100755 index 00000000..992eabab --- /dev/null +++ b/16/x_/mxvs.asm @@ -0,0 +1,110 @@ +;----------------------------------------------------------- +; +; MXVS.ASM - Set/get virtual screen +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxSetVirtualScreen +PUBLIC mxGetVirtualScreen + +EXTRN mxRowAddress : FAR +EXTRN mxSetSysClipRegion : FAR + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD +EXTRN mx_CodeSegment : WORD + +mx_VirtualWidth DW ? ; Virtual screen size +mx_VirtualHeight DW ? + +;----------------------------------------------------------- +; +; Sets the virtual screen. +; +; Input: +; Width = virtual screen width +; Height = virtual screen height +; Output: +; 0 on success, else invalid parameters +; +mxSetVirtualScreen PROC FAR + ARG Height:WORD, \ + Width:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds + +; Set DS to code segment + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, 1 ; Assume an error + cmp [Width], 320 ; Check width + jb @@Exit + push ax ; Save return code + mov dx, 0004h + xor ax, ax ; DX:AX = 256K + div [Width] ; Max height in AX + cmp [Height], ax + pop ax ; Restore return code + ja @@Exit ; Exit if bad heigth + + mov ax, [Width] + and ax, 0FFF8h ; Align to byte + mov [mx_VirtualWidth], ax + shr ax, 1 + shr ax, 1 + mov [mx_BytesPerLine], ax + shr ax, 1 + push ax + call mxRowAddress ; Set row address + mov ax, [Height] + mov [mx_VirtualHeight], ax + + push [Width] + push [Height] + call mxSetSysClipRegion + xor ax, ax + +@@Exit: + .pop ds + .leave ARG_SIZE +mxSetVirtualScreen ENDP + +;----------------------------------------------------------- +; +; Returns the current virtual screen size. +; +; Input: +; Width = pointer to virtual screen width +; Height = pointer to virtual screen height +; Output: +; none +; +mxGetVirtualScreen PROC FAR + ARG Height:DWORD, \ + Width:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si + + mov ax, [mx_VirtualWidth] + lds si, [Width] + mov ds:[si], ax + mov ax, [mx_VirtualHeight] + lds si, [Height] + mov ds:[si], ax + + xor ax, ax + .pop ds, si + .leave ARG_SIZE +mxGetVirtualScreen ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxwd.asm b/16/x_/mxwd.asm new file mode 100755 index 00000000..de55208f --- /dev/null +++ b/16/x_/mxwd.asm @@ -0,0 +1,28 @@ +;----------------------------------------------------------- +; +; MXWD.ASM - Wait display function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxWaitDisplay + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Waits for display start. +; +mxWaitDisplay PROC FAR + mov dx, STATUS +@@1: in al, dx + test al, 08h + jnz @@1 + ret +mxWaitDisplay ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxwm.asm b/16/x_/mxwm.asm new file mode 100755 index 00000000..06158859 --- /dev/null +++ b/16/x_/mxwm.asm @@ -0,0 +1,39 @@ +;----------------------------------------------------------- +; +; MXWM.ASM - Set write mode function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxWriteMode + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Sets the write mode. +; +; Input: +; Mode = write mode (0,1,2,3) +; Output: +; none +; +mxWriteMode PROC FAR + ARG Mode:BYTE:2 = ARG_SIZE + .enter 0 + + mov dx, GDC + mov ah, [Mode] + and ah, 00000011b + or ah, 01000000b + mov al, 05h + out dx, ax + + .leave ARG_SIZE +mxWriteMode ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxwp.asm b/16/x_/mxwp.asm new file mode 100755 index 00000000..19ca99d0 --- /dev/null +++ b/16/x_/mxwp.asm @@ -0,0 +1,62 @@ +;----------------------------------------------------------- +; +; MXWP.ASM - Set write/read plane functions +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxWritePlane +PUBLIC mxReadPlane + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Sets the write plane(s). +; +; Input: +; Plane = write plane(s) to set (bit 0 enables plane 0, +; bit 1 enables plane 1 and so on, different planes +; may be selected at the same time) +; Output: +; none +; +mxWritePlane PROC FAR + ARG Plane:BYTE:2 = ARG_SIZE + .enter 0 + + mov ah, [Plane] + and ah, 00001111b ; Mask off unused bits + mov al, 02h + mov dx, TS + out dx, ax + + .leave ARG_SIZE +mxWritePlane ENDP + +;----------------------------------------------------------- +; +; Sets the read plane. +; +; Input: +; Plane = read plane to set (0,1,2,3) +; Output: +; none +; +mxReadPlane PROC FAR + ARG Plane:BYTE:2 = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + mov al, 04h + mov ah, [Plane] + and ah, 0000011b ; Mask off unused bits + mov dx, GDC + out dx, ax + .leave ARG_SIZE +mxReadPlane ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/mxwr.asm b/16/x_/mxwr.asm new file mode 100755 index 00000000..bd29fe59 --- /dev/null +++ b/16/x_/mxwr.asm @@ -0,0 +1,28 @@ +;----------------------------------------------------------- +; +; MXWR.ASM - Wait vertical retrace function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxWaitRetrace + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Waits for vertical retrace start. +; +mxWaitRetrace PROC FAR + mov dx, STATUS +@@1: in al,dx + test al, 08h + jz @@1 + ret +mxWaitRetrace ENDP + +MX_TEXT ENDS +END diff --git a/16/x_/readme.txt b/16/x_/readme.txt new file mode 100755 index 00000000..306e8b9a --- /dev/null +++ b/16/x_/readme.txt @@ -0,0 +1,8 @@ +ModeX - A graphical library for DOS programs +Copyright (c) 1993-1994 Alessandro Scotti +http://www.ascotti.org/ + +Please look at the above site in the "Art of..." and +then in the "Old programs" section for more information. + + diff --git a/16/xlib/demo1.exe b/16/xlib/demo1.exe deleted file mode 100755 index 7d8a4d659e0835ffa358044fb656c4e062d660f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41502 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 wC_BXtflb(bmO#+32g5e%7(GF6nx!}w=4(U~?4 z6Guo6bVQ%gk>AX3xaiDS)L+puhB9i}K+DBS(<+wM;nE_UaG;a|O)nwm{qA#;QXHLk z=JUMI``1(5Ip^&AUTf{O*IIk+%|nkrNggCmk{mLQh~n+TyhQ$+gNK3)IDTB1jQGZf z0mFDj8Hh5!4 z{02AKr6kQAzOc#H(d9QkPu4eC&wPBVro7(5&8af15s9)$^D$9c{P^0TYCfN9J72^^ z`xM+Urqyruqpb~O%dd#Fr94#iKz_r-mCdL7%bU2<13^?0l8R-AvdY%JKPQ$twIchR)b>ZeHh#Rx z$nPZL%p!zeAp8vBrwGrGO|!s`94{I8KM#{KJM%xgYOt{@by%8_sr-eo4$vq@IDd83j)BL*2lA@?f{7+dH+px+@`y=9K+ zp;KLz6HaYDHDPIk@{l8V`>;*ZREN}s?9wwd<13VwTKG`f(nDrvesBSqxy?Y*LU@?S zmZx+xw`s}dCv`Kos>%BO)AyAh3EnYdmyUe=J0*~G!}^6vU%e`){bJBfv61`^DpMbR zb5yyW6_ipNyG5}a6Ub7|-b$<@W=tiab7s8do;26>mNm2Qy3^fd;T}_Z`)9jP&-b1> z=1nYfE9S2((6za~|L8K?C+;b_wlcP1_!OmUaa%{$5q7`w$nmTe^M2)j9XtNtl}gvF zL`b-+t)rfG=mORw{`Y(6^Tj>Ce_z{kk*V1}JyfAySpbaJnh21R z#Ei+A56UB6(4dyEdpxF~SjH8oEZne(c?ruzMMS`V9a-XETG`|5DfTSeFzZN~FuGyZ zKhlKZmdOh>vjKmV#XGgDVOHC1*=>;%k!Ik<;=iF`##aq@d-@w@bM}7k$y{$d2Vjn; zx%A$+!le|ZRVT`XsnuecFrivODyMOI2HpNLCU)drU*Ao|%&wbAe2<5{Sb=Ug+}#pg zsA!lGYPi$WMeFOmO`Kb8dMI}0m8ypV_E_Wbo|8=2*F<71_>mA;#>QHh+LAYCk02f< zID&93)>_w1Tvw?w)-roR2I3ZEQ1<9mF4gsvsT=O;W9o#X4fpJS)mkSUUV@ZW%B2l= z9Fa%RV;@-P8aZ#iZ(zh~*5@%0&utC&6vr0{7A|}rt>*4)GvDh@e_)Z6FRkI8y!d=w zTglXh8Sw^NaTmtK4CGG_U8&em+_g(Z8fNR-+{T%KTfLVRu1O6uI#))|CuRmz_Q3I` zvr~*|)23Bu`9&@br~*&-S5J7qGP;M)qm`Gbu%JwvZ>d|TxLt;xDt3f9kOChP2^Y57 zS?j)Hjip{ajm&TF1x!sqF9+NX8>Z%JhY$o<)_P~cUl8ANk4eYQGP$144rMnv76&!N zA)4xV#$&ff3(&OepgQxLas>S~t6&TuW_2T$sx z3JQ9cEfcbZ+lQo9KdJN8Dw$g3TCEiCGzY)ZIn2So=_!o+&AvT)JV*C|hACU2d|>w9 z&z7=)TJ$|a(W+^f!ItQwZxT#lMDx-A!W+f;M`|*;D{?Aws$s?pL?7Yh|BBKY?l4Ty zyOqL^B0N6sGE6~Qk*49!tXuUUhUELqA@4au-X9q9{^*eRf+6oe9P(aB-+Sz7UKiS( zL-YkJYL#>b}3T#rQBl#?sg=z83f1e0j+ z>Qjx0e|pu7tH~^Sgb;dt7jPo!_vWI zha3(%pg+h10xNeQipB&GgV$sX|10qzeWj`V&%}eyS6}{3$fb;Rbfj&JonmTUjdd`G z3us5HZfTgfr+~%iEdG3@G_tB&uZ?=bu*BPEDl%~`&BvSDdyaT(OwEF>`JgvydO17P z+ zWbZ@v)6?6m%|i>w@Kot~N=Eq-OFhg-`NTgn&k%UQVfa1QC8WoW`V!O1qV;T^K@|Nn z%SccZQ|JdGR8IcyB3GA+36cd|0nqyLR4px~=qfyOs5W%Y9JfU+&Mb_87T2-#44w8ON~+7!FEF?Mn0x{>w{t)x3aRk8hA2=hQ$cPzq@d{>#Mc(oj&X&aQWB))(mO?b=&SsE@O=I=jZL zUf&w5FbFIPA!adX2Gpemb=|J^?a?fD@T*00@Lj{z_~&jyyxh|jwOZOs-&rM!prbMi z+JlA6H&?`bQWAjywb2NL8obEC7m0qS)^FEjZm=g%B`t)e{u)P>x{zxZ=hV`9ht*O; zzL_+`j|6z=T@uX%I+}%L%)!8yARb?b(H3zlZDGozB(TKRPB18miw&j`hcMDyHCFict8g;_M`LHiOwvbQgCd(ov5xgm5+0BPFI;xAtYdnEXmB*E|Y26(Re^sbH*| z|16jFrpmrCSoRIMEI>H4>{hAlW3((CsJZIiBqvI;nX~Z~2LpAyk_2i$Grf2mFE1Wf zy>#QqoEs}>{xxS`B~n+`lqBb6r|)BJZp_d&wh< z*$prLShV(L(uX5oCJoU^MKy@eXB2WJ3Qy;TkA5twA7A!Fn2pm{zbDRl;(Ll&3zgSK z%$n*No~*U(9RC+l;GdEF3*CXjV`mm#5xV!gdb6a}T_?dd1E zMy|yxOz;joS(Fj@(}xD%!02Ko`Vu3_M;~NFUu3*j$m(8SUP2)pqOa%hsucFn*LJVx zvem_`b6ysze5(@21c>8_2|Lq-KhxBQV)lfRxNkg#qY*J4Qy zl|&-PxyH!x$Z@7tVegGjm&*RvT6+&Dedo}$o@l0sHcZhUh->l^M1h{3k1i8G&bQZRj>t+V$l5GzN#o}240W-%xeaiz`VM&Z+=+Ths@ zbdAt8xeY!~4{_^f)};}yUKoiMRf`>&`GNZ1I|BB8#}ZyQkO>ylqiZTSs8Ia`;xf(TMoXWWYQFqRc{!tT%mQNO9Uer*pOFk?OS^Y z71|36Bs2dJ=r6mMECv&r42Hwm6K@fPYZwF} zRHYTv_|*hi;^1FSm->QsHN-WBbN1?*Jj3}@af^5MZEnT=)`*AkJG<$ZOBb+T233!I z*s?Co=jkR`9^?kayl%cK&c#6bTtP3`4w{^uM%)>JRRiAm&)n%WcNr#5Hx#Y0-uQE_ zG;e&VdpHo0vuKg;*=}ViO(cZL>qbXFnRd7Hm8e*dDi2RhWqe`~zG53eJvM=Wor<{`t6 zkGFT}+C0O!gJ@$IvP2(>13@4q8Tz_G=nLv3?1K(+i~THP@3i>SkO^d_&ds&drx6l0 z#JS?Ga`0|XymBgEJwRu^JLdJAb(AuE)qvXPIRm1^`YSM;y;EM|^d!S{#dx1dV=6ZJ zOf{x`rUujPrXJI0rWVteCg*Tw#Gi-P4bRQ+N&ihY-E0C2+kBG|wi~DFf!Gi?-i<} zx>Xn76l~S4%=*y!He1*=y#H+DzQO_g6b-yN(0)M}KP2Lv0j}k0G8f)H(0(F5ULKCL z7CHyl&)-g5wv6k_NiLl7G7i3fVT^ANU7@kqG7vo^@$;;PiiLId0mAPvNPXttGVIVa z^YlF){SqsvR@xY^_stlECevU#Y-aG+Aw%HSmMOg1_y6%KxwUd)Sgb$MWjO!RtjNJGCM=vWnz6lX0-j8u=BI%)#K)KQtE zKm@_+k;&y$hU*5q*1?*wBoJ10Rgv&x=0|qHQhH>WHx847H*Rz-YcL7Fn5D#&f)UCQB-b~XW?hd-YgtPY zRf=6|w!ySiXq%Pe{^EU8)rba@cfjPjH#lPW^tJ|5kc@bL0)5DZZt)t{5(Nqo6cWav zBDvZT4*oe&8(NA6=e$71xRjMS<5z^MjQr0<2S1W5tI`1K-xs|n%hp+@8rK0~bQy>F zb*sgQTn~urEH@eNVJ$}2$jyi${9PiVvqdD+6z?31ktxogkDMYseW(ZJk*zmN$vG}n z<#mEiG7?)hzd#b9tv5;uYS)Ay>8d^>Iu@IQw;LV&)&yur&+ns;lu)zv7CA2>NF{_l z65Mv1v7WUW38^GoCmOd-Fk-^0#I2Kzn{TAg$;K7o>br~rQ$5=V(JN_1-E||Wo@cDe zX_y#&_e}T?{gvd@e7;9KnGs;g5@NDTv!p&;A6B)U!V}zNHda zyD#zml9Q6+;yVkuez(YVWj8_M%iix;%w_(>xaG%2{_V?8EMxX%wE7DY{=B#_&UUmY z6C6OXT2naL=ZTZT8+^~kiLW4`;4bpdi(E@~lg*hZY;mXA?D4_~CB}m=@D2WD*)o4L z#&u_TYq?oTd~>il=2B;^H$O8*xNCh&mW@T?s4W_jwe6WPW~y&(rDo!vjS(hiaVVHo zj|_z1@r?ZVDSglki)rTBD&HPexV+U|4x?c`0)g2al}T-8S)}INmMw%l!CDk75^I>o z^4es)+Tu58hydLbBCx>lj}Z0xkcB}uYI39$FBpIVGQMkM zwTW08>HZ1II~MaxX~I%Rc3a>}=mbLZaVcSmgP%(io|r9)t})ma0<8ULq#PSGg!nU+ z*rFg|*kQxpP%>?>PheM?SxOSTAk=fIjiVuJCIm|%y*e;41RDtobMeJG8XXh!;I5t^ko4gA0r z3N8x7EE^_^Yautl^p@9i7pz?t|4dLNg%<0e^ax$7nTe#x8k;zN5U-GihlX$$4SXf7 ziaRVJM9$B&ETOYUB&jweFbk{%W2#+4mrsHiMDdF;S=)-nV6);L3VPSvB+PRpnBS9v zIcnyh7TWd|8dj^hX0#?ukYI^0Qn$*(K1$d)^45o zE8?r0yMt}+w9S0h=pF&wLypU>TsL=2okc_oH#}6TD9QH%RVne=@UwxU{NfP|4N(fGo;|jaMZY$P%s9Yh5g0fKe z&$Vv-rdmq5P+ObEj`!~9$%>Uc{C7WxmtmxHjOi9R~$@@ z7c`YtrE8e@d$~g@46_&#It)B49cVs39365^mfAJZfl`VzFpZ13dTSl$G~tc!R3ss> zggfl_B(P(lAhu#tsh0b~Urawmk?R+3Mjb;6IWJKFvHAQ%c#$j4aqv$o7^p_}1Y?ie z>fH@Pp#_PPP1-1_^_%A}tvD!Jo-;~x2zaO>Jhx90{b7X3Zh9hiG0;*)0+}}%{{~A< zAaYCNI;R-u2-rnxJd(&C!k>j3O=UjYXjl3Nq)N$;?V+Fk(TUo7P_j^!sCy5hwFWU% z9F*G9Q&Ldzw=j^3L6)3dZ)0yW4$3>w`~filkQ&MOCq>W&3|3#uatT?!Ckv+hY-EWG zkNG^8pjTp)aVlK*JNOkMdZgj~mqE6$BC{6mPM@7sQWf2G1F|HN`DVaC8Tb;SHnI=n zAHPg9V_8RLt&*#M7`S-@+Nw0V*_VgtA>b@2asN75+{bnv?X=vl#e7RQOwiZFBoaw` z9zal_l_-UkwXJ=S-Jo@(DXdlXW)-Ar_v z!s}5f5Ot#>Vb>?@+Js$`u(Mu|fkos-XbRdY0uzQ_`emhGjr5E7oMZx6LO-mGdYH1F z6cHz98(M_EBiFfsA-UvqS{ZK>uPrLKaJ3o~)zAi_o8%6q8kU;64=oOM>1vODIJ8GY z2XXZs)jshpJ$fsV>XDp1*+BFeF)#;8+A0Iogut`fK%PEO%m$nqe%wVmIrNm!s~*5Q zSZ;^4yHH|_EX0^feyPL{!CHd~x z{?xn`2TwjVC4TCugH;T4lu$QU8|E*HbW%>hq_o!N9OO@mvJxA}oS2M4(@@9tRr7(g zq~(&?NZD34FSqSvZJDsD4wI}hW?mT1wWiFnivbIUER*t8%|S2Gd3`ET-eoy=T1tfq zfW_6uq9T@7Bs_uKkq&ARP8nn$Oj-L2=k(Ni-7|uUdD;892&&A&PMb3Mfw_x??D1uV z*9FNuq>Z5Zz_8VlKA;pnkQ;sOG*t{RGUrF&g|bzhfwfDT)wv^Vc1or%OP{_n$kyM1 zb)1wMF%jvGr-v+~cH<(NJC>_d5tq>-uGS(@%lM&7%a+j;Z<&gez|SRDCE1!kOTe^1 zK=VV?)+R*@(ArCmYXpaF4ur5?W+YWG#FnQvD}@ncRw$6igsjZy8F9Q z;&Mc4EnGerZmt2lN_yb|;XYb`%VjN$I*04B+zOcs)UcnxcBsZy=gOdk&=I0^ zYb?Hpm8R%Yk;*-T%N)egnP$WK0=hnx>xHp&vlIClLRoi$f?X{xTbApy$45%$2lr8~ zesJY>=4Xq03iP5~ZwVL!HM0uc8tj#SgvHeC?OW|mt5!0C#@qLlTUV_d_OX|I1d)`A z3co}llt4LepOyAe4{L+fJ<;3eg3+MwyYA75ce8RXUwhnlK=rX#@exCi0s96ANRDs= z%|>6nf^o}zhN&c^YvgL*B3>8c`!uJXU8koi?~D4zJLP3dTF&Njb(G6W^BR;dGx*dJ z5_j-cj0WJ&rEC2y5+#-12|)`Bu?{XB@)`h$yu|{zH0Qcpl{Qp5lDKt3l25F}Tdoz#Q8VipO=3u4nLYSeFChC&qSrz{d zwx6h6s;hO&S;ojhrwlV06jXhvN+hRr@E5lOLh=qAT|GD04Gwtu=1-Q73YyLojbH=TWi?f@S#$v+VT(RCR zWJong=1~673BOb0x3hU%9eO@eE)ED#Lg6=1wE+6E-U@0@VuzY~=-?SryjH!Kz-BtD;UQv=>zGb3KV!B2S&6 zjsAq@qSQ$<6QXTej>fGjF5#p;JDIcdYpgzXMzl(_l57W!Ef1L)MpD z>6SOm=2z=No?#Z>)5>FDdpFZ4I$upv(`AYD2{2ORDur~KAT7Ie5yDD2sCuv#QB84< zg$C>UiliQzT4<$3^+*aAp6e+LMI$P|c6ugPVzgZHGs;Iy3is3W375E)5(z!5^b(n| zNYVtagA(t0PuL>7OOs_r%58@|{z{e|UI2>JZ+1a{(pvhj3~uIr?(Wzf9Ibqgi@mnf#ilJ6i3 z1NKBr)X2jfUehl2>KYfz<*5V%`@Q0ENF2u^9sbuQ08&FZt+G-9*OFKbwk5Td%2|oHK>rE_hpiCQ|Uzn&1#oG zJ(48aGzt%SS*6CA923m~FOt$nF_VVQj6h}%Y>Jk3Bg?TN2I7M-%0wSkc<1Dpv@R`u zq+`{ZuaH$;jQ)npl7P)bzoVeCY?dNwQP9d!_9X)O5l=cMsXb7<&`RH^M5BIfNVGtV2EY|GUuVo?hcae4 zl?wA$+JIN7X7`P>lr$CH<0$gY!9t^Bkb}GERL8t_kC)SOC?~jD&tu7C7X%Th7Rc31 z^ju*CFNdj9MiktBs4Sp?RfzII2^X#`VG^>zy=ZXD^7jq{ebu4~{U zr&9R*qZPwWN>Hg%H2w!^h=&D=niirz6{ELE-Qd(reTjuO>DGf#ELJEbezgEGgboMA zKI@j2cbF!`A(e`&4Omqq7fI;pAR{VyF!huy6lMD8r@-gG+uz&1rN29|6(sl9OQJCA z|B6;A$&-tPT>37mODBLD2Um|2>_Vus%pgVWK}w$S8SF7(Zla zDOutq_BYTzrd1B+c4CN?N#?>yRa-0R>_2XaR>B)tpEFxY3e&IAyMg=Pf$*Hsp9j&Q#xmOj5tr{Fd4Sp0EzQHpu5FK^wSYa38wp zQQh6G^NGqbc1=PogBLv*$OUZm6=Q42xW>b7g-cyMTWo}GIMO%Ah1hh&mh0VYJ?lcO zv?_voWYUhx`Z$#e(A8QjO_JRY)8=bBf7?k}M~C!rQC96Cfy=r!qz)MWt}4*zn(Ikj zPx114_612b{Ix#)F0fx6eElXm(ah^#E%Q4e>1v_zFwwcvVvcoPB{1+uLhpbm_}rmd zNguyjJshq@g*%PP0PyNdF3{9TAt{_nRJU4b5${AJ=H4XXEACvvTFP^k>qF`%EZlfd zAN7W&4wjPgK%s$%;CE+G<0cEF4XRY%JtFb`Z_Yu*|9j;O&iuF;as>Cq^bma3y5D6t zxJ7t&Nbj+TwT~UIUK@+mVLep7aepK#i5V}iuZ4$(RDV9oW{04uxmBQNZCon1G1hqB zN-25G*>bqYVJpCf16ep#MLmNyeU61ANzX-TAmNEP>y@-6X_5ePfWcXCi+TNf3NDHEOOm@s-z+U%o8kam zIy4cy1?+v6b!xnCc(G7~LY3WSZS=Jfc)Krv>7d_B3TH_v#qsPWYnQK;I5Q==;b*jU z*l_DyBP1~%v@AS=My+UcAuU1u(4knvwH!13Iq}*`s7h8m#R-dJAv^&wmT z2Wnz!;l>a59{u2S8l3(>i0p_t(Oi{-Sl9rQj+jQr)wu|F3P=ezeI_A;@|NtLl;m%N zJ*Q|Q1q3Dx>^LdOf9+XW^0(6rg~x_!h96Qn3USI6k^x^dcQoKL2!np0PMsa2Z0-jX!({EZt5|lmD+|_FAMZ9jUjr68n zH?*9*6$Yz=J&`m!OiP&^XcZ6zHWAW-THqPm4`m5W%ITXXjw2Mz!l#1}^_^v%=HP%5 zD}1NYv1!6hQU+Pk%MMkmOpe8a-Q8;3w%M57Bitm{MtKkon0o_`O+UDqmelVtZ#FVV z;cNq%vad;~OeIapwtqc^4tkS;{6;0t+=?M@Hg0+!AIp|en&0#QeZ2~{IXH;+LxoiT zrsv6J*b>aa|AqD*M=&FdBn|`rM~DGhzjL48US|%TXE6q3*`&h>V+_)t`Df#{H;h}} zFzVPp8{O9hdB(Bn{>kV>@cYQ6fz!dVO>TS}_@0D0m{5YDI)VnuSCjv5`UTD``}P>j z!RgG9M0)H2c~Yrj@jkJ*j+PyPeyvB?Qzt(_QF*>>?AepQ<8{Wbe;zTH*-)eDo97B%P&29|`20 z+ewx<7E8HM`r15azODGu$E}gEVZXi6@BGvpJUtX@Nth(D`0oI%H8q}p0@|NJuy5dC z#y^vFAvEcI4ZDcKF*y9k73y1lm9T1<+c*t#}G(pZT3l=HO`6 z5bFNVf!3ZHj|{X2Kxs2TX^`8K6XT!gEIC20rL)Fs>FmQ4omGO)j;5Lj*pJH~JMnEG zJNj*74%km7LH59n`PeO2 zxv)9-%dclO4b2LMSn>4?*YZSZu5I$BU1sEkhE#vXRAzL}<7#Z|5w=vxg==`GlWJVs zF0k8%sjci6Y|U}ywit^PJTJ1`KFAaFq|3I;?6x#yXk)kav0TlT3vA4S_w($*{OUcp zF~fL1NH&*;tRg&a&;C{88o-Zxz)Hori`!SqwxalY9H0OAGcd_rk1!W2;8f!4OZVvO z*uyM6!b62Qzu_~Mek-Pje0@wAtP@*r);6#dx?$_@5Sx!Y&*hk>tMN-8eX~W z3-+CDZ4hDLc5)cnkR+`H@>uT)3{TN?5*3^eoTyY)f6APf(jdn8<{ZNrE*$JXid_Ir z9s3VffpQcCmD8$23_78o@IdD_oqAikdYe&Q#~x)Nbh6K*p9JlC4L55cl|_!<$F<0C zb5ppv2Kq6EKu6`6^MTXelZwzuRi&B^=)87M=L0lK8Ty2&97dx)M$`bP$jWxG+rDBs zGZ53UEy`{a*lp)nK;ODgI=BS<+1NC-hmo*|ynXD(KyTnI>=Sg06S5Idim}H|&@m}o zH~Z$CU={AgoLOYony(-z)PB5k<^dK*HyO7wyUmYxVdm8wBI}zuz$%2v-&o@)sYaK9 zVWX^|_s>jM`wd1l!(L&zPivw|zd@&FYG{|UoniuSOx0Fqb6vhU!_^A+4Zb)8QpYoks0{-6ip=fH-BQl}$k0VVF^%u&`4!ehde zltq@Q0kf%RL7QYLWkU@6mBfl_uYxx@8!4T^WjBf2!RB@|RCXHp58FJ)Zc~6RrM594 zzO`-4YIxV!TAo+DvQ3Sdg7d)Cn@capFo;Q0g9cz}?8jvi4JN!_LsJrcKu5`B)SMwL zRk+ckwl$a8uzzMdSf;k^E1Blc({q_>eI@hgT{(-*^~f#gB^q zXgc3$7si93Lzg&D@zsTK`|9FcCIHn=eFu-FAm!^|0)GK$3bgcXEkM&kfdd=aKF>q< zPmP1mrhr3rZ;j_JD1CspwdOvU!Qhu(y%z_X;@F+FyBS}n3h)B7bgnc&OM+DegDs1^ zes^p2A*NE4kJ8BFfn%#Vp6sMFEY3a#>s1WE_ZX7>8_C%-YkCorZ@pVKrye^eOw;G zP@KS|Y(~$}FS*YYj$x)|KxsY7g>n8YffGEXYI=Al)^>$6fB^s-PLr(`4vDZpG+LdS z*pbDQGca9CrAM#zAO^^IMkE*Zp#Umx39L$B@>vTsTx9yWz$X{qV7i(9MWvUo?O7c= zU8@LA8}9gkX)yV-?$xem=WG30Gw{4qyYvGkja-P2Ty3RhYqoal9op*qwf@Zeb<%8w zn>UqUl&`o(y}O+VRu90sVsaqmf^Ta_zlUaC}{57-SA@ZqRAuKI>p8pY%a>SR7l zj6{R`4RsZzhtx52K$Kh(me}ealcp$ zUt|;PJJ4kQmt)f&+)xG`UBHH4(wGOQ1IaBQpmuCZSNw+R;7k{_P0`auN3I%0ev+~! z4QXcNwaw5=R<3R4KFP481q|VG`2}2XX~ndqqtxQU9Y##Pb5qiAAa^PMUv}t!k~00* zcpjZNk`M@Y4yKnnZbxd)D4G7f#rk)A9ypK{uUi$Lev)bN7xV{uf!V6zl59(tfI53Z zl^=jDa!+UA5XB{f!;lZRUuHc0iG%L5D;q!Y9V3angu8X<+@?HT=C}Wm;d=lB`Cl6??RbE*mqvp-Xk}C?kbSmhBl3D zaWlAa3b(}urfU$l-E@++;4%_;Uj|m`w@*Jw;T*q;-A@^;cM^63HO@eR9@xD);^H`P z+gXqZO<^$V!~YCv+-hTn!yQ$z`{_?F{pq1Um*@{pw(c#~?D6Pvs2fXNpylnJ4!^yN zD~L0oFkDrJ9f~(`G@;w(yyTjUW2KEDU%e7f-(mX1(c)bA3tuYv3a_2HIF5^>#f-Ce z%^5G$_&9D?iQDoLr8p?r8+cNM+kI~H^_P{6^!0m7jHsk;0j*@+s9eGL68(IEe)>mA zk!iWYwVCU$&0Ieuvp)?*&<2zClc*)M^`MYSTva4;ACTXy|W zB;N)FDOfpPT9B_6hhy{P5U;ENG0J5R%Vq1NvfW=VJ9xG@#m6A|6==L23>;hD3B=dg z6H<>m=RuY@Ncm+TF99C;Hs)^Q$s#7VYIu8>H$FT!amam)BA>kqilO2toxTulVkczQ zECEMQG6N7g_ZH}DPAR!u703u)IhaS*eIPE*q2ZR|v`|vGN%kVJDvtfrw>z!Bi|EU4y4-S5Jr zVp^E4ua5$&Q~%Xb6eJ`GvIk>1EsrHTG!%}K7))jI*pQ**s;D*r>CiLA)>w*7h<>fNa$NO~d#a zGJ3Bf3<_BIH=%<9@@wPh`B&or^G%K;iAWQW^Z5`&LdTNOSM#sX_YJ7K^bN!A zXW(hIs)zXxaCqt4a5#b9QgV`D10ArROM#BNm?VEqSsJP$X$;w|BCp2=a{Tr)Qe-Y} zzVzF9&VDBLEbq6U;_Rnzk<;_GdInqIpnbgY zc*7}zR27J`_|-6z-;9%Ys1@G~e1FQ|8=`?@V)Dv!6i6sQgFA28YHj zDq{|MR|oPsn~rPjCq#RfXz#?u3bPsFfz#@xfc=EDNqi|geTEy`3b+QqDPXRA2rv4j?D8@6?DN`oq8~G5+N}E?eex&I zz3|c>{#v!z$vw(?PnGFL>K;|<9#y#~_y$DR=rv^;MNWx{%a_td>++Sle3g4aZ^7eX znm$`jpLuP%%YwRW`RrW4SWpK~=`1Y|-jS>tF_YeQ_kw`|<^IiBzRaBG~X+_g(JitNeB>D(>rhu8Lw!gA{Mogj8(71TRTQUiQ&3T?w0g4tx>>%!ikA_s*7dHwu8-O}i1M8+il(v_8k zU294;sC|sk<^&2Q?D5ZCDJX1NQ-b)iy(q`Or4#n=)bQV%BK&QqiC;b?s0a!F13bcy zB#FfbwLsJ()o5mgW|txaRKk|Qx|HG_ zP>Mx23r~2_trTax#+~KwfucB4*Yuq3VcdErfhW=wIW-E0vvnCQ8T&FCi!U3thz+k%K}Y2kgLVCTxaj&+!`)dvnBz|y-3mbd%T7`TPY5M);b#VH~Rh;%)iB$ zhL1=%gek5LY71A!a;sGxuWzIh(0E&a;V%)Zuoj#ho7XwEYixhfkFBBCt#xC+h!uB( zug6w(Qy6mgF1q}s(9%giWJpM8I*adEL65hfm%vXgLI5trzgBXct+=}|(`WBdc%8k( z>Nz{MpmS_q*Vy9jl2vdh=IXes%~;X6+>CYK*ly_900gSFwv0XCJ4&Q)shO6st+-P1)UjrT^YsQr9YyBsTq4%8q6g+7>Y7Fm`j70L@Squ zq8Y7RvW8*>m#(w-jIsAJ{StY1mHf(<*IhWuXTPKvZtpSKd##?%u?1aY^SVo(ioTDF z)zA|PGTI6qf!s>6`_fo0S$k7`=j?JT*8Z_AWA}~iDlOt7@;FBMp1q_n?qa4kJ7^f(AJBy_@!()_-b{cspaK(C4Gq*{|t!$@gsq-Gw84b?EY?RIj_n7Ic>^ zf;TP~Mx)6ZX+NbJlYOKeMvZd+N>_5ta_>g^I?=gQ8=kI=g6`6JC>P;lFoZpN7UgwyyH#wKfcovF`AmPKVK z-X6Pvf{ka2(j&*PI2^_Da8$JSN20fMLTr|KPZ!YB3*K|=-Zg!o{BgMZ+M|kZe-%vV zWw2$qlvQk46_@!?^w)9j0QbeKwn!msjZngmU3d+uM(hGN{*~B;R{_Ec!Uk@pblwb$ z;Q}mtAB6{B#XY2q3>2y7W9e&&9P#xhif&l)2>RE;b@xS% z#(MH>UBx5pOjqP67vaJ}XCIcp7GbpA)>Wi5r_6<5o9m z=_?%je5dVE7ShRS+k>jr>4nE_%ayCy!Xq|S;pbQehpfFiu`G<0A>B3q;Z*78FEb^Y zd=No$Em#UfBr3cX1qpr(ze#%>cP1;`xJPwzZ&u)U`!$-(&0pRTQOF| zbIUaVifG1}M` zX@$_&9ylDhi23L{uL{eZ9|qCouVaD9&~A|kpUDGD!&3OlSV#fQp!bl4gTMKsN~g6a z(jGZ%ZBrg~WqA{#Yl=_s^fk6Zp!*CLWV~aNNd)dR33?e0qpFXK0L34#*FLI^9I)=^j&Lr!+w>XEkdt6ty0Bz-*XZRp+bUoaLBtp7!n_%^Kb*L=)wo~E z!KVwizaBd@@WQ4En?w;g`qG67Z$E!15*uB(10_fh+f%rdOa4=Y5HZ$ZUcbNm$g6SS z=i-}h_|EHI9UqS8JFsM6KB89`C)i$1#mX?|;oryPTSIZgR)w}h0^DAyKzu&C{)_T@ zUlx`Qx-ukdQm^!N>cYE`4Ql& z1B+DD-5qIJ_m~zl%)gMOv+W_JKRpbJjo{Ewgifmy&;)&brm~-7B@TI9+;Y|$!gZA@ zT=?D!U01i?qrpsWjx@ISN~*N>sJ3;7ev*M66W6iPiImJ)?#^(Z;0k4mWox4dq^X}V3Z`27?~O>M`Y4zpvLT=VggFP zg`*QWf(AVAPk0OQwO53%xC5^UM*LL6NOGNp8;7Z;w1)7d+yDG9=(cUXBjS4spy54S z)9lu-J@OvuFbgWGInM)%V)O-E!M}p_FHB;H&Rhu^G7u&RtOSe+W!b>ZEUB9r@9QU- z8KPXS^$w)Dblw4ti?uf4+MVmIO_(r=wH4}xsXG*t_GynKQIB=z`3woj+BN;e>&97ZIQ0KWl%mwo{#$&l zVhZyX|6|JVV@_!q0e^$VgL2ak0n4V6j4})0Hwjnen?b$Te*_q1CyfU!m!VuzC8mjd zh`SMTkln47rIJpQ(EXe)j|pY8W$cG_;IiMXp^FYC1K4WX@94^d)4BN)fajLo4FKD} z0l>p3fK}FW!UXF%?sFNy+&|o70ODqJ;&Z_OFmoe61elw+RxXT-V7Q;Km_gKTGs_zC zMyIXL)b7EBm-XBLGJI}5N8x=A@a{R{8jg4Ep2#^YOKp*3jbFBRUxhLNOI)LpP@YVo zY>u@QrVC?)4LcN*4{2-C#4`L_6d8RPM=~NA(dYQrB*>14eU5%L$7Ikn5#Q%zr6gbf z4xC)GA}mSF&iu8I$}vZBN^i%&ACLwo3;e$kj)8k;xabKaF(K|8Vhno!XaByKz5FKq)9W zCFF&~!zHYC>^hqes}_m(gu3|**PlDN(XG<9xqg9~=VWBpUWLLK3I(&&9Tlh@P++yK z?#V*#I;GbG2fMk^Cq-?WTmPGSw}xr5eNlW`VCl2)n6Fb^GK{HTH&5O3rC?<0{qxjz zdl~CptR{uAB6VM+0J})i{C*7l7JQwv6RtpsTUue{g%PBfYVEjL(3j{cOXqsIFqZoR z)+S$_$zG;UnZP2)gbR_=9|H|Z3l@b)0gUu2cs9Y>Cs|TpJ%J+*E+tc9jf|j~q;Vo6 zMwP>i7%KkM+QZr54kH;Y2IFZ?$-fB=T6#bB|FF z1?-vA>{`C{+|XhA&g-+d8?vAxWpR(GvN$)J1w-aNcCG6UYXKRXryT24jV)%2M#c_H z)3)uhJY!*bxI>Zbj8jD~WwvWq2rnxN$nZSnaHnc`F}p(WNvr2Oue`JIotNKv?VY!! z6?ARPD$Y{4hYwarZHE~#VFYwBS;CXei5aonEqd~rZ1SU8CcWJrYciGWG3FtEf2)xG zZlV87A2VeV{iCu5dH*CyZzSn>Q;=shi|TDza-q7M%-5fhUKK>Y@a0N5mXOaE9!|b0 zzShDzQTi*RHT`*$)S8xNEjy)pqB89XyeY_e%YP}Z-%O<*LT>o<%UAw{f6R`?8+R;< zrTWXX{0c|xjAvW^i^UF6&H)kQ<=pZWAOOH_T6_sejB2{t2n$6Jh?Y z7;n15uZi*dMO=#%PRUiY$y5V!<@t|Ee@Fmdot}+9MoK6(-~aNIVRG|-Pt^SaCxfKF z_0^H8u>@l_Q?1ThxJEko(;d6@!=CM`~z3E1FWCV zP_}uC;Al@|gLwi*0GI)sXQkr?AHO@Ao<=E}xHiV;^sG(bYC}EY*IkgnHk;r;Ha$mB zuNRIW8^OJxKPAEsaE^RYR^U%c%<#mTuyPDHfYM4@no5NE8x~&LrpHmer95qD!Wn+z zWomMGh)*J=O+v~TeiGq4i8b{{N2Bzf%WG3Oo60Bc67<#xXFk8-vadvQyi5(N#O}+& zB-(^;p@!id13>A6ql0;)9sGlmQDbK`Su#us_3EFDF_J@L-jWGiBDv=VaSN$yvPA4s zp>fuhU*Fau(LIUxW#=$=NYP~EV&;yVWM$@`49)@aVC8E{*D36dk1RYlmaS@JwucViGWkxB0rSjf&0S=slJ2KdbX7I zm+*ZrPq|+n;X^AX)u)Jkic?tbN{;aEch2s}NY-@auos7I<-eW3Jc+BV{0(L)nLuFiV$k9du8LxFscAXWful@4c>B5xQ!b5lV+gj zFFW%WKeEKZUE+U5KDzaKe$_=ukJ#gMIQf@O!+C5&apG#}T^BdFvB#UwZ~qFXt#La} zoPXvtrKB;^u86!Ga4}vb)xzH-Rhc1uI5)WTfbOi*IERbdG86pte<}##4SDQWTN~Le zE(8qn`PpC5-%ojd01oV+>0FJHFX;vD?z%pB&-J*7x{uBm%%G#E#08SAF4>@G`cGi zXMUN+|D_+71h46b=UJoBCnCS)Lx)oZfk*~rS9=e)T4f(b%$+nqOdKXnpvUU*e=zS$>zV!lk zY=>eedGTl3NBD6A%e-*YG(5r|?-C!v{h?02sbkr?pJ?fr!yF7TTE4Dp>AD44m_LOx z*EVpdOPF+R%n!Q+)3q_1y7(Vm@Rq`?dL4&<_6r?Jry7!;pL9iPVy8+_LUaE0FsMmf zVh7>3ba}5R+#Nsx2?<{YJJJQiV2#4KU{m_w7ag?NNLl8&le8{et4@f6j#*F2@@9ub zkDG7o0`Z75mBedd$VD%-P!$OC&da~Wh13o%&fk6kKCZ8FV-($RXc?z&}TRON6scMV08;rx&=y|%58?&OxzYO0YSbN*BIrX_Z{bj z$G~@=JTK&-Bncr=!M~{yFgAY2dExGQENZBn{zz{u@#gp!XzCVdp|xXH@fibjK;ur* z-v{x}f53pMf)uEb2KZGN|E9?f)lT>nj0@B^@jYL?XPoqfvbN`|>Mk;=x%muJi+>0Z zCtEs&eYc2oaJ15v(FyLz1Fkib&BaRX{{(eIPzoZMA{~$r=(ixqu7ZzBRs|Hr#AtoBK?Tfr<|bfh{r3BQd_OyZJ2Pj_oHOUlotblI z?wzT-grBr51??rFCF6*a#bn78KIp~WpWtP)8|jk{WPd@fb;5+;1>w0H!lt#XS5?}w zcgA$LpzV0ZHxwSG@mwZN!f3pB=)eTDIJ{`^lBYcy3?YS4OP&pzZx9zoz`=|K2A{${ zOWW=j27iU3Nm5cIDZPaaYRki@bB_Ctc@AB)-SU#lT8`?Mb|FT6q8+ z^+k{NIBvsTw3vTjljHtB`hD5&+kQ3u>iX69bM|ZOSFC7PXq7r;Nsm&=O25aVV%aL$ zM%l-*Pi0$WyJfp%op5oF>ynlp!^PndFGZLmevXKYcm|<{h{14uJED*LU__++aD+$> zcVrOXzL8fbcUDoR2k>^*W+&ItdN-PYdrSO#7#)n<0_Lmd{u4r(mmHQoB<-Uy&JB-+) zAvROoR3U8I42fge5CNeP+*Ce>{p5&aLj;5dxRD~bsTd;^aKY<|$=0rdZ}FTJ9D1-L z1khLfwBG!bW8!RpeZ3(GC-gRVl*7TZn~<}bf>$_)636*SW`)BG_fbcNB3U&)_3dMf zGk`Uv?)l-4$Ah!sD+M&yMJuoJ?z=O2Z(y;Cj<#bj+ zmkr3BXz7zPCfU^utQXm|^n_pfE3E>`S?Db2zz`&`rRy#}2UaEF^5Ie+b#HaczqcZ1%YwcCd$${^%Suyu!d)bI{NE za1HkqeAIZ}=9#Chv|WJREBzpAp0oApcv@_`Vh72V)(Gov*4=d6bB`=gP^CpnVuZCz zPe5-XgvpG%##VSHv{~(*sNuoV6YW^ru*=PM0`0B*4fodiFZ`TOWL{X>MulPn`Roqb=4@a`As?uVl*th{V z_??Rsp1M=HHc$$->hB>egyot0hTcsn+)+Gv(1r6OVynwu$*$VMIOb8jGGFqmx7itXG@p}MK!iwcGrrp4W^09SDJ)S z0TvOYoNcw%**hNXtbvdGP!c}jVkFlQ0IP&1_#zKL@Fobywg=ueazKL&H$8;DAc`+R zFSuh%CP*B@cuPEq;&IK#Zx^BX*PxLZ#PJqoEP{FaS>bQZoH70Ep~TLz!HF2B9oO#m zdC=$AKJM#Jp+own^?j>vS>OGAkM#XbZwyqb3j+7y{_xVO#*ORDZ7r}xG227zZc;)y zVGG#h>65~O!?z(+3P(hkuN9de6bY+Kn`GBwo19ewn((7OsG!Au=Fbq4RU}X*|8N+0 zwtIZKcix&Ce zFdWz{MU3@^!;fjOcE#+w0d|d1U4}Us#(IjeK0ZXq?$qAxqPMW_09RI3djo#8WP5Eb zrcDwRhmhQ-j6?I72D^jHT(vURhj%LfLFLSjNs&S0dfRQ%)6h4v+;u(f?lDH3rfY>KI4Av1lwS z^IUB2rtsXOnwhsss=k_eS&#Bz)Yh~IRY6g?4$+^G56bSs8i;4VBOx#mb^5lW2-@8 z>JMxHz}7SD>&yndYFmZuAK(JmOK?&H)GgF=eK3VEA;y{7kpwEX-e=2E;h2eiE7TOE zSv$-VI>d}s2f=o8PRAoQ*f{MOTSZOmwF6f=F29FBo$i^@7pqea>O93Xrn-?a8deFP zWy6X&nKhv`XPLjw;ZDJFu26S)DlE- z$L5GA?2k>pK|la<0*%ztDn+>uzD;XwalLrT`V!JM*%dx}`mD1FzJZnaFX2zLrBA~LlfVXNO6Xez8`n=#xjs6j zpRPDN{PB<5;AlrBLjM|a-C1R(ZO&R*mAyZwYBAqgDS+cWE0;8*`*2=~lV>(@#waa) zm$f-YJEpDaA{i%bTdjg&04smErv7+8Rb=;Z6P}T zq=CT$4IE9JR;nbB^MVY%11vI4DC3z#WxeR3EO}ePa+8WBx;+MAx+7V-BHJ=}@lwcK z#q2I$hcx*}0n{L4jehLWoPnG^efrrS;Zsal19TYMN`eIlOt~kHMrbSUjHSv!XseNH z;#Sf;1F=X@$+nW8E1An9l!$3mDbaQnn5gC!GYg4rVYqx18aN^`wq=J3_yR&D9`}x| zzMWw?Z*B(T9INUFAM=^|We+osG0Kb;=VF6>P=@6Ky!@R}^|sLam1>l%H)u0;+0>}0 zC~6=zN}s>LpqZCTQ-fZ6Z4lL&n5Lt(DwLur&}6GAwZWh__zRP=bb3Qxrk2V#=;s+S z^C((v$kXUDX^mdz&rUo(zmfh^D7kCmjKz|M3BV>q1ZFk|d6XOGxGfrWUkz#mhEGO$=(qPWpK^t?32Vqto2WxB=j@Bm6) z>H$oQhFzD`EFufyb-@4&O9fC??;Zu=sJm=lh|hr@EH?@p@hT&m&kMs7bW`jOe<7?p zO1GF1Zq_WlHd~dWqmdyCP07_5Dfr8zvekKdiq=!cTzw%$=c*}VzFM74WovSB)CRR~ zuA0hH(}ila4$al)}V<b!c7Oa3O$vjq4P5HjVg+o0u1pGj%-$@FuMCQbp`gUCE40}Z6qxl#dHjKtB2G0(n={Pg4MI~i&{fRC z+BfJ;^Kz*ykj_YJwAyHj`in_Jt0_%hK9*5apr-m!Xp~lypO14GwfaJ=MhF|JY<;1Q znhW}X3NU15X&0y{)GR>na7Gfz+)v4IJS0US&4_anHA}pqe1D%2zDbhX0s8_QrKsnv zU_QpW4>vN#PsI4b7vUrV&Mg6&&zV8YNl4I0?VAs6QkL^{qa zVm5aTnZ^4XKg;L7Z>D&VWJo|s;NYNF05c)@?U3eoIlVdE0+$Z6u-^7SsYJ4Y_$c!4yY+}_eaesTBwlH~y(2F_z~@`8_H&E#@^ zC$ZQ!@kJ8H{T}na@0=H65)xi-UL5ZYo`LsoUJDQLd+`(b+5A=f3*>FwDgWXA(7+!W z_KoZ2?0NwPYw#-C&cz-yJQS9` z@xy>Uf4<%OlbQb>c5LBO{<72)%3V1v!Rx2}6#sRBQ?zQr8P(^ypToA!ZW!?$EVnF4 zs_3^p^IE`~Np*w1_{#&|lC)F(|DmzJv}uO*wWAB3@ID+}t=Or)+4JM67hgSO`qh8s z_H7q$5m zkEwZi_qMR?*PK$ZgUeEeQJF+oev>K@U8 z_t6HpE=Akm`T^Pp*ALMlxGqEA!?hS$;hLh)%hc#lirQ^icN*MT3#b@05ln;}82r#w z9SnACC>;iU4H)2BJ=g;J95BSyb2ZqEK$Gdrx$~)oq#sZM_ep z6h@d$KnOnTL{t(&CzBCcn1T{RQ&D>57$m3D%g9vqrS*^KCCR???^tGc8$W zDmXQE{LNXfSI-)5*}8TnvwKL9Kl+s0n50bqZ)|EmV1h%<+PAGwX#_P^vwbh%DrlpuH-;qe6m zfwU(tNEFNqAj0}bM`Fi%JYN5h5O_Fy?!?g%M6`GSAO!UZB?z9F2#FjJG{A!pAqtHQ ziBJSZqABCkkxDL?0}n~0&ZO1CKEhHdN7_>gjzCf_DfQ)bIt=qTafny|K_6*wCq(Ms z6_QGXVzF2tluG&1z#by0G(hSn?Mg@8?>pekLD=?9nuPKVxFs3qX6kaNVHC7Q?*^8G zpNeTCrPI@tR->D*&W5Mq49_bl?l*QMy!{~u*&mWT#`ioi3_mGJ&IAJ!$*m9^J_xt& Fe*;Cgs_*~+ diff --git a/16/xlib/demo3.exe b/16/xlib/demo3.exe deleted file mode 100755 index ef3a06a2b7037cf10439b7ec0f3880eb055affa2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9516 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 diff --git a/16/xlib/demo5.exe b/16/xlib/demo5.exe deleted file mode 100755 index 30993d2f235ae8f9ec22d1ed940c54816b785d48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19556 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%0A^zq{C1voalA;y|dm zZHhAvWxQ=}_Ir=gF4|ub4hKprcp^rNv!VC7j$QPm1OAb(gNFZ^q>8-c&er(s@w!F3f&%5-nh&? z3H=M$0N$GQRp^h(I8DofD9vX|vQ1=Re7FI>k$A;x!o@%%PaEl#{h_w~p}zg0uFJ2( zcA>_7q42(y31K$uKkunC{Fd@_W#EGMn{U0zxYrW$){LeX`B`-{&f)uWQ=9QmZ|;vn zjBWeQo}~>pvM_?h;X4VqK$K=kSmNR9<|PznBb%4t({tlJ7G4a)oE&QyFg$xylcWXY z087^YkN?W|RX)NISe(a{pdaPPz0^O87EhwS$-!d$nt`Y8J8Axm zQ4V(o{WFB(j8xyPaUN38XB6BSsrk2FFDWDFzjaiSHRwwjl{6{npR8ht5t9nT*GB~W z0FC->^}Ryi6a4rwLllm;M}ihBvp-U)2`H+3lk0ngz{jNWR#9kd#~HdP2RNiU!^D;Z zaqe_cfK7tAX&~l@iH&jMV2)iB`r3PfIq9POFh^~WWScIwD>NN!)9qsWd1^@$g%&1# zib$bBygf;zxmIycx`;RYa-~h&lM-)D7HJMNxk?xr&7HzfXpT*k&jA7kxs${_Hb5qe z@}EiI!%2Z7lT?ctjLpc=RF6TmzzAZDYOcoILJQJo3F3?E;xFgWZm0b$w3nxY)JzQB|m>yr)-kTZQED5=HVyrX8 z(f$Zm_GLH-Ftr@u12N(`P^KHeZ{UJCGsK`}rs#;3)qCEeA1!R}VT73jo09}|-M}ET zFY~IVbbI}IUT6?Rtf;O4a=Y=Q<21Al*=LEGf+{I{#WR24v#}B%`zwh>o`rucu^ACWMBW9z=So_0^+eQ#atT6)l8`c=<*H{m~C!V*yblsCBPi4%{%*?nuWB&T* zUo3rQ&00^!ckaLcI~l{B3rjrfvdF{F_?~&{>5QjKOV^i3L>-$vERM`~UdJJ;=`!exv)oo}`h9-Gpl<-PW;C zahxGH=^^X+@%vLgOCuA`rHc%!j}V^W=P`Wa&2aL7b50^Z<_h^0LWQnaA7c1xfq!oN zSm;>V)VqfztYy?Gq=YNti-n!KAL@T5{?O2u^knjPtoMx%revqy1I)SUPfYB7ft$=- zKaQll_(*=v-DD(rH;&{q*Db^;@;Fe$$8rN!9(S5Mmo!%EIK^5}++;Kf>an8%ee(76 z)@|eeF=dU0^IUo@v&>rVuST4lly|ccfA_C3`;u1O6q9cwC&|~u$j#zj!~bBY!@W5bW0ELoi~Cu8-x^+--i)?_@to`F}h?8UPoqh!4&W8E_)KYseDF1 N!rR!|u&y5We*qA$Krop}WQ8!? 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 aw=lYs!U-*YpPIjr{}Cn&ackTsH2p8OYRakr diff --git a/16/xlib/makefile b/16/xlib/makefile index cba0dcac..d1ec5db3 100755 --- a/16/xlib/makefile +++ b/16/xlib/makefile @@ -150,6 +150,9 @@ xvsync.$(OBJ) : xvsync.asm# xvsync.inc xlib.inc model.inc xfill.$(OBJ) : xfill.asm# xfill.inc xlib.inc model.inc $(CC) -c $(CFLAGS) xfill.asm# xfill.inc xlib.inc model.inc +xbezier.$(OBJ): xbezier.asm + $(CC) -c $(CFLAGS) xbezier.asm + # #other~ # diff --git a/16/xlib/model.inc b/16/xlib/model.inc index 0aded8e9..f35b3fae 100755 --- a/16/xlib/model.inc +++ b/16/xlib/model.inc @@ -1,20 +1,22 @@ -/*;IFDEF s +IFDEF s ; DISPLAY "XLIB04 Small Model" -; .model small -;ELSE -; IFDEF c + .model small +ELSE + IFDEF c ; DISPLAY "XLIB04 Compact Model" -; .model compact -; ELSE -; IFDEF l + .model compact + ELSE + IFDEF l ; DISPLAY "XLIB04 Large Model" -; .model large -; ELSE + .model large + ELSE + IFDEF h + .model huge + ELSE ; DISPLAY "WARNING: Model was not defined at the command line." ; DISPLAY " Using default small model ie /ds " ; DISPLAY " Include in TASM commandline either /ds, /dc or /dl" -;; .model small -; ENDIF -; ENDIF -;ENDIF -*/ + .model small + ENDIF + ENDIF +ENDIF diff --git a/16/xlib/xbmtools.asm b/16/xlib/xbmtools.asm index f39c9a32..490b2635 100755 --- a/16/xlib/xbmtools.asm +++ b/16/xlib/xbmtools.asm @@ -42,7 +42,7 @@ COMMENT $ $ -LOCALS +.LOCALS .8086 include model.inc diff --git a/16/xlib/xfileio.asm b/16/xlib/xfileio.asm index 40a07775..253e237c 100755 --- a/16/xlib/xfileio.asm +++ b/16/xlib/xfileio.asm @@ -430,4 +430,3 @@ _f_filelength endp end - diff --git a/16/xlib/xlib.inc b/16/xlib/xlib.inc index 3dbfa758..e352f3cf 100755 --- a/16/xlib/xlib.inc +++ b/16/xlib/xlib.inc @@ -19,12 +19,12 @@ ; -;.LOCALS +;.global ;.8086 ; First lets find out what memory model to use - -include model.inc +;.model huge +;include model.inc AC_INDEX equ 03c0h ;Attribute controller index register @@ -162,5 +162,3 @@ WaitNotVsync2: global _VsyncPaletteStart :word global _VsyncPaletteCount :word global _VsyncPaletteBuffer :byte - - diff --git a/16/xlib/xline.asm b/16/xlib/xline.asm index 6c9c5c56..910c1fc9 100755 --- a/16/xlib/xline.asm +++ b/16/xlib/xline.asm @@ -26,9 +26,10 @@ ModeXAddr macro mov dx,[_ScrnLogicalByteWidth] mul dx pop dx - shr bx,2 + shr bx,1 + shr bx,1 add bx,ax - add bx,[PgOffs] + add bx,[bp+14] and cl,3 endm @@ -44,7 +45,7 @@ ModeXAddr macro ; _x_line proc -ARG x1:word,y1:word,x2:word,y2:word,Color:word,PgOffs:word +;ARG x1:word,y1:word,x2:word,y2:word,Color:word,PgOffs:word LOCAL vertincr:word,incr1:word,incr2:word,routine:word=LocalStk push bp ; Set up stack frame mov bp,sp @@ -60,8 +61,8 @@ LOCAL vertincr:word,incr1:word,incr2:word,routine:word=LocalStk ; check for vertical line mov si,[_ScrnLogicalByteWidth] - mov cx,[x2] - sub cx,[x1] + mov cx,[bp+8] + sub cx,[bp+4] jz VertLine ; force x1 < x2 @@ -70,19 +71,19 @@ LOCAL vertincr:word,incr1:word,incr2:word,routine:word=LocalStk neg cx - mov bx,[x2] - xchg bx,[x1] - mov [x2],bx + mov bx,[bp+8] + xchg bx,[bp+4] + mov [bp+8],bx - mov bx,[y2] - xchg bx,[y1] - mov [y2],bx + mov bx,[bp+10] + xchg bx,[bp+6] + mov [bp+10],bx ; calc dy = abs(y2 - y1) L01: - mov bx,[y2] - sub bx,[y1] + mov bx,[bp+10] + sub bx,[bp+6] jnz short skip jmp HorizLine skip: jns L03 @@ -113,14 +114,17 @@ L04: ; calc first pixel address push cx - mov ax,[y1] - mov bx,[x1] + mov ax,[bp+6] + mov bx,[bp+4] ModeXAddr mov di,bx mov al,1 shl al,cl mov ah,al ; duplicate nybble - shl al,4 + shl al,1 + shl al,1 + shl al,1 + shl al,1 add ah,al mov bl,ah pop cx @@ -130,8 +134,8 @@ L04: ; routine for verticle lines VertLine: - mov ax,[y1] - mov bx,[y2] + mov ax,[bp+6] + mov bx,[bp+10] mov cx,bx sub cx,ax jge L31 @@ -140,7 +144,7 @@ VertLine: L31: inc cx - mov bx,[x1] + mov bx,[bp+4] push cx ModeXAddr @@ -149,7 +153,7 @@ L31: mov al,MAP_MASK out dx,ax pop cx - mov ax, word ptr [Color] + mov ax, word ptr [bp+12] ; draw the line @@ -164,15 +168,15 @@ L32: HorizLine: push ds - mov ax,[y1] - mov bx,[x1] + mov ax,[bp+6] + mov bx,[bp+4] ModeXAddr mov di,bx ; set dl = first byte mask mov dl,00fh shl dl,cl - mov cx,[x2] ; set dh = last byte mask + mov cx,[bp+8] ; set dh = last byte mask and cl,3 mov dh,00eh shl dh,cl @@ -180,17 +184,19 @@ HorizLine: ; determine byte offset of first and last pixel in line - mov ax,[x2] - mov bx,[x1] + mov ax,[bp+8] + mov bx,[bp+4] - shr ax,2 ; set ax = last byte column - shr bx,2 ; set bx = first byte column + shr ax,1 ; set ax = last byte column + shr bx,1 ; set bx = first byte column + shr ax,1 ; set ax = last byte column + shr bx,1 ; set bx = first byte column mov cx,ax ; cx = ax - bx sub cx,bx mov ax,dx ; mov end byte masks to ax mov dx,SC_INDEX ; setup dx for VGA outs - mov bx, [Color] + mov bx, [bp+12] ; set pixels in leftmost byte of line @@ -231,7 +237,7 @@ L44: LoSlopeLine: mov al,MAP_MASK - mov bh,byte ptr [Color] + mov bh,byte ptr [bp+12] L10: mov ah,bl @@ -283,7 +289,7 @@ HiSlopeLine: mov al,MAP_MASK L21: out dx,ax push ax - mov ax,[Color] + mov ax,[bp+12] mov es:[di],al pop ax add di,bx @@ -314,4 +320,3 @@ Lexit: _x_line endp end - \ No newline at end of file diff --git a/16/xlib/xmain.asm b/16/xlib/xmain.asm index a8fd4184..cdb174fd 100755 --- a/16/xlib/xmain.asm +++ b/16/xlib/xmain.asm @@ -22,19 +22,18 @@ ; and tripple buffering - Tore Jahn Bastiansen ; (toreba@ifi.uio.no) for the ;----------------------------------------------------------------------- - - include xlib.inc include xmain.inc - .data + _DATA SEGMENT WORD PUBLIC USE16 'DATA' +;.data ; Mode X CRTC register tweaks for various resolutions -LABEL X256Y200 word +X256Y200 LABEL word db 0e3h ; dot clock db 8 ; Number of CRTC Registers to update dw 05f00h ; horz total @@ -49,7 +48,7 @@ LABEL X256Y200 word dw 200 -LABEL X256Y240 word +X256Y240 label word db 0e3h ; dot clock db 16 ; Number of CRTC Registers to update dw 05f00h ; horz total @@ -157,7 +156,7 @@ X376Y282 label word dw 376 dw 282 -LABEL X256Y400 word +X256Y400 label word db 0e3h ; dot clock db 8 ; Number of CRTC Registers to update dw 05f00h ; horz total @@ -173,7 +172,7 @@ LABEL X256Y400 word dw 400 -LABEL X256Y480 word +X256Y480 label word db 0e3h ; dot clock db 16 ; Number of CRTC Registers to update dw 05f00h ; horz total @@ -439,6 +438,9 @@ PARAM_COUNT equ ($-PARAMS) DoubleScanFlag db ? ; Flag to indicate double scanned mode +_DATA ENDS + + .code ;------------------------------------------------------------------------- @@ -459,7 +461,9 @@ SetLogicalScrWidth proc mov ax,bx ; no - set logical width = physical @@ValidLogicalWidth: - shr ax,3 + shr ax,1 + shr ax,1 + shr ax,1 out dx,al ; The EXACT logical pixel width may not have been possible since @@ -472,10 +476,12 @@ SetLogicalScrWidth proc mov [_RightClip],ax ; Set default Right clip column ; screen sub ax,[_ScrnPhysicalByteWidth] ; Calculate and store Max X position - shl ax,2 ; of physical screen in virtual + shl ax,1 ; of physical screen in virtual + shl ax,1 ; of physical screen in virtual mov [_MaxScrollX],ax ; screen in pixels mov ax,bx ; set ax to byte width of virt scrn - shl ax,2 ; convert to pixels + shl ax,1 ; convert to pixels + shl ax,1 ; convert to pixels mov [_ScrnLogicalPixelWidth],ax ; store virt scrn pixel width mov cx,ax ; save ax (return value) @@ -550,7 +556,7 @@ clear_vram endp ; parts adapted from M. Abrash code. ;------------------------------------------------------------------------ _x_set_mode proc - ARG mode:word,logicalscrwidth:word + ;;arg mode:word,logicalscrwidth:word push bp ;preserve caller's stack frame mov bp,sp @@ -565,7 +571,7 @@ _x_set_mode proc mov cx,PARAM_COUNT rep stosb - mov cx,[mode] + mov cx,[BP+4] cmp cx,LAST_X_MODE ; have we selected a valid mode jle @@ValidMode ; Yes ! @@ -657,7 +663,8 @@ _x_set_mode proc mov [_SplitScrnScanLine],ax ; No splitscrn == ; splitscrn=PhysicalscrnHeight mov bx,ax ; Copy width for later use - shr ax,2 ; Convert to byte width + shr ax,1 ; Convert to byte width + shr ax,1 ; Convert to byte width mov [_ScrnPhysicalByteWidth],ax ; Store for later use lodsw ; Load Screen Phys. Height mov [_ScrnPhysicalHeight],ax ; Store for later use @@ -665,7 +672,7 @@ _x_set_mode proc ; Mode X is set, now set the required logical page width. - mov cx,[logicalscrwidth] + mov cx,[BP+6] call SetLogicalScrWidth @@ -687,10 +694,10 @@ _x_set_mode endp ; Written by Themie Gouthas ;---------------------------------------------------------------------- _x_select_default_plane proc -ARG Plane:byte + ;arg Plane:byte push bp mov bp,sp ; set up stack frame - mov cl,byte ptr [Plane] + mov cl,byte ptr [bp+4] ; SELECT WRITE PLANE and cl,011b ;CL = plane @@ -727,7 +734,7 @@ _x_select_default_plane endp ;---------------------------------------------------------------------- _x_set_splitscreen proc - ARG Line:word + ;arg Line:word push bp mov bp,sp ; set up stack frame push si @@ -769,7 +776,7 @@ _x_set_splitscreen proc mov [_PhysicalStartPixelX],ax ; offset within virtual screen mov [_PhysicalStartY],ax mov [_SplitScrnActive],TRUE - mov ax,[Line] + mov ax,[bp+4] jns @@NotNeg ; Check that Split Scrn start scan line is +ve mov ax,0 ; Since -ve set to 0 @@ -804,7 +811,10 @@ _x_set_splitscreen proc mov ah,bh and ah,1 - shl ah,4 + shl ah,1 + shl ah,1 + shl ah,1 + shl ah,1 mov al,OVERFLOW ; Bit 4 of overflow register = Bit 8 of split out dx,al ; screen scan line, inc dx ; So using readability of VGA registers @@ -816,7 +826,9 @@ _x_set_splitscreen proc dec dx mov ah,bh and ah,2 - ror ah,3 + ror ah,1 + ror ah,1 + ror ah,1 mov al,MAX_SCAN_LINE ; Bit 6 of max scan line register = out dx,al ; Bit 9 of split screen scan line inc dx ; As we did before, update the apropriate @@ -846,9 +858,9 @@ _x_set_splitscreen proc mov [_ScrnLogicalHeight],ax ; Save Screen Logical Height cmp ax,[_BottomClip] - jle @@BottomClipOK ; Adjust Clip Rectangle if necessary + jle @@BottomClipOK2 ; Adjust Clip Rectangle if necessary mov [_BottomClip],ax -@@BottomClipOK: +@@BottomClipOK2: sub ax,[_SplitScrnScanLine] ; Update the maximum Y position of mov [_MaxScrollY],ax ; Physical screen in logical screen @@ -875,14 +887,14 @@ _x_set_splitscreen endp ;------------------------------------------------------------------------ _x_page_flip proc - ARG x:word,y:word + ;arg x:word,y:word push bp ;preserve caller's stack frame mov bp,sp ;point to local stack frame push si - mov si,[x] + mov si,[bp+4] mov ax,[_ScrnLogicalByteWidth] ; Calculate Offset increment - mov cx,[y] + mov cx,[bp+6] mul cx ; for Y cmp [_DoubleBufferActive],TRUE ; Do we have double buffering ? je @@DoubleBuffer @@ -931,14 +943,14 @@ _x_page_flip endp ; Parts addapted from M. Abrash code published in DDJ Mag. ;------------------------------------------------------------------------ _x_set_start_addr proc - ARG x:word,y:word + ;arg x:word,y:word push bp mov bp,sp push si - mov si,[x] + mov si,[bp+4] mov ax,[_ScrnLogicalByteWidth] ; Calculate Offset increment - mov cx,[y] ; for Y + mov cx,[bp+6] ; for Y mul cx cmp [_DoubleBufferActive],TRUE ; Do we have double buffering ? je @@PageResolution @@ -958,7 +970,8 @@ PageFlipEntry2: @@AddColumn: mov cx,si - shr cx,2 + shr cx,1 + shr cx,1 mov [_PhysicalStartByteX],cx add ax,cx ; add the column offset for X mov bh,al ; setup CRTC start addr regs and @@ -1052,14 +1065,14 @@ _x_hide_splitscreen proc cmp [_SplitScrnActive],TRUE je @@SplitScreenEnabled -@@error: +@@error0: mov [_ErrorValue],ERROR pop bp ret @@SplitScreenEnabled: cmp [_CurrXMode],4 ; Do nothing for Modes > 2 - jg @@error + jg @@error0 mov bx,[_ScrnPhysicalHeight] mov ax,[_ScrnLogicalHeight] @@ -1069,10 +1082,10 @@ _x_hide_splitscreen proc mov [_SplitScrnVisibleHeight],ax or [DoubleScanFlag],0 - jz @@NotDoubleScanned + jz @@NotDoubleScanned0 shl bx,1 dec bx -@@NotDoubleScanned: +@@NotDoubleScanned0: ;mov cl,[DoubleScanFlag] ; Compensate for double scanned modes ;shl bx,cl @@ -1086,7 +1099,10 @@ _x_hide_splitscreen proc mov ah,bh and ah,1 - shl ah,4 + shl ah,1 + shl ah,1 + shl ah,1 + shl ah,1 mov al,OVERFLOW ; Bit 4 of overflow register = Bit 8 of split out dx,al ; screen scan line, inc dx ; So using readability of VGA registers @@ -1098,7 +1114,9 @@ _x_hide_splitscreen proc dec dx mov ah,bh and ah,2 - ror ah,3 + ror ah,1 + ror ah,1 + ror ah,1 mov al,MAX_SCAN_LINE ; Bit 6 of max scan line register = out dx,al ; Bit 9 of split screen scan line inc dx ; As we did before, update the apropriate @@ -1108,7 +1126,7 @@ _x_hide_splitscreen proc out dx,al sti ; Registers are set, so interrupts are safe -@@done: +@@done0: mov [_ErrorValue],OK pop bp @@ -1140,16 +1158,16 @@ _x_show_splitscreen proc mov bp,sp cmp [_SplitScrnActive],TRUE - je @@SplitScreenEnabled + je @@SplitScreenEnabled0 -@@error: +@@error1: mov [_ErrorValue],ERROR pop bp ret -@@SplitScreenEnabled: +@@SplitScreenEnabled0: cmp [_CurrXMode],4 ; Do nothing for Modes > 2 - jg @@error + jg @@error1 mov bx,[_SplitScrnScanLine] mov ax,[_ScrnLogicalHeight] ; Update Max Scroll Y @@ -1161,10 +1179,10 @@ _x_show_splitscreen proc mov [_SplitScrnVisibleHeight],ax or [DoubleScanFlag],0 - jz @@NotDoubleScanned + jz @@NotDoubleScanned1 shl bx,1 dec bx -@@NotDoubleScanned: +@@NotDoubleScanned1: ;mov cl,[DoubleScanFlag] ; Compensate for double scanned modes ;shl bx,cl WaitVsyncStart ; wait for vertical retrace @@ -1177,7 +1195,10 @@ _x_show_splitscreen proc mov ah,bh and ah,1 - shl ah,4 + shl ah,1 + shl ah,1 + shl ah,1 + shl ah,1 mov al,OVERFLOW ; Bit 4 of overflow register = Bit 8 of split out dx,al ; screen scan line, inc dx ; So using readability of VGA registers @@ -1189,7 +1210,9 @@ _x_show_splitscreen proc dec dx mov ah,bh and ah,2 - ror ah,3 + ror ah,1 + ror ah,1 + ror ah,1 mov al,MAX_SCAN_LINE ; Bit 6 of max scan line register = out dx,al ; Bit 9 of split screen scan line inc dx ; As we did before, update the apropriate @@ -1199,7 +1222,7 @@ _x_show_splitscreen proc out dx,al sti ; Registers are set, so interrupts are safe -@@Done: +@@Done1: mov [_ErrorValue],0 pop bp ret @@ -1229,24 +1252,24 @@ _x_show_splitscreen endp _x_adjust_splitscreen proc - ARG ScanLine + ;arg ScanLine push bp mov bp,sp cmp [_SplitScrnActive],TRUE - je @@SplitScreenEnabled + je @@SplitScreenEnabled1 -@@error: +@@error2: mov [_ErrorValue],ERROR pop bp ret -@@SplitScreenEnabled: +@@SplitScreenEnabled1: cmp [_CurrXMode],4 ; Do nothing for Modes > 2 - jg @@error - mov bx,[ScanLine] ; Is the required starting scan line + jg @@error2 + mov bx,[bp+4] ; Is the required starting scan line cmp bx,[_SplitScrnScanLine] ; valid ? - js @@Done ; No - Then do nothing + js @@Done2 ; No - Then do nothing @@ValidScanLine: @@ -1259,10 +1282,10 @@ _x_adjust_splitscreen proc mov [_SplitScrnVisibleHeight],ax or [DoubleScanFlag],0 - jz @@NotDoubleScanned + jz @@NotDoubleScanned2 shl bx,1 dec bx -@@NotDoubleScanned: +@@NotDoubleScanned2: ;mov cl,[DoubleScanFlag] ; Compensate for double scanned modes ;shl bx,cl @@ -1277,7 +1300,10 @@ _x_adjust_splitscreen proc mov ah,bh and ah,1 - shl ah,4 + shl ah,1 + shl ah,1 + shl ah,1 + shl ah,1 mov al,OVERFLOW ; Bit 4 of overflow register = Bit 8 of split out dx,al ; screen scan line, inc dx ; So using readability of VGA registers @@ -1289,7 +1315,9 @@ _x_adjust_splitscreen proc dec dx mov ah,bh and ah,2 - ror ah,3 + ror ah,1 + ror ah,1 + ror ah,1 mov al,MAX_SCAN_LINE ; Bit 6 of max scan line register = out dx,al ; Bit 9 of split screen scan line inc dx ; As we did before, update the apropriate @@ -1298,7 +1326,7 @@ _x_adjust_splitscreen proc or al,ah out dx,al sti ; Registers are set, so interrupts are safe -@@Done: +@@Done2: mov [_ErrorValue],OK pop bp ret @@ -1330,7 +1358,7 @@ _x_adjust_splitscreen endp _x_set_doublebuffer proc - ARG PageHeight:word + ;arg PageHeight:word push bp mov bp,sp @@ -1346,7 +1374,7 @@ _x_set_doublebuffer proc mov ax,[_ScrnLogicalHeight] ; Set Maximum D.B. Page height to shr ax,1 ; _ScrnLogicalHeight / 2 - mov bx,[PageHeight] ; Is the require D.B. Page Height + mov bx,[bp+4] ; Is the require D.B. Page Height cmp ax,bx ; > the Maximum D.B. Page Height ? js @@InvalidHeight ; no - jump @@ -1357,9 +1385,9 @@ _x_set_doublebuffer proc mov [_ScrnLogicalHeight],ax ; Update logical screen height to ; reflect the height of a D.B. page cmp ax,[_BottomClip] - jle @@BottomClipOK ; Adjust Clip Rectangle if necessary + jle @@BottomClipOK0 ; Adjust Clip Rectangle if necessary mov [_BottomClip],ax -@@BottomClipOK: +@@BottomClipOK0: push ax mul [_ScrnLogicalByteWidth] ; Calculate the offset of the second mov cx,ax ; D.B. Page in video ram @@ -1410,40 +1438,40 @@ _x_set_doublebuffer endp ;------------------------------------------------------------------------ _x_set_tripplebuffer proc - ARG PageHeight:word + ;arg PageHeight:word push bp mov bp,sp cmp [_DoubleBufferActive],0 - jne @@Error + jne @@Error3 cmp [_TrippleBufferActive],0 - je @@OkToContinue -@@Error: + je @@OkToContinue3 +@@Error3: mov [_ErrorValue],ERROR pop bp ret -@@OkToContinue: +@@OkToContinue3: mov [_VisiblePageIdx],0 ; Set visible Page to 0 mov ax,[_ScrnLogicalHeight] ; Set Maximum T.B. Page height to mov bx,3 xor dx,dx idiv bx ; _ScrnLogicalHeight / 3 - mov bx,[PageHeight] ; Is the require T.B. Page Height + mov bx,[bp+4] ; Is the require T.B. Page Height cmp ax,bx ; > the Maximum T.B. Page Height ? - js @@InvalidHeight ; no - jump + js @@InvalidHeight0 ; no - jump mov ax,bx ; yes - Set the T.B. Page height to ; to the maximum allowed. -@@InvalidHeight: +@@InvalidHeight0: mov [_ScrnLogicalHeight],ax ; Update logical screen height to ; reflect the height of a T.B. page cmp ax,[_BottomClip] - jle @@BottomClipOK ; Adjust Clip Rectangle if necessary + jle @@BottomClipOK1 ; Adjust Clip Rectangle if necessary mov [_BottomClip],ax -@@BottomClipOK: +@@BottomClipOK1: push ax mul [_ScrnLogicalByteWidth] ; Calculate the offset of the second mov cx,ax ; D.B. Page in video ram @@ -1489,19 +1517,19 @@ _x_set_tripplebuffer endp ;------------------------------------------------------------------------ _x_set_cliprect proc -ARG left:word,top:word,right:word,bottom:word +;arg left:word,top:word,right:word,bottom:word push bp mov bp,sp - mov ax,[left] - mov bx,[right] + mov ax,[bp+4] + mov bx,[bp+8] cmp bx,ax jns @@CorrectXOrder xchg bx,ax @@CorrectXOrder: mov [_LeftClip],ax mov [_RightClip],bx - mov ax,[top] - mov bx,[bottom] + mov ax,[bp+6] + mov bx,[bp+10] cmp bx,ax jns @@CorrectYOrder xchg bx,ax @@ -1536,4 +1564,4 @@ _x_wait_vsync proc _x_wait_vsync endp - end +end diff --git a/16/xlib/xmain.inc b/16/xlib/xmain.inc index 44b40fc2..4b1f4410 100755 --- a/16/xlib/xmain.inc +++ b/16/xlib/xmain.inc @@ -26,6 +26,6 @@ global _x_show_splitscreen :proc global _x_adjust_splitscreen :proc global _x_set_doublebuffer :proc - global _x_set_tripplebuffer :proc + global _x_set_tripplebuffer :proc global _x_set_cliprect :proc - global _x_wait_vsync :proc \ No newline at end of file + global _x_wait_vsync :proc diff --git a/16/xlib/xpal.asm b/16/xlib/xpal.asm index 558f2665..a27155dc 100755 --- a/16/xlib/xpal.asm +++ b/16/xlib/xpal.asm @@ -65,18 +65,18 @@ include xpal.inc ; Written by Themie Gouthas ;---------------------------------------------------------------------- _x_get_pal_struc proc -ARG PalBuff:dword,NumColors:word,StartColor:word +;ARG PalBuff:dword,NumColors:word,StartColor:word push bp ; Set up stack frame mov bp,sp push di push si cld - les di,dword ptr [PalBuff] ; Point es:di to palette buffer - mov si,[StartColor] ; Store the Start Colour + les di,dword ptr [bp+4] ; Point es:di to palette buffer + mov si,[bp+10] ; Store the Start Colour mov ax,si stosb - mov dx,[NumColors] ; Store the Number of Colours + mov dx,[bp+8] ; Store the Number of Colours mov al,dl stosb @@ -100,16 +100,16 @@ _x_get_pal_struc endp ; Written by Themie Gouthas ;---------------------------------------------------------------------- _x_get_pal_raw proc -ARG PalBuff:dword,NumColors:word,StartColor:word +;ARG PalBuff:dword,NumColors:word,StartColor:word push bp ; Set up stack frame mov bp,sp push di push si - les di,dword ptr [PalBuff] ; Point es:di to palette buffer + les di,dword ptr [bp+4] ; Point es:di to palette buffer - mov si,[StartColor] - mov cx,[NumColors] + mov si,[bp+10] + mov cx,[bp+8] ReadPalEntry: cld diff --git a/16/xlib/xpoint.asm b/16/xlib/xpoint.asm index f6bed961..7b7dc910 100755 --- a/16/xlib/xpoint.asm +++ b/16/xlib/xpoint.asm @@ -34,21 +34,21 @@ include xpoint.inc ; _x_put_pix proc - ARG X:word,Y:word,PgOfs:word,Color:word + ;ARG X:word,Y:word,PgOfs:word,Color:word push bp ;preserve caller's stack frame mov bp,sp ;point to local stack frame mov ax,[_ScrnLogicalByteWidth] - mul [Y] ;offset of pixel's scan line in page - mov bx,[X] + mul [BP+6] ;offset of pixel's scan line in page + mov bx,[BP+4] shr bx,1 ;X/4 = offset of pixel in scan line shr bx,1 ;X/4 = offset of pixel in scan line add bx,ax ;offset of pixel in page - add bx,[PgOfs] ;offset of pixel in display memory + add bx,[BP+8] ;offset of pixel in display memory mov ax,SCREEN_SEG mov es,ax ;point ES:BX to the pixel's address - mov cl,byte ptr [X] + mov cl,byte ptr [BP+4] and cl,011b ;CL = pixel's plane mov ax,0100h + MAP_MASK ;AL = index in SC of Map Mask reg shl ah,cl ;set only the bit for the pixel's @@ -56,7 +56,7 @@ _x_put_pix proc mov dx,SC_INDEX ;set the Map Mask to enable only the out dx,ax ; pixel's plane - mov al,byte ptr [Color] + mov al,byte ptr [BP+10] mov es:[bx],al ;draw the pixel in the desired color pop bp ;restore caller's stack frame @@ -74,21 +74,21 @@ _x_put_pix endp _x_get_pix proc - ARG x:word,y:word,PageBase:word + ;ARG x:word,y:word,PageBase:word push bp ;preserve caller's stack frame mov bp,sp ;point to local stack frame mov ax,[_ScrnLogicalByteWidth] - mul [Y] ;offset of pixel's scan line in page - mov bx,[X] + mul [bp+6] ;offset of pixel's scan line in page + mov bx,[bp+4] shr bx,1 shr bx,1 ;X/4 = offset of pixel in scan line add bx,ax ;offset of pixel in page - add bx,[PageBase] ;offset of pixel in display memory + add bx,[bp+8] ;offset of pixel in display memory mov ax,SCREEN_SEG mov es,ax ;point ES:BX to the pixel's address - mov ah,byte ptr [X] + mov ah,byte ptr [bp+4] and ah,011b ;AH = pixel's plane mov al,READ_MAP ;AL = index in GC of the Read Map reg mov dx,GC_INDEX ;set the Read Map to read the pixel's diff --git a/16/xw/default.fnt b/16/xw/default.fnt new file mode 100755 index 00000000..12eb22cb --- /dev/null +++ b/16/xw/default.fnt @@ -0,0 +1,260 @@ +; +; MODEX library default font +; Copyright (c) 1993-1994 by Alessandro Scotti +; + DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; #0 + DB 07Eh, 081h, 0A5h, 081h, 0A5h, 099h, 081h, 07Eh ; #1 + DB 07Eh, 0FFh, 0DBh, 0FFh, 0DBh, 0E7h, 0FFh, 07Eh ; #2 + DB 06Ch, 0FEh, 0FEh, 0FEh, 07Ch, 038h, 010h, 000h ; #3 + DB 010h, 038h, 07Ch, 0FEh, 07Ch, 038h, 010h, 000h ; #4 + DB 010h, 038h, 010h, 054h, 0FEh, 054h, 010h, 0FEh ; #5 + DB 010h, 038h, 07Ch, 0FEh, 0FEh, 07Ch, 010h, 0FEh ; #6 + DB 000h, 018h, 03Ch, 07Eh, 07Eh, 03Ch, 018h, 000h ; #7 + DB 0FFh, 0E7h, 0C3h, 081h, 081h, 0C3h, 0E7h, 0FFh ; #8 + DB 000h, 03Ch, 066h, 042h, 042h, 066h, 03Ch, 000h ; #9 + DB 0FFh, 0C3h, 099h, 0BDh, 0BDh, 099h, 0C3h, 0FFh ; #10 + DB 007h, 003h, 005h, 078h, 084h, 084h, 084h, 078h ; #11 + DB 07Ch, 082h, 082h, 082h, 07Ch, 010h, 038h, 010h ; #12 + DB 01Ch, 010h, 01Ch, 010h, 010h, 010h, 030h, 030h ; #13 + DB 03Eh, 022h, 03Eh, 022h, 022h, 026h, 066h, 060h ; #14 + DB 099h, 05Ah, 03Ch, 0E7h, 0E7h, 03Ch, 05Ah, 099h ; #15 + DB 000h, 010h, 030h, 070h, 0F0h, 070h, 030h, 010h ; #16 + DB 000h, 080h, 0C0h, 0E0h, 0F0h, 0E0h, 0C0h, 080h ; #17 + DB 010h, 038h, 054h, 010h, 010h, 054h, 038h, 010h ; #18 + DB 048h, 048h, 048h, 048h, 048h, 000h, 048h, 000h ; #19 + DB 07Eh, 092h, 092h, 072h, 012h, 012h, 012h, 000h ; #20 + DB 03Ch, 022h, 018h, 024h, 024h, 018h, 044h, 03Ch ; #21 + DB 000h, 000h, 000h, 000h, 000h, 03Eh, 03Eh, 000h ; #22 + DB 038h, 054h, 010h, 010h, 010h, 054h, 038h, 0FEh ; #23 + DB 000h, 010h, 038h, 054h, 010h, 010h, 010h, 000h ; #24 + DB 000h, 010h, 010h, 010h, 054h, 038h, 010h, 000h ; #25 + DB 000h, 008h, 004h, 0FEh, 004h, 008h, 000h, 000h ; #26 + DB 000h, 020h, 040h, 0FEh, 040h, 020h, 000h, 000h ; #27 + DB 000h, 000h, 080h, 080h, 080h, 0FCh, 000h, 000h ; #28 + DB 000h, 024h, 042h, 0FFh, 042h, 024h, 000h, 000h ; #29 + DB 000h, 000h, 010h, 038h, 07Ch, 0FEh, 000h, 000h ; #30 + DB 000h, 000h, 0FEh, 07Ch, 038h, 010h, 000h, 000h ; #31 + DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; + DB 010h, 010h, 010h, 010h, 010h, 000h, 010h, 000h ; ! + DB 000h, 024h, 024h, 000h, 000h, 000h, 000h, 000h ; " + DB 024h, 024h, 07Eh, 024h, 07Eh, 024h, 024h, 000h ; # + DB 038h, 054h, 050h, 038h, 014h, 054h, 038h, 010h ; $ + DB 000h, 002h, 044h, 008h, 010h, 020h, 042h, 000h ; % + DB 038h, 044h, 038h, 060h, 094h, 088h, 074h, 000h ; & + DB 020h, 020h, 040h, 000h, 000h, 000h, 000h, 000h ; ' + DB 010h, 020h, 040h, 040h, 040h, 020h, 010h, 000h ; ( + DB 040h, 020h, 010h, 010h, 010h, 020h, 040h, 000h ; ) + DB 000h, 024h, 018h, 07Eh, 018h, 024h, 000h, 000h ; * + DB 000h, 010h, 010h, 07Ch, 010h, 010h, 000h, 000h ; + + DB 000h, 000h, 000h, 000h, 000h, 010h, 010h, 020h ; , + DB 000h, 000h, 000h, 0FCh, 000h, 000h, 000h, 000h ; - + DB 000h, 000h, 000h, 000h, 000h, 000h, 010h, 000h ; . + DB 000h, 004h, 008h, 010h, 020h, 040h, 080h, 000h ; / + DB 07Ch, 0C6h, 08Ah, 092h, 0A2h, 0C6h, 07Ch, 000h ; 0 + DB 010h, 030h, 010h, 010h, 010h, 010h, 038h, 000h ; 1 + DB 078h, 084h, 004h, 018h, 060h, 080h, 0FCh, 000h ; 2 + DB 078h, 084h, 004h, 038h, 004h, 084h, 078h, 000h ; 3 + DB 01Ch, 024h, 044h, 084h, 0FEh, 004h, 00Eh, 000h ; 4 + DB 0FCh, 080h, 0F8h, 004h, 004h, 084h, 078h, 000h ; 5 + DB 078h, 084h, 080h, 0F8h, 084h, 084h, 078h, 000h ; 6 + DB 0FCh, 004h, 004h, 008h, 010h, 020h, 020h, 000h ; 7 + DB 078h, 084h, 084h, 078h, 084h, 084h, 078h, 000h ; 8 + DB 078h, 084h, 084h, 07Ch, 004h, 084h, 078h, 000h ; 9 + DB 000h, 000h, 010h, 000h, 000h, 000h, 010h, 000h ; : + DB 000h, 000h, 010h, 000h, 000h, 010h, 010h, 020h ; ; + DB 008h, 010h, 020h, 040h, 020h, 010h, 008h, 000h ; < + DB 000h, 000h, 0FCh, 000h, 000h, 0FCh, 000h, 000h ; = + DB 040h, 020h, 010h, 008h, 010h, 020h, 040h, 000h ; > + DB 078h, 084h, 004h, 008h, 010h, 000h, 010h, 000h ; ? + DB 07Ch, 082h, 0BAh, 0A6h, 0BEh, 080h, 07Ch, 000h ; @ + DB 078h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h ; A + DB 0F8h, 084h, 084h, 0F8h, 084h, 084h, 0F8h, 000h ; B + DB 078h, 084h, 080h, 080h, 080h, 084h, 078h, 000h ; C + DB 0F0h, 088h, 084h, 084h, 084h, 088h, 0F0h, 000h ; D + DB 0FCh, 080h, 080h, 0F0h, 080h, 080h, 0FCh, 000h ; E + DB 0FCh, 080h, 080h, 0F0h, 080h, 080h, 080h, 000h ; F + DB 078h, 084h, 080h, 09Ch, 084h, 084h, 078h, 000h ; G + DB 084h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h ; H + DB 038h, 010h, 010h, 010h, 010h, 010h, 038h, 000h ; I + DB 01Ch, 008h, 008h, 008h, 088h, 088h, 070h, 000h ; J + DB 084h, 088h, 090h, 0E0h, 090h, 088h, 084h, 000h ; K + DB 080h, 080h, 080h, 080h, 080h, 080h, 0FCh, 000h ; L + DB 0C6h, 0AAh, 092h, 082h, 082h, 082h, 082h, 000h ; M + DB 082h, 0C2h, 0A2h, 092h, 08Ah, 086h, 082h, 000h ; N + DB 078h, 084h, 084h, 084h, 084h, 084h, 078h, 000h ; O + DB 0F8h, 084h, 084h, 0F8h, 080h, 080h, 080h, 000h ; P + DB 078h, 084h, 084h, 084h, 094h, 088h, 076h, 000h ; Q + DB 0F8h, 084h, 084h, 0F8h, 090h, 088h, 084h, 000h ; R + DB 078h, 084h, 080h, 078h, 004h, 084h, 078h, 000h ; S + DB 0FEh, 010h, 010h, 010h, 010h, 010h, 010h, 000h ; T + DB 084h, 084h, 084h, 084h, 084h, 084h, 078h, 000h ; U + DB 084h, 084h, 084h, 084h, 084h, 048h, 030h, 000h ; V + DB 082h, 082h, 082h, 082h, 092h, 0AAh, 0C6h, 000h ; W + DB 082h, 044h, 028h, 010h, 028h, 044h, 082h, 000h ; X + DB 044h, 044h, 044h, 038h, 010h, 010h, 010h, 000h ; Y + DB 0FEh, 004h, 008h, 010h, 020h, 040h, 0FEh, 000h ; Z + DB 078h, 040h, 040h, 040h, 040h, 040h, 078h, 000h ; [ + DB 000h, 080h, 040h, 020h, 010h, 008h, 004h, 000h ; \ + DB 078h, 008h, 008h, 008h, 008h, 008h, 078h, 000h ; ] + DB 010h, 028h, 044h, 082h, 000h, 000h, 000h, 000h ; ^ + DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0FFh ; _ + DB 020h, 020h, 010h, 000h, 000h, 000h, 000h, 000h ; ` + DB 000h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; a + DB 000h, 040h, 040h, 078h, 044h, 044h, 078h, 000h ; b + DB 000h, 000h, 03Ch, 040h, 040h, 040h, 03Ch, 000h ; c + DB 000h, 004h, 004h, 03Ch, 044h, 044h, 03Ch, 000h ; d + DB 000h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; e + DB 000h, 00Ch, 010h, 03Ch, 010h, 010h, 010h, 000h ; f + DB 000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 038h ; g + DB 000h, 040h, 040h, 078h, 044h, 044h, 044h, 000h ; h + DB 000h, 010h, 000h, 010h, 010h, 010h, 010h, 000h ; i + DB 000h, 004h, 000h, 004h, 004h, 004h, 044h, 038h ; j + DB 000h, 040h, 040h, 050h, 060h, 050h, 048h, 000h ; k + DB 000h, 030h, 010h, 010h, 010h, 010h, 010h, 000h ; l + DB 000h, 000h, 068h, 054h, 054h, 044h, 044h, 000h ; m + DB 000h, 000h, 078h, 044h, 044h, 044h, 044h, 000h ; n + DB 000h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; o + DB 000h, 000h, 078h, 044h, 044h, 078h, 040h, 040h ; p + DB 000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 004h ; q + DB 000h, 000h, 05Ch, 060h, 040h, 040h, 040h, 000h ; r + DB 000h, 000h, 038h, 040h, 07Ch, 004h, 07Ch, 000h ; s + DB 000h, 010h, 038h, 010h, 010h, 010h, 018h, 000h ; t + DB 000h, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; u + DB 000h, 000h, 044h, 044h, 044h, 028h, 010h, 000h ; v + DB 000h, 000h, 044h, 044h, 054h, 054h, 06Ch, 000h ; w + DB 000h, 000h, 044h, 028h, 010h, 028h, 044h, 000h ; x + DB 000h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch ; y + DB 000h, 000h, 07Ch, 004h, 038h, 040h, 07Ch, 000h ; z + DB 000h, 008h, 010h, 010h, 030h, 010h, 010h, 008h ; { + DB 000h, 010h, 010h, 010h, 000h, 010h, 010h, 010h ; | + DB 000h, 020h, 010h, 010h, 018h, 010h, 010h, 020h ; } + DB 064h, 098h, 000h, 000h, 000h, 000h, 000h, 000h ; ~ + DB 000h, 010h, 028h, 044h, 082h, 082h, 0FEh, 000h ;  + DB 07Ch, 080h, 080h, 080h, 080h, 07Ch, 004h, 07Ch ; #128 + DB 000h, 028h, 000h, 044h, 044h, 044h, 038h, 000h ; #129 + DB 03Ch, 000h, 07Ch, 044h, 07Ch, 040h, 07Ch, 000h ; #130 + DB 07Eh, 081h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #131 + DB 024h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #132 + DB 078h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #133 + DB 018h, 018h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #134 + DB 000h, 000h, 078h, 080h, 080h, 078h, 008h, 038h ; #135 + DB 07Ch, 082h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #136 + DB 048h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #137 + DB 078h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #138 + DB 000h, 028h, 000h, 010h, 010h, 010h, 010h, 000h ; #139 + DB 010h, 028h, 000h, 010h, 010h, 010h, 010h, 000h ; #140 + DB 000h, 030h, 000h, 010h, 010h, 010h, 010h, 000h ; #141 + DB 048h, 000h, 078h, 084h, 0FCh, 084h, 084h, 000h ; #142 + DB 030h, 030h, 078h, 084h, 0FCh, 084h, 084h, 000h ; #143 + DB 038h, 000h, 0FCh, 080h, 0F0h, 080h, 0FCh, 000h ; #144 + DB 000h, 000h, 07Eh, 008h, 07Eh, 048h, 07Eh, 000h ; #145 + DB 07Eh, 090h, 090h, 0FCh, 090h, 090h, 09Eh, 000h ; #146 + DB 07Ch, 082h, 038h, 044h, 044h, 044h, 038h, 000h ; #147 + DB 028h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #148 + DB 070h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #149 + DB 038h, 044h, 000h, 044h, 044h, 044h, 038h, 000h ; #150 + DB 070h, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; #151 + DB 028h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch ; #152 + DB 048h, 000h, 078h, 084h, 084h, 084h, 078h, 000h ; #153 + DB 048h, 000h, 084h, 084h, 084h, 084h, 078h, 000h ; #154 + DB 000h, 010h, 038h, 040h, 040h, 040h, 038h, 010h ; #155 + DB 038h, 044h, 040h, 0E0h, 040h, 040h, 082h, 0FCh ; #156 + DB 044h, 07Ch, 010h, 07Ch, 010h, 07Ch, 010h, 000h ; #157 + DB 0F0h, 088h, 08Ah, 0F7h, 082h, 082h, 082h, 000h ; #158 + DB 00Ch, 012h, 010h, 018h, 030h, 010h, 090h, 060h ; #159 + DB 03Ch, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #160 + DB 000h, 018h, 000h, 010h, 010h, 010h, 010h, 000h ; #161 + DB 01Ch, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #162 + DB 01Ch, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; #163 + DB 07Ch, 000h, 078h, 044h, 044h, 044h, 044h, 000h ; #164 + DB 07Ch, 000h, 044h, 064h, 054h, 04Ch, 044h, 000h ; #165 + DB 018h, 024h, 024h, 01Eh, 000h, 03Eh, 000h, 000h ; #166 + DB 01Ch, 022h, 022h, 01Ch, 000h, 03Eh, 000h, 000h ; #167 + DB 010h, 000h, 010h, 020h, 040h, 042h, 03Ch, 000h ; #168 + DB 000h, 000h, 000h, 0FCh, 080h, 080h, 000h, 000h ; #169 + DB 000h, 000h, 000h, 0FCh, 004h, 004h, 000h, 000h ; #170 + DB 040h, 044h, 048h, 057h, 021h, 047h, 004h, 007h ; #171 + DB 040h, 044h, 048h, 052h, 026h, 04Ah, 01Fh, 002h ; #172 + DB 010h, 000h, 010h, 010h, 010h, 010h, 010h, 000h ; #173 + DB 000h, 024h, 048h, 090h, 048h, 024h, 000h, 000h ; #174 + DB 000h, 048h, 024h, 012h, 024h, 048h, 000h, 000h ; #175 + DB 022h, 088h, 022h, 088h, 022h, 088h, 022h, 088h ; #176 + DB 055h, 0AAh, 055h, 0AAh, 055h, 0AAh, 055h, 0AAh ; #177 + DB 0DBh, 077h, 0DBh, 0EEh, 0DBh, 077h, 0DBh, 0EEh ; #178 + DB 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h ; #179 + DB 018h, 018h, 018h, 018h, 0F8h, 018h, 018h, 018h ; #180 + DB 018h, 018h, 0F8h, 018h, 0F8h, 018h, 018h, 018h ; #181 + DB 036h, 036h, 036h, 036h, 0F6h, 036h, 036h, 036h ; #182 + DB 000h, 000h, 000h, 000h, 0FEh, 036h, 036h, 036h ; #183 + DB 000h, 000h, 0F8h, 018h, 0F8h, 018h, 018h, 018h ; #184 + DB 036h, 036h, 0F6h, 006h, 0F6h, 036h, 036h, 036h ; #185 + DB 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h ; #186 + DB 000h, 000h, 0FEh, 006h, 0F6h, 036h, 036h, 036h ; #187 + DB 036h, 036h, 0F6h, 006h, 0FEh, 000h, 000h, 000h ; #188 + DB 036h, 036h, 036h, 036h, 0FEh, 000h, 000h, 000h ; #189 + DB 018h, 018h, 0F8h, 018h, 0F8h, 000h, 000h, 000h ; #190 + DB 000h, 000h, 000h, 000h, 0F8h, 018h, 018h, 018h ; #191 + DB 018h, 018h, 018h, 018h, 01Fh, 000h, 000h, 000h ; #192 + DB 018h, 018h, 018h, 018h, 0FFh, 000h, 000h, 000h ; #193 + DB 000h, 000h, 000h, 000h, 0FFh, 018h, 018h, 018h ; #194 + DB 018h, 018h, 018h, 018h, 01Fh, 018h, 018h, 018h ; #195 + DB 000h, 000h, 000h, 000h, 0FFh, 000h, 000h, 000h ; #196 + DB 018h, 018h, 018h, 018h, 0FFh, 018h, 018h, 018h ; #197 + DB 018h, 018h, 01Fh, 018h, 01Fh, 018h, 018h, 018h ; #198 + DB 036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h ; #199 + DB 036h, 036h, 037h, 030h, 03Fh, 000h, 000h, 000h ; #200 + DB 000h, 000h, 03Fh, 030h, 037h, 036h, 036h, 036h ; #201 + DB 036h, 036h, 0F7h, 000h, 0FFh, 000h, 000h, 000h ; #202 + DB 000h, 000h, 0FFh, 000h, 0F7h, 036h, 036h, 036h ; #203 + DB 036h, 036h, 037h, 030h, 037h, 036h, 036h, 036h ; #204 + DB 000h, 000h, 0FFh, 000h, 0FFh, 000h, 000h, 000h ; #205 + DB 036h, 036h, 0F7h, 000h, 0F7h, 036h, 036h, 036h ; #206 + DB 018h, 018h, 0FFh, 000h, 0FFh, 000h, 000h, 000h ; #207 + DB 036h, 036h, 036h, 036h, 0FFh, 000h, 000h, 000h ; #208 + DB 000h, 000h, 0FFh, 000h, 0FFh, 018h, 018h, 018h ; #209 + DB 000h, 000h, 000h, 000h, 0FFh, 036h, 036h, 036h ; #210 + DB 036h, 036h, 036h, 036h, 03Fh, 000h, 000h, 000h ; #211 + DB 018h, 018h, 01Fh, 018h, 01Fh, 000h, 000h, 000h ; #212 + DB 000h, 000h, 01Fh, 018h, 01Fh, 018h, 018h, 018h ; #213 + DB 000h, 000h, 000h, 000h, 03Fh, 036h, 036h, 036h ; #214 + DB 036h, 036h, 036h, 036h, 0FFh, 036h, 036h, 036h ; #215 + DB 018h, 018h, 0FFh, 018h, 0FFh, 018h, 018h, 018h ; #216 + DB 018h, 018h, 018h, 018h, 0F8h, 000h, 000h, 000h ; #217 + DB 000h, 000h, 000h, 000h, 01Fh, 018h, 018h, 018h ; #218 + DB 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh ; #219 + DB 000h, 000h, 000h, 000h, 0FFh, 0FFh, 0FFh, 0FFh ; #220 + DB 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h ; #221 + DB 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh ; #222 + DB 0FFh, 0FFh, 0FFh, 0FFh, 000h, 000h, 000h, 000h ; #223 + DB 000h, 000h, 062h, 094h, 088h, 094h, 062h, 000h ; #224 + DB 000h, 0F0h, 088h, 0F0h, 088h, 088h, 0F0h, 080h ; #225 + DB 000h, 0F8h, 088h, 080h, 080h, 080h, 080h, 000h ; #226 + DB 000h, 0FCh, 048h, 048h, 048h, 048h, 048h, 000h ; #227 + DB 0FCh, 084h, 040h, 020h, 040h, 084h, 0FCh, 000h ; #228 + DB 03Ch, 040h, 038h, 044h, 044h, 044h, 038h, 000h ; #229 + DB 000h, 000h, 044h, 044h, 044h, 078h, 040h, 040h ; #230 + DB 000h, 036h, 048h, 008h, 008h, 008h, 008h, 000h ; #231 + DB 038h, 010h, 038h, 044h, 044h, 038h, 010h, 038h ; #232 + DB 078h, 084h, 084h, 0FCh, 084h, 084h, 078h, 000h ; #233 + DB 078h, 084h, 084h, 084h, 048h, 048h, 0CCh, 000h ; #234 + DB 078h, 004h, 038h, 044h, 044h, 044h, 038h, 000h ; #235 + DB 000h, 000h, 06Ch, 092h, 092h, 06Ch, 000h, 000h ; #236 + DB 000h, 000h, 03Ah, 044h, 05Ah, 022h, 05Ch, 000h ; #237 + DB 018h, 020h, 040h, 078h, 040h, 020h, 018h, 000h ; #238 + DB 078h, 084h, 084h, 084h, 084h, 084h, 084h, 000h ; #239 + DB 000h, 0FCh, 000h, 0FCh, 000h, 0FCh, 000h, 000h ; #240 + DB 020h, 020h, 0F8h, 020h, 020h, 000h, 0F8h, 000h ; #241 + DB 020h, 010h, 008h, 010h, 020h, 000h, 07Ch, 000h ; #242 + DB 008h, 010h, 020h, 010h, 008h, 000h, 07Ch, 000h ; #243 + DB 00Ch, 012h, 010h, 010h, 010h, 010h, 010h, 010h ; #244 + DB 010h, 010h, 010h, 010h, 010h, 010h, 090h, 060h ; #245 + DB 000h, 010h, 000h, 07Ch, 000h, 010h, 000h, 000h ; #246 + DB 000h, 032h, 04Ch, 000h, 032h, 04Ch, 000h, 000h ; #247 + DB 038h, 044h, 044h, 038h, 000h, 000h, 000h, 000h ; #248 + DB 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h ; #249 + DB 000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h ; #250 + DB 00Eh, 008h, 008h, 008h, 048h, 028h, 018h, 008h ; #251 + DB 038h, 024h, 024h, 024h, 024h, 000h, 000h, 000h ; #252 + DB 03Ch, 004h, 03Ch, 020h, 03Ch, 000h, 000h, 000h ; #253 + DB 000h, 000h, 03Ch, 03Ch, 03Ch, 03Ch, 000h, 000h ; #254 + DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; #255 diff --git a/16/xw/makefile b/16/xw/makefile new file mode 100755 index 00000000..96d1c081 --- /dev/null +++ b/16/xw/makefile @@ -0,0 +1,132 @@ +# +# MODEX library makefile (for Borland MAKE) +# Copyright (c) 1993,1994 by Alessandro Scotti +# +!ifdef __LINUX__ +REMOVECOMMAND=rm -f +COPYCOMMAND=cp -f +DIRSEP=/ +OBJ=o +!else +REMOVECOMMAND=del +COPYCOMMAND=copy /y +DIRSEP=\ +OBJ=obj +!endif +LIBINCS = modex.def + +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) + +# +# ASM compiler +# +ASMC =wasm +ASMO =-mh -0 + +# +# PAS compiler +# +#PASC = tpc +#PASO = /m -$D- -$L- -$S- + +# +# LIB maker, uses response file +# +LIBC = wlib + +# .asm.obj: +# $(ASMC) $(ASMO) $< + +mxbb.$(OBJ): mxbb.asm + $(ASMC) $(ASMO) mxbb.asm +mxcc.$(OBJ): mxcc.asm + $(ASMC) $(ASMO) mxcc.asm +mxcg.$(OBJ): mxcg.asm + $(ASMC) $(ASMO) mxcg.asm +mxcl.$(OBJ): mxcl.asm + $(ASMC) $(ASMO) mxcl.asm +mxcr.$(OBJ): mxcr.asm + $(ASMC) $(ASMO) mxcr.asm +mxfb.$(OBJ): mxfb.asm + $(ASMC) $(ASMO) mxfb.asm +mxfp.$(OBJ): mxfp.asm + $(ASMC) $(ASMO) mxfp.asm +mxgc.$(OBJ): mxgc.asm + $(ASMC) $(ASMO) mxgc.asm +mxgi.$(OBJ): mxgi.asm + $(ASMC) $(ASMO) mxgi.asm +mxgm.$(OBJ): mxgm.asm + $(ASMC) $(ASMO) mxgm.asm +mxgp.$(OBJ): mxgp.asm + $(ASMC) $(ASMO) mxgp.asm +mxgv.$(OBJ): mxgv.asm + $(ASMC) $(ASMO) mxgv.asm +mxhl.$(OBJ): mxhl.asm + $(ASMC) $(ASMO) mxhl.asm +mxit.$(OBJ): mxit.asm + $(ASMC) $(ASMO) mxit.asm +mxll.$(OBJ): mxll.asm + $(ASMC) $(ASMO) mxll.asm +mxln.$(OBJ): mxln.asm + $(ASMC) $(ASMO) mxln.asm +mxot.$(OBJ): mxot.asm + $(ASMC) $(ASMO) mxot.asm +mxpb.$(OBJ): mxpb.asm + $(ASMC) $(ASMO) mxpb.asm +mxpf.$(OBJ): mxpf.asm + $(ASMC) $(ASMO) mxpf.asm +mxpg.$(OBJ): mxpg.asm + $(ASMC) $(ASMO) mxpg.asm +mxpi.$(OBJ): mxpi.asm + $(ASMC) $(ASMO) mxpi.asm +mxpn.$(OBJ): mxpn.asm + $(ASMC) $(ASMO) mxpn.asm +mxpp.$(OBJ): mxpp.asm + $(ASMC) $(ASMO) mxpp.asm +mxra.$(OBJ): mxra.asm + $(ASMC) $(ASMO) mxra.asm +mxrp.$(OBJ): mxrp.asm + $(ASMC) $(ASMO) mxrp.asm +mxsa.$(OBJ): mxsa.asm + $(ASMC) $(ASMO) mxsa.asm +mxsc.$(OBJ): mxsc.asm + $(ASMC) $(ASMO) mxsc.asm +mxsi.$(OBJ): mxsi.asm + $(ASMC) $(ASMO) mxsi.asm +mxsl.$(OBJ): mxsl.asm + $(ASMC) $(ASMO) mxsl.asm +mxsm.$(OBJ): mxsm.asm + $(ASMC) $(ASMO) mxsm.asm +mxsp.$(OBJ): mxsp.asm + $(ASMC) $(ASMO) mxsp.asm +mxss.$(OBJ): mxss.asm + $(ASMC) $(ASMO) mxss.asm +mxtl.$(OBJ): mxtl.asm + $(ASMC) $(ASMO) mxtl.asm +mxvs.$(OBJ): mxvs.asm + $(ASMC) $(ASMO) mxvs.asm +mxwd.$(OBJ): mxwd.asm + $(ASMC) $(ASMO) mxwd.asm +mxwm.$(OBJ): mxwm.asm + $(ASMC) $(ASMO) mxwm.asm +mxwp.$(OBJ): mxwp.asm + $(ASMC) $(ASMO) mxwp.asm +mxwr.$(OBJ): mxwr.asm + $(ASMC) $(ASMO) mxwr.asm + +all: $(LIBOBJS) modex.lib +# modex.tpu modex.tpp + +#modex.tpu: $(LIBOBJS) modex.pas +# $(PASC) $(PASO) modex +# copy modex.tpu .. +# copy modex.pas .. + +#modex.tpp: $(LIBOBJS) modex.pas +# $(PASC) /cp $(PASO) modex +# copy modex.tpp .. + +modex.lib: modex.lbr $(LIBOBJS) + $(LIBC) modex.lib @modex.lbr + +$(LIBOBJS): modex.def diff --git a/16/xw/makefile.bcc b/16/xw/makefile.bcc new file mode 100755 index 00000000..d3ad8b71 --- /dev/null +++ b/16/xw/makefile.bcc @@ -0,0 +1,81 @@ +# +# MODEX library makefile (for Borland MAKE) +# Copyright (c) 1993,1994 by Alessandro Scotti +# +LIBINCS = MODEX.DEF + +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 + +# +# ASM compiler +# +ASMC = tasm +ASMO = /m5 /p + +# +# PAS compiler +# +PASC = tpc +PASO = /m -$D- -$L- -$S- + +# +# LIB maker, uses response file +# +LIBC = tlib + +.asm.obj: + $(ASMC) $(ASMO) $< + +target: modex.lib +# modex.tpu modex.tpp + +#modex.tpu: $(LIBOBJS) modex.pas +# $(PASC) $(PASO) modex +# copy modex.tpu .. +# copy modex.pas .. + +#modex.tpp: $(LIBOBJS) modex.pas +# $(PASC) /cp $(PASO) modex +# copy modex.tpp .. + +modex.lib: modex.lbr $(LIBOBJS) + $(LIBC) modex.lib @modex.lbr + +$(LIBOBJS): modex.def diff --git a/16/xw/modex.bak b/16/xw/modex.bak new file mode 100755 index 0000000000000000000000000000000000000000..560a1c68304c56844f41325820f296a21192ac4e GIT binary patch literal 25600 zcmd^n4M0>?+W)!t4#S9uBPvmnf|;vPq*8`L%I5$r3hK<@51prFEB zGqw+_ec4?NYkSR#cH7PDV^IchwOX;=v~1JFbOu}?bper>|L-~X-eFMdeX;-h{~UPk zJ?GqWo_ju?^PJ~A&vS0qD8?2s=Eu}uSpYL+<|igb-M{LmpHvzctJP7IRfZ!&n5B5- z(nrD*R;_yIr%RVVv@$&0`q0W%4?nUZ{I;l>&sQ2*ynA}afn+a&36*1zG{$@&c|>Mb za!P(wa*8RlQbJnB7Ll=K6x{aomLTSznZMYQl5f!^A=^Kn^JmL`D~OViyJ;>PpSvJ2 zEh{H|QI^?~kdcvYPDwYLve;;pu%;)cWaXx$W~P`eJRxzRB_%gIC5LjcXRAjuCQx0{ zEr}TxRR3(Hj>W$q{BmopATYK-K2v@sWTI7{S8fkvMc2qC;}l7@8p=*c?;K@w_ZCa< zL^IFF(e;b{3ns~5-M2rG$pr@4q?gTsF2*WNXDSQZs?32=+Zfw?WOKc23X1BP%9vbY zZ0Ts}kh*q%B<=D`=$b)rp;yJ54qRSo5|^T~cp)aqr>+Q>t7Lxc+F- z4al-f9L@7YHpo_Fk`J8Y`R*$I*Wv={oOIDq*al=FLy>8y_#5Lp8&E^})0Xy@_OdUf zI>RB?`+8QjsP~|&{9|S|uQ~s%HLfb@M*Eaj*bOb6EuB(tmHj;LnMzZaY&HV%*d-N99#i*0Q%AY=Ji4x1wx1s`pDq56hT57~<_xn4&KoR3#hrRVaNeaC zM5k3RNY2%Csi8|FUHb8$(ST567+rpZOPvGsRfI8D=s78g==pCNJtrj%m!1^_*Iqq6 zZ}0;>FWaOL?hrb?jFLxyw39N@v-4*%Ex2$nm_KVUbrx%_9t$E5%*Q05B1HHXb?na? zp?@lY&;wXJz{*Cj<;>%uco|>|;yZa<&+3_;eFPrxIge8wUpT`$*w?I$oo78vC$zCK z!Z;y9n1#^ofLK5pU@>61uu*W}-o~nhU-SE$!XDvs;h50PWAvnrN#Y1GT#OY_4xs%l zMz}%w>P zE6M!_$?cL{zm%e4XEV0uwEL*!+NwrAbAKecUzc1(O5DER{et8wS0nGapOH9@Q=+R? zbT5}&{}7{MCo*PpyPuU@2i3^uE(Zz(F=qdpJ56%Ett6K=y7MI0PBpU2b(fl_&OL=! z&HbwA+9A3ximvS{o_2Sl^OLQ}HyrMai{FjqG;)3n9FC&1>#I zh}2$pwdi^rY4cFWuU)@Ih+6!W+bz0El;qOS+}lOh!=ih)=z2iS+3YG-a@yZ<*NUzT zHD{gc=W6nH_a=_s^$&r!f6ZC<4@B3!%2V5E*L6yXHAmg=3asg8Mze6{S9J zaovj$bz!snCBb!#nsc}7el__u_Y)kc%gK0~>}TC)nJYHxn7yb1UdU>9IF;9bD`fO^1QfD_OJ*az4T z_yF(`;2_`-;BSCW07n3y0X_$O0XPmg0XPXb1^7lU=o$m)a-Ck#H~xSw2^2NcC0{T2 zH9kaXE9qjR=oWfVOP5z^dD=}6n(5L)(XZ&zNl&qi`8AD3wCP$rZJJ8a85AP)O@zJ) z=%ps0mzo}-3()JEHqe8|DfAl(y+WZsQrW$9`GC?srAsS4Xrs${M4M^7Y#xs+&C@6} zi_+#(G@U|=kgpjFslNH&=&7A9l@xu3p8l3XFVUrrqI)Rx5iX{!e-wnjgN^a&+rH2> z0E)#7C~a|NsD#|uzS#A&O2_ZGW-F<-Hx#m$Tpz00e$yT!H$^r?$svqI9`0$A-I1L= z-$+NIWT5VC_|9j0BAbLul=ZuQ8FTw93K^{S5SmgD#Da%ln2UBk6wGKi;*N675grRAT&yTQ)Dftr5+i* zaofgEJcs0F`IGw^?z_;CTeF=xB@Dh3Hs&e?Q{r)Va~z*#_-hbiCB z>9U?4fW-CAZIti#ba{`mfFL9%D9_IcqVse93t1ZVbQyyzjg#qeGeu)4l!z=egCv?k zdYVDHMv%B)<1Z);{GsuAi!fai>LAx?zcRjGNlGR8?x0t`OC7d+#}SObdiicHgM9aP z^*BglqcZc8vNE!AELo{J2@6qCizbfEV-UyqzJt-eLpJMMBN|HropwY2JI`kB>^?0Y z+}YhK9o+e5SocY3ufzGujuUQe`w_t2`}X!{Q2P&f+n+J)_HzWrt8f1iYX5})2KiRq z#3iNYBxR(aGX+RQQ2f2piP=|1iPwT zqHyRW-#wZ1mHrKXteM1|6KKP;m8Q|}Xa>E8N#O)%*E`?EcIcl9F{t#PL*w7*9sitR zk3UBcaP{MVnD*-vHjQCHw0prWUfY-7pzKi84N7`uLTXB+z+SHg=M%8?NlmfP#w8~u zH9gDxC3vRxAlLW7R>p3rHll>KA)P|K#)Xc=P(T9R6qYZ5TjWYKN!nN8o=Y+V; z$mEH^Ob!~y z7PXZk2UO<4u}0U|8dxnbm<(yPKw{FT)dsO$jAaM8$~?TBZb&s`Q(!G>VhX55T}%ea z6qr_v8kzK<)wJ3WhF8Q1#eOKB;EAs12n;F$eO?qA;j{-&t@4Z77K~634~=6{k$UKT zob~`7521K4#q|{Dm0s*m+7lzgdMD2lS#0x~agn`|hwXP^-u3l-DR;?-qqd=i@;p5r zmPV&W_C@xt5v9X?v5!5rW>ngXOZUx*1Fah!a_X1V| zAYC`E2LNZ|OMq7_!V^PQ357qHxIXWY#ve?>*5@e*uDN>t;Gy;5{3g@odb-Q>A3pQ) z+q8chw3%s2&&a_1y%8HnZT3l|+;bdeot)@_x+|G`9&0b2L`hh}?ketDEZGAch5bHSze~`N)=y%czKY8Hnp;^#99E8sR9ZAF zw2%~lq#gjQ1#AF3N3_^Pmt(m6PNf=^Ub1ODaeC<`d${X~i6aQY@B~IgH({4fV@3)Jcy#`m>b}|7clJ__PP6htHfdXVxva+!mgYV@b~qUlp}7 zYI#(6!t&+eJkzT1l@G0YXl2Pm4@P15*PaQ`Tk|IBn>X}c5HOy`8=0rb@P^@IR~1qy zKEU1(K6Z_)FP3)AU{xEsFT_`F=)2Igq5p!=v|-=^$^_lXgq4!}O$L67V2N=T6CzDP zRi;2H<*vbq2g-X|j!XMC9o$_1`1|Y|BDF3gG&Pn4OI`h%X0*p-6j)KXjF(gbHNC@w zB2X=Bg`jxe&K&lDveWY&1%|TL`Hm8O*{S)CEdv*njNtI{=I#rR|A~ErGJUS;EH?*{ zK6+yT9`#;u-N_c+BW~%xFtEArLh)byCoL{exO4vk*|qbg=I*xc3u5z*oi{b`Py<3u zJk+!!v-sG34UXfxKa=j8*t_el>OB;z#=wIY5y@NMwfuk*yKetzP*O!n$k< zR@&595_G0g*H{w3uXUzBF5rsT{%RtDir+seN-c&18YT zlGlI1Y-0226E3ZxPnK(a^1ioEj0)Qfgfs!OfNa$(Y_l3{Q!kXLmXLFbAp~XxF0hof zN|gm?hgc^549mnlie(}zYt4BW6}rf%u-RmE6rSa#h552QNHZtsVIZ*P!I-eUyje;w zz5tVm-4G>Vt9@7TX;>7T-A-MR9`=N?ldviT4Vb%%-|=OObv5Hz#Wlq8en3+79mE!& zL@3uwo~pedHIv4#$vb|T!yZ45VC2=0-y<}B71iS*Z9<|>O~}klNXp8|NlCKA`xvrT z(Ri?cpfO{|UlV%Wgs|%;g-1-jVakm+PW{2O>CU0ndFQ-&^XCuUkcKE5(svl^m-k42k@oG3I=tgV-{3Cvjv7Bk zn!+w$dgtuE!P{TMUN2HP0>jn!*EH&{1Ik{5&u4YHK=-_>QSZ%O>Sg*oNUYd@Lkzxz zS1Hn}f$0>QQ0KFi=;1wY`>eyJ2aZ6z`u6FleVsn-v!>+aV#|c~y{NU%K<(Q#O*rt% zrSzP}xA$IpP8+spg^=% z@)uQW7r|IW`(tOKVi*6VQc?mOq8%Zt_MW_D<1%X%CV=J8B7xbC=mXw^# zrx-h<#na8{mOB|UY5c->2Oi7VF>O;l#AFUhs$A>bUs0cO8-4ilhnKFrf921@Zwdca z$!hsSt5)5=;=z@Vgy%l+NKw(lY^$o)($lKYY#Q)*noa#|>n3yGt_>j{-U>nJ+Fb!` z(}53XuAE$D>f0rh>pe%?*v^MXp>LmU$tH6b=5DF0*mzn6f-rHa1;nH&kN8oq${q-vt zb%nhD27RGAL&y?tU~Hq-%fAuP%X@_$;b!pxk*|2c&>BL*mkYFg-&3^jD`)c8TOym* z=r?}7@w1*Iq)H?cfV?-dVU4cmQ%dQtGM|?l6b0T#iiE=zcw-KotSs!nP^g0!eH2O@ zYz~8`NJF=WNlBn^+1wwyXO)lyR^@pXbZpnNB7clN?H|3GL}+z-<+HQu6*GVss2CLO zVj!%dkb2gLfv^@JfD{89G$`Xdo{WqLC>gPhR5Bua7#ud4jzVdOe{sEWK##L1+0VtW&c0*}9~X z^O5%6c2|RZ0fmsekG5ebg#0MQomG@V$Vny6DTUQS-|;3#+$HboP~UaxJKv=iQ{VRW z;M-0$+)z`=oD2+31n2-z{5WA55u90c`7ueVuz--}mpi@qk$FYuJWSf)uPCj9G{ik* zHeqByp}l`&5?x@k@oR(vz_0NEda#_bz;L5$TuYaYl(v~JzoyKv>G^dIVHnE#m&Mn= zw={l{HSG0ILC}9ielb>c8ygAlu!IE}mMD|i^5lQbOKkrLaFOs$*I%Y}4#>>UUSLu7 zFM%2ZhGv(X%yKO$*)NZPf0$~lfht!^t{TC1XsV^G1z^<)IUg8Uv$m|NIk|P`6$4Aw zvLf9C_q0$0TcIVPG$G9#!6s@f$VJXL+RwiB#kDU!zt(Q|9Q7PM?XfQ(7#Og{7@0A~ zrrwQ~0gG{f;sZA001J(?+v7r+=XAr`wGF2|EUqvyu`rH#8lHdez2_S|{*vG7ii(QW zwsq^)*^Dv9F#H*fGiJ=2Ja6*ksfA0PUle!xbljrnnQ_LWU60N%va9Y z(Gp`!qaRCS_9vfQ85|tU;wFbqnG%{D$Ll+99;0l?H-HLKh%p|;-Jl!Lfzh(?_<{Iv z%3W4g){oniL{H)ric<^d&YML6{zGwKLHQ{>6K;0=O~HGzW5%IAOiVTy!xLFda?Fya zD~nioc)U_BJU%`?92)0vl&7>Qq4rQhVKmyPTKtD6xKl0EA0Fs{F20P}njBBQ&}2h5 zPz7Sx>Iz-x5>y!X7+u9`7B(fhVn7$f`pbHC6klCY){Aas{W?Mrj(7$A)7_@S9WNdP zyqDe*Zln&u>+w$!sweOpsJ*szyI*?0%tqz=FJr zaxbIjHS}IQ<>g|i`lx@H!C*#&> zt>*7T1|EO9vV_N}9PqEE_6%^mMtTp=&u?in7$JLdM-y9@Jk2;Qc^ykmPNpg_3_hAS zz*b{e;^WaDWz=FFTa9`d467N>td0V1o^Xtv@{7^MCEL(J@vD=QsUPD|K8`URk~!JM zB-UOFr@}q<q{mSKn+_#04=~$|7 zuI{g{{td`e>85GGN6mj!y~iXg^?a0WNaxi?^9e7JRT?Ll)zp3H%@|`$a{Tf5_;vls zHcU&K5oGP?A#w~1HiphHRxgQD+r>ha`h}_Q2~+W7g3ybYjU_*5$w+2kMiUu?kFd#; z!|0CD506ibqaMW!p&P>t1vMq7rp!0LxH823gf5X z4Go=yFuelqmi*_T2!4|QltAeeSJEf(bi#KBU1r}gV?Hl6e})q8;rXdlkNTX_DNcB1 z&+g&r^fo0vdp6zqbM1Y+-0azemufMIKUdyM!TIWQ5AIYet-e~jsNNp+NBJq(rT#{% zKT4x#j4ge-^68}vgwa)5*;U4RD``ex6qSXjzal<7zM>yYL7TRq2Aa0B(}=GyqA)O^ z7*HR`nzQ4Iw6qV{YMqvU`IAr5Y-Mwk7frsGg@(tkjt>vz)Cz(n)=Ym`R(iqIdofMH z#z1YjVh-DgPJMpWONes=7@L(r|3s}Zgk9dM7lnQP2q|Mm0YDJym^Llc5Hkfo#N%{v z;hb1m9DYdf{tS%P3a}6UM}0$aRVBx@rqJoHuP=^=qV-OJtrVl{$>~5oB5!1dTD@Tt zUgg**8fKlW4KUP>GdP}=470kcLIMpvCu)Nz1!m$9L;IXv9uM5t%P$%qi-NYcyf6H* zsZ|pL43txD@bhOaF8bqz$U>}#r+Z+n0i}o7fhVd}GSnK$6}~oD%fKzoYtM-A#el82 zakk!o&Cjfp*d+xSq%PI+fxT3S(GayQ&``Bu;2UhL0t}8gQ~3o$iR1_~Irg@+t`r?j zQ!D*a(~H0MY##Wg_~_#sFr%_PB>|oiLzHKB09^v<5^M-^F*c~()oYz*Z7k6{bQSeQ z;U-T>AWFiXz0?!6ZJa?c!C5~9w*Zd&v*>!wUt@?}9XdgD8?`RPFw}}}B`nbWSLp~3 z-czM&{|)RHHQSgo1`_%_i?A;qcX-eV&SC^s18e}8YMn6EatBCqeuPsKHwBZk<8J}v zxcDxB923bLOpb{EBqZk$xB%O3Fdz&N2_Sng-q!dqUFT zwjgjA&;|e&+Yrf~s1D0D_n*q<_Thb+e4jmR`>=vwROOhfJ@3K7A<2KNiR6oOlM>8{ z3rwaIGRgczm7uRseXaf`(r0+>mD#4@>NB!Ag70Cke2MfKKist9atq6)4l!i!9&!M{ z>(esm3s3Y}nO(TAqW*SEB`v`Syd{;{UE zH6yA_ZB^E@Ro1Rp(lo~k`%eN|1)qLFHl5HiynqZYEyFWPhRuSw$ z#O^JPjNNY!s}kaY*L{F-~1^B@!w&VN7`;ryDE83TI3zY)rLu`yIH7)XU-Xso6S zG!?qWw@7F4AwB&&={DfP;NN%wm!@%uHbsN`HQfV^MiaR&@AF|CD!=3Io?d%Z_OSg$ zvpItAVXt~l0>8-rU(YX8okwccf}Df}$;2{l6$VulHKd}@SVrF6**RBW8-{OT8;0*> z8wQna+>^g>G3INqZKk8O4*VuXEN=$J?)Jo?tfn$Wnp#;*4;8c>?Gcx9qrof+?vDE! zNK@W)DfIWwyHaJdUgK1!cM%YpR=d!`n#7o%Vm%eQ9ZwieHw4UTIm9Cs-jG!C-Cahwf;{ShCOnLGxJ4h-?M#tr}R%^){y+68|_l^X&Dal>(5 zZuo5|`dq&P3XLf?U4bc%_F;-xF|NQCPyVND@nOyu4OvA?%9{+t7Ihk1Ob1)MzRIFg z+2UMKd1SJ_r@iNb00J7!x!*Pkylw)x9JK(-YlpB;<=7;oa@V|XyiC$SOcM4l&G2qyH`YAFoH)-RIlD+#dp%vY z6EA#&cwr;4!9&Cb-NY5ofKxWXec#Zuk}jpl*Yxkm*M!Vs)7!)(8;D(k-}*QEBiejB zcqSeBkhc1;OHIDw?kIb_^5L-kS+Y3-{ng8dkCQ*xL*K`rMbihr$k=O|i1bTxAPZzu zSPCm-8`*O(3$F~^Ufv`Tq!<6If$psr+Rq?;j6>&mP&YNgFEthPlwRD`uybm-AHq`W zzuH>|GmP-fV7NktnZ6ljcr!S3b77L9%@0;cLhsN`WoqQSB5aLQoNj{1%?oaXRs(iG zkhY zj>0sBT_&bC`Q`A#zMBhzxl>LiWF;JH_C4|ommAGZ#~|AkHyv16Jl6B@(kTgulID?@ zj*FlBJ!m>pZtZ3slabE)zB)+cL9C%>CcDfKV!#e40LOsI?_HSzpA(Hw#I|M`2zI>> z!K&*!H&4FnrPpEGH?uhc;p*u%j_kp2fnFi8=Ov_DlGAguGjJLNyMbH_ToV(LlXFsX zb1!#?uvQ1c#_tFFMFKf@e5R3VJei3Vy#NVX{G_?n(9+h@Chg7s6>a7Cg}n22*GqNL z9dIZm!(&HuJvsR4*uQ+_+X+{9PsHjD$jpv|8aMm-QNBiwm(lcN8q{o z{(Fu3FXg|%KCEt-zzwp~^HVacjD4YPqF^85Y3PVdt=oS;*zFUo=t^iI$lz+5%WtL8 zm@a99SR6V$dBZ= z(kUDdA959oIpESGBRWl)p=bBh+{v6q47Bqa@O5VdiPbpcr+3C;(l~L_3WquA=}+is zF+H`>({g%>Gk(GzU%F7}At!Lj z)r7&Z+Wj}FZmgqF4^ui(zsQo+Myc)L4oC3K)wkzo)SjPfemOZ=mIPQO z6%S{SU$fSvHENUAo?(*0{0-7kseqJFA^zkR+z)0TA6#Ewly198s+SH%ekPr>%KOi4 z-;6b4AgjPEANc0n_K->B5=<^{`}@yrZ@->$_Iwuk8D*qYd}Tt(LJ6A0VPJ=SDZ!UN zV#8U|{A(XN*Cz*0yPbZ6p8WK)7LdBsxq1 z#P|XF4o$gP>DxlJeOw%SU!(urVas#59D#K8^uLefxtliK%6w0ITy_-XGF@5U;E3m- zPtv%B9}DILtyexEiS9NbLwHcI2~P`k0$(z@;1qp`yTJ$aoP(zeG+wx!r?f!m#VK-D zN$Zjeg2^w)N5CQ#OaNr8=>@^lO_z#UIBTehS$&QJnj~d1Vor{ekMtCF$@}Gop2D-z zo}R)W!88u8?Atml5seo;=KWq|dl=x+>oK;%cLJe5FXbzUk__w|ti{_(NLA?x%$eIv$Z! z=KLElKl7z_O~0MX{R7|e()+Oe0~G}9>gjzp&FA;7?EeZcS7D?o7n0u^W_gcB&vOT7 zxhD2KrJcaIgr6zNMHjUt??1=|5CWgD!KX{q`On?cz4Be|u>IR}IfCyY-`z&~uXi`i zW>+{%`Je01Kh_pbh-|q@IVmaT-1J2$!4mtU_F#yL9VWGxy$_W9X({QcX%>+&ug^G~ zeaxvTwyBE-k6u3Y)QjV8LHLsLtPT^^{FIFmpI6e zW=I0w&PK$KW7o9eo}k?ExtuI9TUw{H_?3;Fh73Ou7K)3c&AI|V$JkpK)Bo9jlCgZu z`r!MJ}5n_TjuwSeuID4 zh$W+E8t)nNcyQj>S>xFFB_U<>_6PL%$WOemk6p*^VyHEXmRbc6SiI1Mq(y2Has?o% zTA*A3S}qYu$C0#1P5RLUHjXU=uA5X`N5s=3V7y!gTsNt>j)=%L4N27kmk~+F zk)+@{BI4{TO!va;sKi{g5<`-dO8ky;DFu~WN5mmXDtdv5`20}5_+#XLLYyX4<7jQH z@F(^cW)?nYo$P)=6vhih0(>n$G&bu&0<2k2W2Ee{`N@1ma4*r94~#02+|_J-cd_2} zp~t;}nV}JTvs~!6?i!2Y1<-u&(&;;KH&<~SaD|e)mo9sUm%ZsM^e)I?jpmhSP;&2w)c9-UVjJKH3<(61=7kA?RgukF9BVEvw-th5F~&fz#k9-2nAdRm<}K_>Mejc0F1VcFxoa|0dRP?F&D5D z@F1WN06T6Y+|L`=07?OHLvJhx(9zqCfGU6tcpUHq0QGM~{TpilF96=eGS!GL%`^^J zgeJInHo?8K2`7u2#sF}Vc*6{^=_cBrHCd4IQ)F*~y}0Rj09bRIUI+XE@HyaL0HA5U z1`uu$`h1u>h`5Z~b94Fj#Otq_JM8_9g5b*jn*XKm_f4nuZojr)0~a0K+|+4n+bx4@ z+eD%W^*j#Au|9_hH8D1fH&kt3F6~F(^seW*!`+YOas(Hyemzg6_U+W{)zIyvs|yjv z;6AN^KOAfz7Vnnhj(*4IYg+~J4c*7B2Tx-j;lOZcXPrMd#a)i$WhXlWTI>8f>qcnt zKL?zy8_}ukQ;sR)thC?4-Sk|zp&|s%h&45WcHET!fDA#Fy}(? zVoA?PDaPRwZH-lv&~py0=eh@bj&FPMF%7QqvIi;$eYnhxvzRR_4ET4L1ECLj6At*z zrT`tjBmgEDSzu7~>Q#1}>c&SK4ca+d=^{>5%l1I{Ums>92Ol1kg9CkdDcoSb|4Ung zxGxInbxrVUIZH2h`M&(GzAx{h&wfC4BRVINbjuYs_`r_ne2SuV2&E03?&^HEa&mq{ zn-A7u&j$rT_tnpbQlf{VP01`UGv7x$^KH`I5C@1$JtP8rKC)p=&#^2>$WTNs9b@~n zXOOmrJcH-M8jX5Nnc!8g@fC5Gz}DIg@xscv*}HXc8tN%A%rWWnAB%*l?Z#e@wlvcU zt>{uQU9m{R=g3o{=XzDu56X)cu0V`|XOSzAhyYxHG!2}A4b!51N6{?Rb|VK)en)%wcHvLn_6&Q!k;f5Sy!!S`p!OWmMD@I!bPE^t(c|A}t(i2) zbD+F+6zZ|7F8d(9&QImQmhWgEUvK~5ZQroh+dPh-_v+g>gWA`iwJ#?nAsOZda|)ah zM`(*MZ!}LutG$cxZG)}mO;$hRsw_H+xJD{%>I_n8E9pP=c7?JYfx|I|YNpWN?}A6SRg(w24uW7pwG zDE*@OwJ4W8%*M|DclOH{@fBs|16-fu{H-+PlLGxn8RvCjo5iEvFVyDGRN^parDjIF zA&dZG3TH<+1=_A*u>c=eMMEc;NzkP#z_WtL0tlaapk}Fvlh6#ud#D^4a0H#iB7ieD zAtFh4EpP$@o(*aRev1quVNkd7N}Nh$M|`7$q(HS86i~mxB4fZ)OGd;5zi>Ro>f|f9 zOz>k&RE>HniBGFOc3tp#-i5eg=zv07lFAV+n77rpDvIG#!xUq=b?4IfokvY8p=znPHBYB;r$Z z40%ZfHwnIzlNG9?LtqNkAzyZS#9j$LR8%J09Pv*HA84R(PC~?F-8E`BJK|Oyd4Z!> zh8T8k)sb$3TYv|Z*Nb%`3nr@f)k`Tf3Y{SON6{&HsWvY;Vxiw;Ua`YlU9UF~$ zdjOpjajdU76QMu{5saL^e5~o^qS8nc#hS1JR^Fb53}5jUNQoI zZhFLG-2^?W!BjO7IR-146yw?{XrZAd` z^qB)bYcJU$XfxTz6*^qfu`yJiY*WO|66rQUJ(^ea&5{I-DJXK#>+uof52rkuThLy( zJ_b?w1oJ-;4CA=6BLrQDQs>;vh~Mh2N0{p3qXFjhhH|;N5hMNR$PBoKx}oJu1>v#g zM#T9=;2G-RBT6sCxnUzI7c`mBO*}58GI^}Wrr1>yg*e*Xh>)L^y% literal 0 HcmV?d00001 diff --git a/16/xw/modex.def b/16/xw/modex.def new file mode 100755 index 00000000..7977a4a0 --- /dev/null +++ b/16/xw/modex.def @@ -0,0 +1,163 @@ +;------------------------------------------------------------ +; +; MODEX.DEF - Include file +; Copyright (c) 1993-1994 by Alessandro Scotti +; +;JUMPS +;LOCALS + +TRUE EQU 1 ; Boolean constants +FALSE EQU 0 + +USE286 = FALSE ; TRUE enables 80286 instructions +USE386 = FALSE ; TRUE enables 80386 (and 80286) instructions + +IF USE286 EQ TRUE + P286 +ENDIF + +IF USE386 EQ TRUE + P386 + USE286 = TRUE +ENDIF + +MXVERSION EQU 0128h ; Library version (1.40) + +;------------------------------------------------------------ +; +; VGA definitions +; +MISC EQU 3C2h ; Miscellaneous output +TS EQU 3C4h ; Timing Sequencer index register +GDC EQU 3CEh ; Graphics Data Controller index register +CRTC EQU 3D4h ; CRTC index register +STATUS EQU 3DAh ; Input Status register one + +;------------------------------------------------------------ +; +; Raster operators +; +OP_SET EQU 0 +OP_MOVE EQU 0 ; Same as OP_SET +OP_AND EQU 1 +OP_OR EQU 2 +OP_XOR EQU 3 +OP_TRANS EQU 4 +OP_ADD EQU 5 ; Must be last op + +;------------------------------------------------------------ +; +; Polygon fill functions +; +POLYSCANBUFSIZE EQU 4*1024 + +;------------------------------------------------------------ +; Macro to push registers, variables or flags onto the stack +; Usage: .push "loc16"[,"loc16"...] +; where "loc16" is a 16-bit register, a word-sized variable or the +; keyword "FLAGS". +; Exmpl: .push ax, flags, var1 +; .pop ax, flags, var1 +; +.push MACRO r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10 + IFNB + .ERROR <.PUSH has more than 10 arguments> + ENDIF + IRP $reg, + IFB <$reg> ;; Is argument blank? + EXITM ;; Yes, exit + ELSEIFIDNI <$reg>, ;; Is argument the keyword "FLAGS"? + pushf ;; Yes, push flags + ELSE + push $reg ;; Push argument + ENDIF + ENDM +ENDM + +;------------------------------------------------------------ +; Macro to pop registers, variables or flags from the stack +; Usage: .pop "loc16"[,"loc16"...] +; where "loc16" is a 16-bit register, a word-sized variable or the +; keyword "FLAGS". +; Exmpl: .push ax, flags, var1 +; .pop ax, flags, var1 +; +.pop MACRO r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10 + IFNB + .ERROR <.POP has more than 10 arguments> + ENDIF + IRP $reg, + IFNB <$reg> ;; Is argument non-blank? + IFIDNI <$reg>, ;; Yes, is it the keyword "FLAGS"? + popf ;; Yes, pop flags + ELSE + pop $reg ;; Pop argument + ENDIF + ENDIF + ENDM +ENDM + +;------------------------------------------------------------ +; +.enter MACRO localsize + IF USE286 EQ TRUE + enter localsize, 0 + ELSE + push bp + mov bp, sp + sub sp, localsize + ENDIF +ENDM + +;------------------------------------------------------------ +; +;.leave MACRO argsize +; IF USE286 EQ TRUE +; leave +; ELSE +; mov sp, bp +; pop bp +; ENDIF +; IFNB +; ret argsize +; ELSE +; ret +; ENDIF +;ENDM + +;------------------------------------------------------------ +; +;.shr MACRO arg, count +; IF USE286 EQ TRUE +; shr arg, count +; ELSE +; $temp = count +; WHILE $temp GT 0 +; shr arg, 1 +; $temp = $temp-1 +; ENDM +; ENDIF +;ENDM + +;------------------------------------------------------------ +; +;.shl MACRO arg, count +; IF USE286 EQ TRUE +; shl arg, count +; ELSE +; $temp = count +; WHILE $temp GT 0 +; shl arg, 1 +; $temp = $temp-1 +; ENDM +; ENDIF +;ENDM + +;------------------------------------------------------------ +; +;.chk386 MACRO name, jump +; IF USE386 EQ FALSE +; .OUT "Warning: ", , " needs a 386 or better to run!" +; jmp @@jump +; ENDIF +;ENDM diff --git a/16/xw/modex.h b/16/xw/modex.h new file mode 100755 index 00000000..2c1f1ebe --- /dev/null +++ b/16/xw/modex.h @@ -0,0 +1,153 @@ +/* + MODEX.H - C/C++ include file for the MODEX library + Copyright (c) 1994 Alessandro Scotti +*/ + +#ifndef _MODEX_H_ // Avoid nested inclusions +#define _MODEX_H_ + +// +// Video modes +// +#define MX_TEXT 0 // 80x25 text +#define MX_320x175 1 // 320x175x256 +#define MX_320x200 2 // 320x200x256, 4 pages, aspect 6:5 +#define MX_320x240 3 // 320x240x256, 3 pages, aspect 1:1 +#define MX_320x350 4 // 320x350x256 +#define MX_320x400 5 // 320x400x256, 2 pages +#define MX_320x480 6 // 320x480x256, 1 page +#define MX_360x175 7 // 360x175x256 +#define MX_360x200 8 // 360x200x256, 3 pages +#define MX_360x240 9 // 360x240x256, 2 pages +#define MX_360x350 10 // 360x350x256 +#define MX_360x400 11 // 360x400x256, 1 page +#define MX_360x480 12 // 360x480x256, 1 page +#define MX_400x600 13 // 400x600x256, 1 page + +// +// Fade effects +// +#define MX_FADEIN 0 +#define MX_FADEOUT 1 + +// +// Raster ops +// +#define OP_SET 0 // No operator +#define OP_AND 1 // And +#define OP_OR 2 // Or +#define OP_XOR 3 // Xor +#define OP_TRANS 4 // Transparent +#define OP_ADD 5 // Additive +#define OP_MOVE 0 // Alias for OP_SET + +// +// Temporary definitions +// +#define MXBYTE unsigned char +#define MXBOOL short int +#define MXSINT short int +#define MXUINT unsigned short int +#define MXAPI far pascal +#define MXPTR void far * + +// Functions + +#ifdef __cplusplus // Avoid C++ name mangling +extern "C" { +#endif + +// +// Initialization +// +MXSINT MXAPI mxInit( void ); // Returns 0 if successful +void MXAPI mxTerm( void ); +MXUINT MXAPI mxGetVersion( void ); +// +// Mode setting +// +void MXAPI mxChangeMode( MXUINT mode ); +void MXAPI mxSetMode( MXUINT mode ); +void MXAPI mxGetAspect( MXUINT far *aspectx, MXUINT far *aspecty ); +void MXAPI mxGetScreenSize( MXUINT far *width, MXUINT far *height ); +// +// Hardware support +// +void MXAPI mxWriteMode( MXBYTE wm ); +void MXAPI mxSplitScreen( MXUINT line ); +void MXAPI mxStartAddress( MXUINT sa ); +void MXAPI mxStartLine( MXUINT sl ); +void MXAPI mxWaitDisplay( void ); +void MXAPI mxWaitRetrace( void ); +void MXAPI mxWritePlane( MXBYTE wp ); +void MXAPI mxReadPlane( MXBYTE rp ); +void MXAPI mxRowAddress( MXBYTE ra ); +// +// Virtual screen +// +void MXAPI mxGetVirtualScreen( MXUINT far *width, MXUINT far *height ); +void MXAPI mxSetVirtualScreen( MXUINT width, MXUINT height ); +void MXAPI mxPan( MXUINT x, MXUINT y ); +// +// Clipping +// +MXBOOL MXAPI mxGetClip( void ); +MXBOOL MXAPI mxGetClipRegion( MXSINT far *x, MXSINT far *y, MXSINT far *w, MXSINT far *h ); +MXBOOL MXAPI mxSetClip( MXBOOL ); +void MXAPI mxSetClipRegion( MXUINT x, MXUINT y, MXUINT width, MXUINT height ); +// +// Graphics +// +void MXAPI mxBitBlt( MXSINT sx, MXSINT sy, MXUINT width, MXUINT height, MXSINT dx, MXSINT dy ); +void MXAPI mxFillBox( MXSINT x, MXSINT y, MXUINT width, MXUINT height, MXUINT color, MXUINT op ); +MXBYTE MXAPI mxGetPixel( MXSINT x, MXSINT y ); +void MXAPI mxPutPixel( MXSINT x, MXSINT y, MXBYTE color ); +void MXAPI mxLine( MXSINT x1, MXSINT y1, MXSINT x2, MXSINT y2, MXUINT color, MXUINT op ); +void MXAPI mxGetImage( MXPTR img, MXSINT x, MXSINT y, MXUINT width, MXUINT height ); +void MXAPI mxPutImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT op ); +void MXAPI mxPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT width, MXUINT height ); +void MXAPI mxTransPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT w, MXUINT h ); +void MXAPI mxCircle( MXSINT x, MXSINT y, MXUINT radius, MXBYTE color ); +void MXAPI mxStretchImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT neww, MXUINT newh, MXUINT op ); +// +// Palette +// +void MXAPI mxColorToGray( MXPTR source, MXPTR dest, MXUINT count ); +void MXAPI mxGammaCorrect( MXPTR source, MXPTR dest, MXUINT count ); +void MXAPI mxGetColor( MXUINT index, MXSINT far *r, MXSINT far *g, MXSINT far *b ); +void MXAPI mxSetColor( MXUINT index, MXSINT red, MXSINT green, MXSINT blue ); +void MXAPI mxGetPalette( MXPTR palette, MXUINT index, MXUINT count ); +void MXAPI mxSetPalette( MXPTR palette, MXUINT index, MXUINT count ); +void MXAPI mxFadePalette( MXPTR, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT ); +void MXAPI mxRotatePalette( MXPTR palette, MXUINT count, MXSINT step ); +// +// Text +// +MXSINT MXAPI mxSetFont( MXPTR font, MXUINT charwidth, MXUINT charheight ); +void MXAPI mxSetTextColor( MXUINT color, MXUINT op ); +void MXAPI mxGetTextStep( MXSINT far *deltax, MXSINT far *deltay ); +void MXAPI mxSetTextStep( MXSINT deltax, MXSINT deltay ); +void MXAPI mxOutChar( MXSINT x, MXSINT y, char c ); +void MXAPI mxOutText( MXSINT x, MXSINT y, char far *sz ); +// +// Convex polygons +// +void MXAPI mxFillPoly( MXUINT, MXPTR, MXPTR, MXUINT, MXUINT ); +void MXAPI mxGouraudPoly( MXUINT, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT ); +void MXAPI mxTexturePoly( MXUINT, MXPTR, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT ); + +#ifdef __cplusplus +} +#endif + +// +// Remove temporary defines +// +#undef MXBYTE +#undef MXBOOL +#undef MXSINT +#undef MXUINT +#undef MXPTR +#undef MXAPI + +#endif // _MODEX_H_ diff --git a/16/xw/modex.lbr b/16/xw/modex.lbr new file mode 100755 index 00000000..93fc7801 --- /dev/null +++ b/16/xw/modex.lbr @@ -0,0 +1,39 @@ ++-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 & ++-MXPT.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 diff --git a/16/xw/modex.pas b/16/xw/modex.pas new file mode 100755 index 00000000..7d9d26ed --- /dev/null +++ b/16/xw/modex.pas @@ -0,0 +1,194 @@ +(* + Turbo Pascal interface to the MODEX library + Copyright (c) 1993,1994 by Alessandro Scotti +*) +unit ModeX; +interface + +const + (* Video modes *) + MX_TEXT = 0; + MX_320x175 = 1; + MX_320x200 = 2; + MX_320x240 = 3; + MX_320x350 = 4; + MX_320x400 = 5; + MX_320x480 = 6; + MX_360x175 = 7; + MX_360x200 = 8; + MX_360x240 = 9; + MX_360x350 = 10; + MX_360x400 = 11; + MX_360x480 = 12; + MX_400x600 = 13; + + (* Fade effects *) + MX_FADEIN = 0; + MX_FADEOUT = 1; + + (* Raster ops *) + OP_SET = 0; + OP_AND = 1; + OP_OR = 2; + OP_XOR = 3; + OP_TRANS = 4; + OP_ADD = 5; + OP_MOVE = 0; (* Alias for OP_SET *) + +procedure mxBitBlt( SX, SY: integer; Width, Height: word; DX, DY: integer ); +procedure mxCircle( CX, CY: integer; Radius: word; Color: byte ); +procedure mxChangeMode( Mode: word ); +procedure mxColorToGray( ColorPalette, GrayPalette: pointer; Count: word ); +procedure mxFadePalette( Palette: pointer; Cmd, Start, Count, R, G, B: word ); +procedure mxFillBox( X, Y: integer; Width, Height: word; Color: byte; Op: word ); +procedure mxGammaCorrect( ColorPalette, GammaPalette: pointer; Count: word ); +procedure mxGetAspect( var AspectX, AspectY: word ); +function mxGetClipRegion( var X1, Y1, Width, Height: word ): boolean; +function mxGetClip: boolean; +procedure mxGetImage( Image: pointer; X, Y: integer; Width, Height: word ); +procedure mxGetPalette( Palette: pointer; Start, Count: word ); +function mxGetPixel( X, Y: word ): byte; +procedure mxGetScreenSize( var Width, Height: word ); +procedure mxGetTextStep( var DeltaX, DeltaY: integer ); +function mxGetVersion: word; +procedure mxGetVirtualScreen( var Width, Height: word ); +procedure mxInit; +procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word ); +procedure mxOutChar( X, Y: integer; C: char ); +procedure mxOutText( X, Y: integer; S: pointer ); +procedure mxPan( X, Y: word ); +procedure mxPutImage( Image: pointer; X, Y: integer; Width, Height, Op: word ); +procedure mxPutPixel( X, Y: word; C: byte ); +procedure mxPutTile( Tile: pointer; X, Y: integer; Width, Height: word ); +procedure mxReadPlane( Plane: byte ); +procedure mxRotatePalette( Palette: pointer; Count: word; Step: integer ); +procedure mxRowAddress( RowAddress: byte ); +function mxSetClip( Clip: boolean ): boolean; +procedure mxSetClipRegion( X1, Y1, Width, Height: word ); +procedure mxSetColor( Index, R, G, B: word ); +procedure mxSetFont( Font: pointer; Width, Height: word ); +procedure mxSetMode( Mode: word ); +procedure mxSetPalette( Palette: pointer; Start, Count: word ); +procedure mxSetTextColor( Color, Op: word ); +procedure mxSetTextStep( DeltaX, DeltaY: integer ); +procedure mxSetVirtualScreen( Width, Height: word ); +procedure mxStretchImage( Image: pointer; X, Y: integer; Width, Height, NewWidth, NewHeight, Op: word ); +procedure mxSplitScreen( Line: word ); +procedure mxStartAddress( StartAddress: word ); +procedure mxStartLine( Line: word ); +procedure mxTerm; +procedure mxTransPutTile( Tile: pointer; X, Y: integer; Width, Height: word ); +procedure mxWaitDisplay; +procedure mxWaitRetrace; +procedure mxWriteMode( Mode: byte ); +procedure mxWritePlane( Plane: byte ); + +procedure mxFillPoly( Count: word; var Map, Points; Color: word ); +procedure mxGouraudPoly( Count: word; var Map, Points, Colors; BaseColor: word ); +procedure mxTexturePoly( Count: word; var Map, Points, ImgPoints, Texture; Width: word ); + +procedure mxOutStr( X, Y: integer; S: string ); + +implementation + +procedure mxBitBlt; external; +procedure mxChangeMode( Mode: word ); external; +procedure mxCircle; external; +procedure mxColorToGray; external; +procedure mxFadePalette; external; +procedure mxFillBox; external; +procedure mxGammaCorrect; external; +procedure mxGetAspect( var AspectX, AspectY: word ); external; +function mxGetClipRegion; external; +function mxGetClip: boolean; external; +procedure mxGetImage; external; +procedure mxGetPalette( Palette: pointer; Start, Count: word ); external; +function mxGetPixel( X, Y: word ): byte; external; +procedure mxGetScreenSize( var Width, Height: word ); external; +procedure mxGetTextStep( var DeltaX, DeltaY: integer ); external; +function mxGetVersion: word; external; +procedure mxGetVirtualScreen( var Width, Height: word ); external; +procedure mxInit; external; +procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word ); external; +procedure mxOutChar( X, Y: integer; C: char ); external; +procedure mxOutText( X, Y: integer; S: pointer ); external; +procedure mxPan( X, Y: word ); external; +procedure mxPutImage; external; +procedure mxPutPixel( X, Y: word; C: byte ); external; +procedure mxPutTile; external; +procedure mxReadPlane( Plane: byte ); external; +procedure mxRotatePalette; external; +procedure mxRowAddress( RowAddress: byte ); external; +function mxSetClip( Clip: boolean ): boolean; external; +procedure mxSetClipRegion( X1, Y1, Width, Height: word ); external; +procedure mxSetColor( Index, R, G, B: word ); external; +procedure mxSetFont( Font: pointer; Width, Height: word ); external; +procedure mxSetMode( Mode: word ); external; +procedure mxSetPalette( Palette: pointer; Start, Count: word ); external; +procedure mxSetTextColor( Color, Op: word ); external; +procedure mxSetTextStep( DeltaX, DeltaY: integer ); external; +procedure mxSetVirtualScreen( Width, Height: word ); external; +procedure mxSplitScreen( Line: word ); external; +procedure mxStartAddress( StartAddress: word ); external; +procedure mxStartLine; external; +procedure mxStretchImage; external; +procedure mxTerm; external; +procedure mxTransPutTile; external; +procedure mxWaitDisplay; external; +procedure mxWaitRetrace; external; +procedure mxWriteMode( Mode: byte ); external; +procedure mxWritePlane( Plane: byte ); external; + +procedure mxFillPoly; external; +procedure mxGouraudPoly; external; +procedure mxTexturePoly; external; +{$L MXPB} +{$L MXPF} +{$L MXPG} +{$L MXPT} + +{$L MXBB} +{$L MXCC} +{$L MXCG} +{$L MXCL} +{$L MXCR} +{$L MXFB} +{$L MXFP} +{$L MXGI} +{$L MXGM} +{$L MXGP} +{$L MXGV} +{$L MXHL} +{$L MXIT} +{$L MXLN} +{$L MXOT} +{$L MXPI} +{$L MXPN} +{$L MXPP} +{$L MXRA} +{$L MXRP} +{$L MXSA} +{$L MXSC} +{$L MXSI} +{$L MXSL} +{$L MXSM} +{$L MXSP} +{$L MXSS} +{$L MXTL} +{$L MXVS} +{$L MXWD} +{$L MXWM} +{$L MXWP} +{$L MXWR} + +(* + Prints a Turbo Pascal string. + Note: BP 7.0 supports ASCIIZ strings (PChar type). +*) +procedure mxOutStr; +begin + S := S + #0; + mxOutText( X, Y, @S[1] ); +end; + +end. diff --git a/16/xw/modex/DEMO01.EXE b/16/xw/modex/DEMO01.EXE new file mode 100755 index 0000000000000000000000000000000000000000..28caff88c58a0b8ce5a4d23c6544c00cda8482fc GIT binary patch literal 10208 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 320 ) then begin + S.X := 320; + S.DX := -S.DX; + end; + if( S.X < -16 ) then begin + S.X := -16; + S.DX := -S.DX; + end; + if( S.Y > 240 ) then begin + S.Y := 240; + S.DY := -S.DY; + end; + if( S.Y < -16 ) then begin + S.Y := -16; + S.DY := -S.DY; + end; + (* Draw the sprite, note the Page offset added to the *) + (* Y coordinate of the image *) + mxPutImage( @S.Image, S.X, Page+S.Y, S.W, S.H, OP_TRANS ); +end; + +begin + (* Initialize library *) + mxInit; + + (* Enter graphics mode *) + mxSetMode( MX_320x240 ); + + (* Print initialization message *) + mxSetTextColor( 15, OP_TRANS ); + mxOutStr( 4, 4, 'Initializing...' ); + + (* Initialize sprites *) + for I:=1 to MAX_SPRITE do sxInit( S[I] ); + + (* Draw background *) + for I:=1 to 192 do begin + mxCircle( 160, 480+120, I, I+63 ); + mxCircle( 161, 480+120, I, I+63 ); + end; + + (* Compute and set palette *) + for I:=1 to 192 do with Palette[I+63] do begin + R := 0; + G := 0; + B := 0; + if( I < 64 ) then + R := I shr 1+31 + else if( I < 128 ) then + G := (I-64) shr 1+31 + else + B := (I-128) shr 1+31; + end; + mxSetPalette( @Palette[64], 64, 192 ); + + (* Main loop *) + Page := 240; + while( not KeyPressed ) do begin + (* Set clip region to current page *) + mxSetClipRegion( 0, Page, 320, 240 ); + mxSetClip( TRUE ); + (* Restore background *) + mxBitBlt( 0, 480, 320, 240, 0, Page ); + (* Draw sprites *) + for I:=1 to MAX_SPRITE do sxMove( S[I] ); + (* Print message *) + mxOutStr( 4, Page+4, 'Some sprites moving...' ); + (* Flip page *) + mxStartLine( Page ); + Page := 240-Page; + (* Animate palette *) + mxSetPalette( @Palette[64], 64, 192 ); + mxRotatePalette( @Palette[64], 192, 3 ); + end; + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw/modex/DEMO02.EXE b/16/xw/modex/DEMO02.EXE new file mode 100755 index 0000000000000000000000000000000000000000..14e7dc72b16e421ae94767feaa07cb3988f49db1 GIT binary patch literal 24688 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 L6~S)>H$VReFZ-F@ literal 0 HcmV?d00001 diff --git a/16/xw/modex/DEMO02.PAS b/16/xw/modex/DEMO02.PAS new file mode 100755 index 00000000..6b4fb6f9 --- /dev/null +++ b/16/xw/modex/DEMO02.PAS @@ -0,0 +1,125 @@ +(* + DEMO02 - Texture mapping and palette rotation + (c) 1994 by Alessandro Scotti +*) +uses Crt, Modex, Plasma, Threed; + +const + LSIZE = 85; + Trans : TPoint = ( X:0; Y:0; Z:0 ); +type + T2DPoint = record + X, Y: integer; + end; + TTexture = record + Desc : array[ 0..3 ] of T2DPoint; + Width : word; + Data : array[ 1..64*64 ] of byte; + end; + TQuad = record + VtxCnt : word; + Vtx : array[ 0..3 ] of word; + Texture: word; + end; +var + Vtx : array[ 0..7 ] of TPoint; + XVtx : array[ 0..7 ] of TPoint; + VVtx : array[ 0..7 ] of T2DPoint; + Face : array[ 0..5 ] of TQuad; + Txts : array[ 0..5 ] of TTexture; + Nrm : array[ 0..5 ] of TPoint; + XNrm : array[ 0..5 ] of TPoint; + Page : word; + Palette: array[ byte ] of record R, G, B: byte; end; + +(* Make a 64x64 plasma to be used as texture *) +procedure MakeTexture( Idx: word ); +var + I: word; +begin + mxFillBox( 0, 0, 64, 64, 0, OP_SET ); + MakePlasma( 0, 0, 64, 64, 96, Random(192)+1, Random(192)+1, Random(192)+1 ); + mxGetImage( @Txts[Idx].Data, 0, 0, 64, 64 ); + (* Texture vertexes are 8:8 fixed, add $80 (0.5) for best results *) + with Txts[Idx] do begin + Desc[0].X := $80; Desc[0].Y := $80; + Desc[1].X := $80; Desc[1].Y := $3F80; + Desc[2].X := $3F80; Desc[2].Y := $3F80; + Desc[3].X := $3F80; Desc[3].Y := $80; + Width := 64; + end; +end; + +procedure Init; +var + I: integer; +begin + (* Build vertexes for a cube *) + with Vtx[0] do begin X:=-LSIZE; Y:=-LSIZE; Z:=-LSIZE; end; + with Vtx[1] do begin X:=+LSIZE; Y:=-LSIZE; Z:=-LSIZE; end; + with Vtx[2] do begin X:=-LSIZE; Y:=+LSIZE; Z:=-LSIZE; end; + with Vtx[3] do begin X:=+LSIZE; Y:=+LSIZE; Z:=-LSIZE; end; + with Vtx[4] do begin X:=-LSIZE; Y:=-LSIZE; Z:=+LSIZE; end; + with Vtx[5] do begin X:=+LSIZE; Y:=-LSIZE; Z:=+LSIZE; end; + with Vtx[6] do begin X:=-LSIZE; Y:=+LSIZE; Z:=+LSIZE; end; + with Vtx[7] do begin X:=+LSIZE; Y:=+LSIZE; Z:=+LSIZE; end; + for I:=0 to 7 do begin (* Make points 16:16 fixed *) + Vtx[I].X := Vtx[I].X*$10000; + Vtx[I].Y := Vtx[I].Y*$10000; + Vtx[I].Z := Vtx[I].Z*$10000; + end; + (* Build faces *) + with Face[0] do begin Vtx[0]:=0; Vtx[1]:=2; Vtx[2]:=3; Vtx[3]:=1; end; + with Face[1] do begin Vtx[0]:=4; Vtx[1]:=5; Vtx[2]:=7; Vtx[3]:=6; end; + with Face[2] do begin Vtx[0]:=0; Vtx[1]:=1; Vtx[2]:=5; Vtx[3]:=4; end; + with Face[3] do begin Vtx[0]:=1; Vtx[1]:=3; Vtx[2]:=7; Vtx[3]:=5; end; + with Face[4] do begin Vtx[0]:=2; Vtx[1]:=0; Vtx[2]:=4; Vtx[3]:=6; end; + with Face[5] do begin Vtx[0]:=7; Vtx[1]:=3; Vtx[2]:=2; Vtx[3]:=6; end; + for I:=0 to 5 do Face[I].Texture := I; + (* Build textures and palette *) + Randomize; + FillChar( Palette, SizeOf(Palette), 0 ); + MakePlasmaPalette( Palette, PAL_RGB ); + mxSetPalette( @Palette, 0, 193 ); + for I:=0 to 5 do MakeTexture( I ); +end; + +var + AX, AY, AZ: byte; + I: word; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; (* Start with hidden page *) + + AX := 0; + AY := 0; + AZ := 0; + (* Init 3D transforms, perspective is intentionally exaggerated *) + tdSetTranslation( Trans ); + tdSetPerspective( 400*$10000, $10000, $10000 ); + (* Main loop, all magic here! *) + while( not KeyPressed ) do begin + tdSetRotation( AX, AY, AZ ); (* Set new angles *) + tdTransform( Vtx, XVtx, 8 ); (* 3D transform points *) + tdTransformToImage( XVtx, VVtx, 8, 160, 120+Page ); + Inc( AX, 1 ); (* Bump angles *) + Inc( AY, 1 ); + Inc( AZ, 2 ); + mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *) + mxSetClip( TRUE ); + mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *) + mxRotatePalette( @Palette[1], 192, 3 ); (* Rotate palette *) + (* Draw cube: backface culling is straighforward in this case, so *) + (* it can be handled by the polygon filling procedure *) + for I:=0 to 5 do + mxTexturePoly( 4, Face[I].Vtx, VVtx, Txts[I].Desc, Txts[I].Data, Txts[I].Width ); + mxStartLine( Page ); (* Flip pages *) + mxSetPalette( @Palette[1], 1, 192 ); (* Set new palette *) + Page := 240-Page; + end; + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw/modex/DEMO03.EXE b/16/xw/modex/DEMO03.EXE new file mode 100755 index 0000000000000000000000000000000000000000..c646c4b0283db932174d915432747c2176034195 GIT binary patch literal 14256 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 RADIUS*RADIUS ) then goto Retry; + Z := Toggle( Round( Sqrt( Abs( RADIUS*RADIUS-X*X-Y*Y ) ) ) ); + case Random(3) of + 0: Swap( X, Z ); + 1: Swap( Y, Z ); + end; + X := X * $10000; Y := Y * $10000; Z := Z * $10000; + end; + end; + (* Initialize morphing *) + Move( CubeVtx^, Vtx^, SizeOf(Vtx^) ); + Status := 0; + Count := WAITCOUNT; +end; + +procedure Morph; +var + I: integer; +begin + (* Fully unoptimized, slowest loop I could think of! *) + for I:=0 to MAXVTX-1 do begin + Vtx^[I].X := ((CubeVtx^[I].X * Morph1)+(SphereVtx^[I].X * Morph2)) div MS; + Vtx^[I].Y := ((CubeVtx^[I].Y * Morph1)+(SphereVtx^[I].Y * Morph2)) div MS; + Vtx^[I].Z := ((CubeVtx^[I].Z * Morph1)+(SphereVtx^[I].Z * Morph2)) div MS; + end; +end; + +var + AX, AY, AZ: byte; + I: word; + C: char; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; (* Start with hidden page *) + + AX := 0; + AY := 0; + AZ := 0; + (* Init 3D transforms, perspective is intentionally exaggerated *) + tdSetTranslation( Trans ); + tdSetPerspective( 400*$10000, $10000, $10000 ); + C := #0; + repeat + tdSetRotation( AX, AY, AZ ); (* Set new angles *) + tdTransform( Vtx^, XVtx^, MAXVTX ); (* 3D transform points *) + tdTransformToImage( XVtx^, VVtx, MAXVTX, 160, 120+Page ); + Inc( AX, 1 ); (* Bump angles *) + Inc( AY, 1 ); + Inc( AZ, 2 ); + mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *) + mxSetClip( TRUE ); + mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *) + (* Draw points *) + for I:=0 to MAXVTX-1 do + mxPutPixel( VVtx[I].X, VVtx[I].Y, 128 + XVtx^[I].Z shr 18 ); + mxStartLine( Page ); (* Flip pages *) + Page := 240-Page; + (* Morph *) + if( Odd(Status) ) then begin + Morph; + Inc( Morph1, Delta1 ); + Inc( Morph2, Delta2 ); + if( Morph1 < 0 )or( Morph2 < 0 ) then Inc( Status ); + if( Status = 4 ) then Status := 0; + end + else begin + Dec( Count ); + if( Count < 0 ) then begin + Inc( Status ); + Count := WAITCOUNT; + Morph1 := InitMorph1[Status]; + Morph2 := InitMorph2[Status]; + Delta1 := InitDelta1[Status]; + Delta2 := InitDelta2[Status]; + end; + end; + until( KeyPressed ); + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw/modex/DEMO04.DAT b/16/xw/modex/DEMO04.DAT new file mode 100755 index 0000000000000000000000000000000000000000..72aaad08ac55e4d161e7868374296a4e42554684 GIT binary patch literal 37662 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%0D)*4A2IO9KMZYD#oU43C^WOCfTg8_%RD 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�-ncKj8QX2BIutynAlnfJ{;J0ue86t5F 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 XG;Ye`)EVP3#M6mPm!(a=?*#mR$DZhs literal 0 HcmV?d00001 diff --git a/16/xw/modex/DEMO04.EXE b/16/xw/modex/DEMO04.EXE new file mode 100755 index 0000000000000000000000000000000000000000..1fec5e8aa383353d986ca1e4420838b09e61eef4 GIT binary patch literal 24384 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 Im202>1y)VB#{d8T literal 0 HcmV?d00001 diff --git a/16/xw/modex/DEMO04.PAS b/16/xw/modex/DEMO04.PAS new file mode 100755 index 00000000..1a946315 --- /dev/null +++ b/16/xw/modex/DEMO04.PAS @@ -0,0 +1,198 @@ +(* + DEMO04 - Multiple textures and triple buffering (3 pages) + (c) 1994 by Alessandro Scotti +*) +uses Crt, Modex, Threed; + +const + MAXVTX = 256; + MAXCUB = 2; + MAXTXT = 2; + Trans : TPoint = ( X:0; Y:0; Z:0 ); + TxtSunDial: array[ 0..7 ] of word = ( + $7F80,$0080, $0080,$0080, $0080,$7E80, $7F80,$7E80 ); + TxtSapphire : array[ 0..7 ] of word = ( + $0080,$0080, $0080,$1F80, $1F80,$1F80, $1F80,$0080 ); + TxtMarble: array[ 0..7 ] of word = ( + $0080,$8080, $0080,$FD80, $7F80,$FD80, $7F80,$8080 ); +type + T2DPoint = record + X, Y: integer; + end; + TTexture = record + Desc : array[ 0..3 ] of record X, Y: word end; + Width : word; + Data : pointer; + end; + TQuad = record + Vtx : array[ 0..3 ] of word; + Texture: word; + end; + TCube = record + Face : array[ 0..5 ] of TQuad; + Base : integer; + end; +var + Vtx, XVtx: array[ 0..MAXVTX ] of TPoint; + VVtx : array[ 0..MAXVTX ] of T2DPoint; + Cube : array[ 0..MAXCUB ] of TCube; + ZList : array[ 0..MAXCUB ] of integer; + VtxCnt : word; + Txts : array[ 0..MAXTXT ] of TTexture; + Page : word; + Palette : array[ byte ] of record R, G, B: byte; end; + TxtDat1, TxtDat2: pointer; + +(* Add a new entry to the vertex array *) +procedure AddVtx( PX, PY, PZ: longint ); +begin + with Vtx[VtxCnt] do begin X:=PX*$10000; Y:=PY*$10000; Z:=PZ*$10000; end; + Inc( VtxCnt ); +end; + +procedure MakeCube( var C: TCube; X1,Y1,Z1, X2,Y2,Z2, TX,TY,TZ, Texture: integer ); +const + FaceIdx: array[ 0..23 ] of integer = ( + 0,1,2,3, 0,4,5,1, 1,5,6,2, 2,6,7,3, 3,7,4,0, 6,5,4,7 ); +var + I, VC: integer; +begin + VC := VtxCnt; + C.Base := VC; + AddVtx( X1+TX, Y1+TY, Z1+TZ ); + AddVtx( X2+TX, Y1+TY, Z1+TZ ); + AddVtx( X2+TX, Y2+TY, Z1+TZ ); + AddVtx( X1+TX, Y2+TY, Z1+TZ ); + AddVtx( X1+TX, Y1+TY, Z2+TZ ); + AddVtx( X2+TX, Y1+TY, Z2+TZ ); + AddVtx( X2+TX, Y2+TY, Z2+TZ ); + AddVtx( X1+TX, Y2+TY, Z2+TZ ); + for I:=0 to 23 do C.Face[I shr 2].Vtx[I and 3] := VC+FaceIdx[I]; + for I:=0 to 5 do C.Face[I].Texture := Texture; +end; + +procedure MakeTexture( Idx: integer; var VtxData ); +var + P: ^word; + I: integer; +begin + P := @VtxData; + with Txts[Idx] do begin + for I:=0 to 3 do begin + Desc[I].X := P^; Inc( P ); + Desc[I].Y := P^; Inc( P ); + end; + Width := 129; + Data := TxtDat1; + end; +end; + +procedure Init; +var + I: integer; + V: integer; + F: file; + P: array[ 1..768 ] of byte; +begin + (* Initialize objects *) + VtxCnt := 0; + MakeCube( Cube[0], -64,-64,8, 64,64,-8, 0,0,0, 1 ); (* Sundial *) + Cube[0].Face[0].Texture := 0; + V := VtxCnt; + MakeCube( Cube[1], -16,-16,16, 16,16,-16, 0,0,0, 2 ); (* Sapphire *) + tdSetTranslation( Trans ); + tdSetRotation( 32, 32, 00 ); + tdRotate( Vtx[V], XVtx[V], 8 ); (* Got to rotate this cube *) + for I:=V to V+7 do begin + Vtx[I].X := XVtx[I].X; + Vtx[I].Y := XVtx[I].Y; + Vtx[I].Z := XVtx[I].Z + 100*$10000; + end; + MakeCube( Cube[2], -64,-4,48, 64,4,-48, 0,68,56, 1 ); (* Marble *) + (* Load texture and palette *) + Assign( F, 'DEMO04.DAT' ); + Reset( F, 1 ); + BlockRead( F, P, SizeOf(P) ); + mxSetPalette( @P, 0, 256 ); + GetMem( TxtDat1, 63*1024 ); + BlockRead( F, TxtDat1^, 129*286 ); + Close( F ); + TxtDat2 := Ptr( Seg(TxtDat1^), Ofs(TxtDat1^)+129*254 ); + (* Init textures *) + MakeTexture( 0, TxtSundial ); + MakeTexture( 1, TxtMarble ); + MakeTexture( 2, TxtSapphire ); + Txts[2].Data := TxtDat2; +end; + +(* Sort procedure, not worth optimizing with only a few objects *) +procedure SortObjects; +var + I, J, K: integer; + ZMax: array[ 0..MAXCUB ] of longint; + ZI: integer; + L: longint; +begin + for I:=0 to MAXCUB do begin + L := XVtx[Cube[I].Base].Z; + for J:=1 to 7 do + if( L > XVtx[Cube[I].Base+J].Z ) then L := XVtx[Cube[I].Base+J].Z; + ZMax[I] := L; + ZList[I] := I; + end; + for I:=0 to MAXCUB-1 do begin + ZI := I; + for J:=I+1 to MAXCUB do + if( ZMax[ZList[J]] > ZMax[ZList[ZI]] ) then ZI := J; + if( ZI <> I ) then begin + K := ZList[I]; + ZList[I] := ZList[ZI]; + ZList[ZI] := K; + end; + end; +end; + +var + AX, AY, AZ: byte; + I, J, K: word; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; (* Start with hidden page *) + + (* Init 3D transforms, perspective is intentionally exaggerated *) + AX := 0; AY := 0; AZ := 0; + tdSetTranslation( Trans ); + tdSetPerspective( 600*$10000, $10000, $10000 ); + (* Main loop, all magic here! *) + while( not KeyPressed ) do begin + tdSetRotation( AX, AY, AZ ); (* Set new angles *) + tdTransform( Vtx, XVtx, VtxCnt ); (* 3D transform points *) + tdTransformToImage( XVtx, VVtx, VtxCnt, 160, 120+Page ); + Inc( AX, 1 ); (* Bump angles *) + Inc( AY, 2 ); + Inc( AZ, 1 ); + mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *) + mxSetClip( TRUE ); + mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *) + (* Draw objects *) + SortObjects; + for I:=0 to MAXCUB do with Cube[ZList[I]] do begin + for J:=0 to 5 do begin + K := Face[J].Texture; + mxTexturePoly( 4, Face[J].Vtx, VVtx, Txts[K].Desc, Txts[K].Data^, Txts[K].Width ); + end; + end; + (* Flip page: at 320x240 the Start Address Register Low is always zero *) + case Page of + 0 : begin PortW[$3D4] := $000C; Page := 240; end; + 240: begin PortW[$3D4] := $4B0C; Page := 480; end; + 480: begin PortW[$3D4] := $960C; Page := 0; end; + end; + mxWaitRetrace; (* If the frame rate seems low, try to remove this line *) + end; + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw/modex/DEMO05.EXE b/16/xw/modex/DEMO05.EXE new file mode 100755 index 0000000000000000000000000000000000000000..21a7c207f7134ed187a08530637509b96b37b19e GIT binary patch literal 22528 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 CoI~RP literal 0 HcmV?d00001 diff --git a/16/xw/modex/DEMO05.PAS b/16/xw/modex/DEMO05.PAS new file mode 100755 index 00000000..819c5cf3 --- /dev/null +++ b/16/xw/modex/DEMO05.PAS @@ -0,0 +1,131 @@ +(* + DEMO05 - A Gouraud-shaded rotating torus + (c) 1994 Alessandro Scotti +*) +uses Crt, Modex, Threed; + +(* Define ALTPAL for alternate palette *) +{$define ALTPAL} + +const + MAXVTX1 = 15; RADIUS1 = 70; (* MAXVTX1+1 must be multiple of 4 *) + MAXVTX2 = 15; RADIUS2 = 30; + MAXVTX = (MAXVTX1+1)*(MAXVTX2+1)-1; + MAXFACE = MAXVTX; + Trans : TPoint = ( X:0; Y:0; Z:0 ); (* Object translation *) + Light : TPoint = ( X:0; Y:0; Z:-63*$10000 ); (* Light direction *) +type + TQuad = record + QVtx : array[ 0..3 ] of integer; + end; +var + Vtx, XVtx : array[ 0..MAXVTX ] of TPoint; (* Points *) + VVtx : array[ 0..MAXVTX ] of record X, Y: integer end; + Face : array[ 0..MAXFACE ] of TQuad; (* Polys *) + Culled : array[ 0..MAXFACE ] of integer; + GNrm,XGNrm: array[ 0..MAXVTX ] of TVector; (* Gouraud normals *) + VtxLight : array[ 0..MAXVTX ] of integer; (* Points brightness *) + Page : word; + +function GetVtx( I1, I2: integer ): integer; +begin + GetVtx := (I1 mod (MAXVTX1+1))*(MAXVTX2+1) + I2 mod (MAXVTX2+1); +end; + +procedure Init; +var + R, N, X, Y, Z: real; + I, J, K, V: integer; +begin + (* Build vertexes *) + for I:=0 to MAXVTX1 do begin + K := (I + (MAXVTX1+1) shr 2) mod (MAXVTX1+1); + R := RADIUS1 + RADIUS2*Cos( 2*K*Pi / (MAXVTX1+1) ); + for J:=0 to MAXVTX2 do begin + V := I*(MAXVTX2+1)+J; (* Index of current vertex *) + (* Compute coordinates of current vertex *) + X := R*Cos(2*J*Pi / (MAXVTX2+1)); (* Get coordinates *) + Y := R*Sin(2*J*Pi / (MAXVTX2+1)); + Z := RADIUS2*Sin(2*K*Pi / (MAXVTX1+1)); + Vtx[V].X := Round( X )*$10000; (* Save coordinates *) + Vtx[V].Y := Round( Y )*$10000; + Vtx[V].Z := Round( Z )*$10000; + (* Compute direction of Gouraud normal thru current vertex *) + X := X - RADIUS1*Cos(2*J*Pi / (MAXVTX2+1)); + Y := Y - RADIUS1*Sin(2*J*Pi / (MAXVTX2+1)); + N := Sqrt( X*X + Y*Y + Z*Z ); (* Get vector length *) + GNrm[V].X := Trunc( X*$10000/N ); (* Save normal vector *) + GNrm[V].Y := Trunc( Y*$10000/N ); + GNrm[V].Z := Trunc( Z*$10000/N ); + end; + end; + (* Generate faces so that depth-sorting is not needed: there are still *) + (* some *very* little errors, but this is the best I could devise *) + J := 0; + K := 0; + for I:=0 to MAXFACE do with Face[I] do begin + QVtx[0] := GetVtx( J, K ); + QVtx[1] := GetVtx( J, K+1 ); + QVtx[2] := GetVtx( J+1, K+1 ); + QVtx[3] := GetVtx( J+1, K ); + Inc( K ); + if( K > MAXVTX2 ) then begin + K := 0; + Inc( J ); + end; + end; +{$ifndef ALTPAL} + for I:=0 to 63 do mxSetColor( I+64, 0, 0, I ); (* Blue palette *) +{$else} + for I:=0 to 31 do mxSetColor(I+64, 0, I shl 1, 0); (* Green neon palette *) + for I:=32 to 63 do mxSetColor ( I+64, (I-32) shl 1, 63, (I-32) shl 1 ); +{$endif} +end; + +var + AX, AY, AZ: byte; + I: word; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; (* Start with hidden page *) + + AX := 0; + AY := 0; + AZ := 0; + (* Init 3D transforms, perspective is intentionally exaggerated *) + tdSetTranslation( Trans ); + tdSetLight( Light ); + tdSetPerspective( 400*$10000, $10000, $10000 ); + (* Main loop, all magic here! *) + while( not KeyPressed ) do begin + tdSetRotation( AX, AY, AZ ); (* Set new angles *) + tdTransform( Vtx, XVtx, MAXVTX+1 ); (* 3D transform points *) + tdTransformToImage( XVtx, VVtx, MAXVTX+1, 160, 120+Page ); + tdRotate( GNrm, XGNrm, MAXVTX+1 ); (* Rotate Gouraud normals *) + tdTransformLight( XGNrm, VtxLight, MAXVTX+1 ); + (* Backplane culling is not really needed here! *) + FillChar( Culled, SizeOf(Culled), 0 ); + tdBackPlaneCull( Face, XVtx, Culled, MAXFACE+1, SizeOf(TQuad) ); + Inc( AX, 1 ); (* Bump angles *) + Inc( AY, 2 ); + Inc( AZ, 3 ); + mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *) + mxSetClip( TRUE ); + mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *) + (* Draw polygons *) + for I:=0 to MAXFACE do with Face[I] do + if( Culled[I] >= 0 ) then mxGouraudPoly( 4, QVtx, VVtx, VtxLight, 64 ); + (* Flip page: at 320x240 the Start Address Register Low is always zero *) + case Page of + 0 : begin PortW[$3D4] := $000C; Page := 240; end; + 240: begin PortW[$3D4] := $4B0C; Page := 480; end; + 480: begin PortW[$3D4] := $960C; Page := 0; end; + end; + mxWaitRetrace; (* Uncomment this instruction if screen flickers *) + end; + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw/modex/DEMO06.DAT b/16/xw/modex/DEMO06.DAT new file mode 100755 index 0000000000000000000000000000000000000000..1ac2c2bb8f8c79a7cf1f3c968f75e8e5ac8cd705 GIT binary patch literal 77568 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 P3zel81wBCVexm$;I2yv& literal 0 HcmV?d00001 diff --git a/16/xw/modex/DEMO06.EXE b/16/xw/modex/DEMO06.EXE new file mode 100755 index 0000000000000000000000000000000000000000..f1308e8a536aa9d3d4574566fd018d698d5ef784 GIT binary patch literal 10864 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 G@BaZ%)XT^K literal 0 HcmV?d00001 diff --git a/16/xw/modex/DEMO06.PAS b/16/xw/modex/DEMO06.PAS new file mode 100755 index 00000000..f26af067 --- /dev/null +++ b/16/xw/modex/DEMO06.PAS @@ -0,0 +1,135 @@ +(* + DEMO06 - Magnifying glass + (c) 1994 Alessandro Scotti +*) +uses Crt, Modex; + +const + R = 40; (* Lens radius *) + K : real = 1.8; (* Magnifying factor, less makes a stronger lens *) +type + TLine = array[ 0..319 ] of byte; + PLine = ^TLine; + TScreen = array[ 0..239 ] of PLine; +var + VScreen: TScreen; (* Virtual screen *) + BallX : array[ 0..R, 0..R ] of integer; + BallY : array[ 0..R, 0..R ] of integer; + Sprite : array[ -R..R, -R..R ] of byte; + Page : word; + +(* Returns "lens-view" coordinates of X,Y *) +procedure GetCoords( var X, Y: integer ); +var + LR, Z, SinA, SinB, TgB, Q: real; +begin + LR := Sqrt( X*X + Y*Y ); + if( LR = 0 ) then Exit; + if( LR < R ) then begin + Z := Sqrt( R*R - LR*LR ); + SinA := LR / R; + SinB := SinA / K; + TgB := SinB / Sqrt( 1-SinB*SinB ); + Q := LR - TgB*Z; + X := Round( X * ( Q/LR ) ); + Y := Round( Y * ( Q/LR ) ); + end; +end; + +procedure Init; +var + F : file; + Palette: array[ 0..767 ] of record R, G, B: byte; end; + X, Y, + X2, Y2 : integer; +begin + (* Load background image *) + Assign( F, 'demo06.dat' ); + Reset( F, 1 ); + BlockRead( F, Palette, 768 ); + mxSetPalette( @Palette, 0, 256 ); + for Y:=0 to 239 do begin + New( VScreen[Y] ); + BlockRead( F, VScreen[Y]^, 320 ); + mxPutImage( VScreen[Y], 0, 480+Y, 320, 1, OP_MOVE ); + end; + Close( F ); + (* Build lens *) + for X:=0 to R do begin + for Y:=0 to R do begin + X2 := X; + Y2 := Y; + GetCoords( X2, Y2 ); + BallX[X, Y] := X2; + BallY[X, Y] := Y2; + end; + end; +end; + +procedure PutLens( OX, OY: integer ); +var + X, Y: integer; +begin + for X:=0 to R do begin + for Y:=0 to R do begin + Sprite[Y][X] := VScreen[ OY+BallY[X,Y] ]^[ OX+BallX[X,Y] ]; + Sprite[Y][-X] := VScreen[ OY+BallY[X,Y] ]^[ OX-BallX[X,Y] ]; + Sprite[-Y][X] := VScreen[ OY-BallY[X,Y] ]^[ OX+BallX[X,Y] ]; + Sprite[-Y][-X] := VScreen[ OY-BallY[X,Y] ]^[ OX-BallX[X,Y] ]; + end; + end; + (* Draw the sprite *) + mxPutImage( @Sprite, OX-R, OY-R+Page, 2*R+1, 2*R+1, OP_MOVE ); +end; + +function Delta: integer; +begin + Delta := Random(3)+2; +end; + +procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer ); +begin + if( Cond ) then begin + Coord := NewCoord; + DeltaC := Sign*Delta; + end; +end; + +var + X, Y, DX, DY: integer; + C: char; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; + X := R; + Y := R; + Randomize; + DX := Delta; + DY := Delta; + + (* Main loop *) + repeat + (* Update video *) + mxBitBlt( 0, 480, 320, 240, 0, Page ); + PutLens( X, Y ); + mxCircle( X, Page+Y, R, 0 ); + (* Update lens coordinates *) + Inc( X, DX ); + Check( X+R >= 319, X, DX, 319-R, -1 ); + Check( X <= R, X, DX, R, +1 ); + Inc( Y, DY ); + Check( Y+R >= 239, Y, DY, 239-R, -1 ); + Check( Y <= R, Y, DY, R, +1 ); + (* Flip pages: double buffering, avoid wait for display *) + case Page of + 0 : begin PortW[$3D4] := $000C; Page := 240; end; + 240: begin PortW[$3D4] := $4B0C; Page := 0; end; + end; + mxWaitRetrace; (* Wait for hidden page to show *) + until( KeyPressed ); + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw/modex/DEMO07.EXE b/16/xw/modex/DEMO07.EXE new file mode 100755 index 0000000000000000000000000000000000000000..8a401169bba312a0d668452c9df6086505c394a8 GIT binary patch literal 7440 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 639, X, DX, 319, -1 ); + Check( X < 0, X, DX, 0, +1 ); + Inc( Y, DY ); + Check( Y+200 >= 399, Y, DY, 199, -1 ); + Check( Y < 0, Y, DY, 0, +1 ); + mxPan( X, Y ); + mxWaitRetrace; + end; + + (* Shutdown *) + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw/modex/MATH.INC b/16/xw/modex/MATH.INC new file mode 100755 index 00000000..742af410 --- /dev/null +++ b/16/xw/modex/MATH.INC @@ -0,0 +1,34 @@ +; +; MATH.INC - Include file for THREED.ASM +; + +; 3-dimensional point, coordinates in fixed format (16:16) +; +TPOINT STRUC + X DD ? + Y DD ? + Z DD ? +TPOINT ENDS + +; 2-dimensional point, coordinates in integer format +; +TIMAGEPOINT STRUC + IX DW ? + IY DW ? +TIMAGEPOINT ENDS + +; Fixed-point divide: EAX = EAX / arg +; +.xdiv MACRO arg + xor edx, edx + shld edx, eax, 16 + shl eax, 16 + idiv arg +ENDM + +; Fixed-point multiply: EAX = EAX * arg +; +.xmul MACRO arg + imul arg + shrd eax, edx, 16 +ENDM diff --git a/16/xw/modex/PLASMA.PAS b/16/xw/modex/PLASMA.PAS new file mode 100755 index 00000000..237e292a --- /dev/null +++ b/16/xw/modex/PLASMA.PAS @@ -0,0 +1,103 @@ +unit Plasma; +interface + +const + PAL_RGB = 0; + PAL_CLOUDS = 1; + PAL_LANDSCAPE = 2; + +procedure MakePlasma( X, Y: integer; W, H: word; C1, C2, C3, C4: byte ); +procedure MakePlasmaPalette( var Palette; What: word ); + +implementation uses Modex; + +procedure NewColor( XA, YA, X, Y, XB, YB: integer ); +var + Color: longint; +begin + Color := Abs( XA-XB )+Abs( YA-YB ); + Color := Random( Color shl 1 )-Color; + Color := (Color+mxGetPixel( XA, YA )+mxGetPixel( XB, YB )+1) shr 1; + if( Color < 1 ) then Color := 1; + if( Color > 192 ) then Color := 192; + if( mxGetPixel( X, Y ) = 0 ) then + mxPutPixel( X, Y, Lo(Color) ); +end; + +procedure Divide( X1, Y1, X2, Y2: integer ); +var + X, Y, Color: integer; +begin + if not( (X2-X1<2)and(Y2-Y1<2) ) then begin + X := (X1+X2) shr 1; + Y := (Y1+Y2) shr 1; + NewColor( X1, Y1, X, Y1, X2, Y1 ); + NewColor( X2, Y1, X2, Y, X2, Y2 ); + NewColor( X1, Y2, X, Y2, X2, Y2 ); + NewColor( X1, Y1, X1, Y, X1, Y2 ); + Color := (mxGetPixel( X1, Y1 )+mxGetPixel( X2, Y1 )+ + mxGetPixel( X2, Y2 )+mxGetPixel( X1, Y2 )) shr 2; + mxPutPixel( X, Y, Color ); + Divide( X1, Y1, X, Y ); + Divide( X, Y1, X2, Y ); + Divide( X, Y, X2, Y2 ); + Divide( X1, Y, X, Y2 ); + end; +end; + +procedure MakePlasma; +begin + Dec( W ); + Dec( H ); + mxPutPixel( X, Y, C1 ); + mxPutPixel( X, Y+H, C2 ); + mxPutPixel( X+W, Y+H, C3 ); + mxPutPixel( X+W, Y, C4 ); + Divide( X, Y, X+W, Y+H ); +end; + +procedure MakePlasmaPalette; +type + TPal = array[ byte ] of record R, G, B: byte end; +var + I: word; +begin + FillChar( TPal(Palette)[1], 192*3, 0 ); + case What of + PAL_CLOUDS: + for I:=1 to 192 do begin + TPal(Palette)[I].R := Abs( I-96 )*63 div 96; + TPal(Palette)[I].G := Abs( I-96 )*63 div 96; + TPal(Palette)[I].B := 63; + end; + PAL_LANDSCAPE: + begin + for I:=0 to 31 do begin + TPal(Palette)[I+1].R := I; + TPal(Palette)[I+1].G := I; + TPal(Palette)[I+1].B := I + I shr 1+15; + end; + for I:=32 to 63 do begin + TPal(Palette)[I+1].R := 0; + TPal(Palette)[I+1].G := I; + TPal(Palette)[I+1].B := 0; + end; + for I:=64 to 191 do begin + TPal(Palette)[I+1].R := (I-64) div 3 + 15; + TPal(Palette)[I+1].G := (I-64) div 3 + 15; + TPal(Palette)[I+1].B := (I-64) div 3 + 15; + end; + end; + else + for I:=1 to 64 do begin + TPal(Palette)[I].G := I-1; + TPal(Palette)[I].B := 64-I; + TPal(Palette)[I+64].R := I-1; + TPal(Palette)[I+64].G := 64-I; + TPal(Palette)[I+128].B := I-1; + TPal(Palette)[I+128].R := 64-I; + end; + end; +end; + +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 index 0000000000000000000000000000000000000000..a10d7db5a0a62654c70c632d8ce6b078a520613c GIT binary patch literal 10336 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 DJ^3nG literal 0 HcmV?d00001 diff --git a/16/xw/modex/QIX2.PAS b/16/xw/modex/QIX2.PAS new file mode 100755 index 00000000..d1b59791 --- /dev/null +++ b/16/xw/modex/QIX2.PAS @@ -0,0 +1,210 @@ +{$E-,N+} +uses Crt, Modex; + +const + DEFVERT = 12; (* Vertex count *) + DEFREPL = 3; (* Repetition count *) + DEFQIXS = 2; (* Qixs *) + FADESPEED = 48; +type + TPoint = record + X, Y : integer; + end; + TRGB = record + R, G, B: byte; + end; + TQix = record + Color: integer; + Vert : array[ 0..DEFVERT-1, 0..DEFREPL-1 ] of TPoint; + Delta: array[ 0..DEFVERT-1 ] of TPoint; + end; +var + Page : integer; + MaxX, + MaxY : word; + Qix : array[ 0..DEFQIXS-1 ] of TQix; + Pal : array[ byte ] of TRGB; + +type + TReal = double; + TRPoint = record + X, Y: TReal; + end; + TMatrix = array[ 0..3, 0..3 ] of TReal; +var + M: TMatrix; + G: array[ 0..DEFVERT-1 ] of TRPoint; + C: array[ 0..DEFVERT-1 ] of TRPoint; + +procedure BumpPal( Idx, DR, DG, DB, Steps: integer ); +var + I: integer; +begin + for I:=1 to Steps do begin + Pal[Idx+1].R := Pal[Idx].R + DR; + Pal[Idx+1].G := Pal[Idx].G + DG; + Pal[Idx+1].B := Pal[Idx].B + DB; + Inc( Idx ); + end; +end; + +procedure InitPalette; +begin + with Pal[0] do begin R:=0; G:=0; B:=0; end; + with Pal[1] do begin R:=0; G:=0; B:=62; end; + BumpPal( 1, 0, 2, -2, 31 ); + BumpPal( 32, 2, -2, 0, 31 ); + BumpPal( 63, -2, 2, 2, 31 ); + BumpPal( 94, 2, 0, -2, 31 ); + BumpPal( 125, -2, -2, 2, 31 ); +end; + +procedure Init( var Qix: TQix; Color: integer ); +var + I: integer; +begin + FillChar( Qix.Vert, SizeOf(Qix.Vert), 0 ); + for I:=0 to DEFVERT-1 do begin + Qix.Vert[I, DEFREPL-1].X := Random( MaxX ); + Qix.Vert[I, DEFREPL-1].Y := Random( MaxY ); + Qix.Delta[I].X := Random(5)+1; + Qix.Delta[I].Y := Random(5)+1; + end; + Qix.Color := Color; + + (* Initialize matrix (Catmull-Rom) *) + M[0,0] := -1/2; M[0,1] := 3/2; M[0,2] := -3/2; M[0,3] := 1/2; + M[1,0] := 1; M[1,1] := -5/2; M[1,2] := 2; M[1,3] := -1/2; + M[2,0] := -1/2; M[2,1] := 0; M[2,2] := 1/2; M[2,3] := 0; + M[3,0] := 0; M[3,1] := 1; M[3,2] := 0; M[3,3] := 0; +end; + +procedure mxBezier( var Qix: TQix; I0, Idx, N: integer ); +var + I, J: integer; + T, T2, T3: TReal; + X0, Y0, X, Y: TReal; + Delta: TReal; +begin + (* Compute coefficients *) + for I:=0 to 3 do begin + C[I].X := 0; + for J:=0 to 3 do C[I].X := C[I].X + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].X; + C[I].Y := 0; + for J:=0 to 3 do C[I].Y := C[I].Y + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].Y; + end; + X0 := C[3].X; + Y0 := C[3].Y; + Delta := 1 / N; + T := 0; + for I:=1 to N do begin + T := T + Delta; + T2 := T*T; + T3 := T*T2; + X := C[0].X*T3 + C[1].X*T2 + C[2].X*T + C[3].X; + Y := C[0].Y*T3 + C[1].Y*T2 + C[2].Y*T + C[3].Y; + mxLine( Round(X0), Page+Round(Y0), Round(X), Page+Round(Y), Qix.Color, OP_SET ); + X0 := X; + Y0 := Y; + end; +end; + +procedure Plot( var Qix: TQix; Idx: integer ); +var + I, J: integer; +begin + for I:=0 to DEFVERT-1 do begin + mxBezier( Qix, I, Idx, 12 ); + end; +end; + +procedure Update( var Qix: TQix; Idx: integer ); +var + I: integer; +begin + for I:=0 to DEFVERT-1 do with Qix do begin + Inc( Vert[I,Idx].X, Delta[I].X ); + if( Vert[I,Idx].X < 0 ) then begin + Vert[I,Idx].X := 0; + Delta[I].X := Random( 5 )+1; + end; + if( Vert[I,Idx].X > MaxX ) then begin + Vert[I,Idx].X := MaxX; + Delta[I].X := -Random( 5 )-1; + end; + Inc( Vert[I,Idx].Y, Delta[I].Y ); + if( Vert[I,Idx].Y < 0 ) then begin + Vert[I,Idx].Y := 0; + Delta[I].Y := Random( 5 )+1; + end; + if( Vert[I,Idx].Y > MaxY ) then begin + Vert[I,Idx].Y := MaxY; + Delta[I].Y := -Random( 5 )-1; + end; + end; +end; + +procedure Copy( var Qix: TQix; Dest, Src: integer ); +var + I: integer; +begin + for I:=0 to DEFVERT-1 do with Qix do begin + Vert[I,Dest].X := Vert[I,Src].X; + Vert[I,Dest].Y := Vert[I,Src].Y; + end; +end; + +procedure AnimateQix; +var + Q, Idx, I, J, P, Count: integer; +begin + Count := 0; + P := DEFREPL-1; + I := 0; + J := 1; + repeat + mxSetClipRegion( 0, Page, MaxX+1, MaxY+1 ); + mxSetClip( TRUE ); + mxFillBox( 0, Page, MaxX+1, MaxY+1, 0, OP_SET ); + for Q:=0 to DEFQIXS-1 do begin + Copy( Qix[Q], I, P ); + Update( Qix[Q], I ); + for Idx:=0 to DEFREPL-1 do begin + Plot( Qix[Q], Idx ); + end; + end; + I := (I+1) mod DEFREPL; + J := (J+1) mod DEFREPL; + P := (P+1) mod DEFREPL; + Inc( Count ); + mxStartLine( Page ); + if( Count >= FADESPEED ) then begin + for Q:=0 to DEFQIXS-1 do begin + Inc( Qix[Q].Color ); + if( Qix[Q].Color > 156 ) then + Qix[Q].Color := 1; + end; + Count := 0; + end; + Page := 240-Page; + until( KeyPressed ); +end; + +var + I: integer; +begin + Randomize; + mxInit; + mxSetMode( MX_320x240 ); + mxGetScreenSize( MaxX, MaxY ); + for I:=0 to DEFQIXS-1 do + Init( Qix[I], (I*(155 div DEFQIXS)) mod 155 + 1 ); + InitPalette; + mxSetPalette( @Pal, 0, 157 ); + Page := 240; + Dec( MaxX ); + Dec( MaxY ); + AnimateQix; + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw/modex/README.TXT b/16/xw/modex/README.TXT new file mode 100755 index 00000000..306e8b9a --- /dev/null +++ b/16/xw/modex/README.TXT @@ -0,0 +1,8 @@ +ModeX - A graphical library for DOS programs +Copyright (c) 1993-1994 Alessandro Scotti +http://www.ascotti.org/ + +Please look at the above site in the "Art of..." and +then in the "Old programs" section for more information. + + diff --git a/16/xw/modex/SINCOS.INC b/16/xw/modex/SINCOS.INC new file mode 100755 index 00000000..6986eeeb --- /dev/null +++ b/16/xw/modex/SINCOS.INC @@ -0,0 +1,518 @@ +; +; SINCOS.INC - Sin/cos tables for THREED.ASM +; + +tblSin LABEL DWORD + DD 0 + DD 411733 + DD 823219 + DD 1234209 + DD 1644455 + DD 2053710 + DD 2461729 + DD 2868265 + DD 3273072 + DD 3675909 + DD 4076531 + DD 4474698 + DD 4870169 + DD 5262706 + DD 5652074 + DD 6038037 + DD 6420363 + DD 6798821 + DD 7173184 + DD 7543226 + DD 7908725 + DD 8269459 + DD 8625213 + DD 8975771 + DD 9320922 + DD 9660458 + DD 9994176 + DD 10321873 + DD 10643353 + DD 10958422 + DD 11266890 + DD 11568571 + DD 11863283 + DD 12150850 + DD 12431097 + DD 12703856 + DD 12968963 + DD 13226258 + DD 13475586 + DD 13716797 + DD 13949745 + DD 14174291 + DD 14390298 + DD 14597637 + DD 14796184 + DD 14985817 + DD 15166424 + DD 15337895 + DD 15500126 + DD 15653022 + DD 15796488 + DD 15930439 + DD 16054795 + DD 16169479 + DD 16274424 + DD 16369565 + DD 16454846 + DD 16530216 + DD 16595628 + DD 16651044 + DD 16696429 + DD 16731757 + DD 16757007 + DD 16772163 + DD 16777216 + DD 16772163 + DD 16757007 + DD 16731757 + DD 16696429 + DD 16651044 + DD 16595628 + DD 16530216 + DD 16454846 + DD 16369565 + DD 16274424 + DD 16169479 + DD 16054795 + DD 15930439 + DD 15796488 + DD 15653022 + DD 15500126 + DD 15337895 + DD 15166424 + DD 14985817 + DD 14796184 + DD 14597637 + DD 14390298 + DD 14174291 + DD 13949745 + DD 13716797 + DD 13475586 + DD 13226258 + DD 12968963 + DD 12703856 + DD 12431097 + DD 12150850 + DD 11863283 + DD 11568571 + DD 11266890 + DD 10958422 + DD 10643353 + DD 10321873 + DD 9994176 + DD 9660458 + DD 9320922 + DD 8975771 + DD 8625213 + DD 8269459 + DD 7908725 + DD 7543226 + DD 7173184 + DD 6798821 + DD 6420363 + DD 6038037 + DD 5652074 + DD 5262706 + DD 4870169 + DD 4474698 + DD 4076531 + DD 3675909 + DD 3273072 + DD 2868265 + DD 2461729 + DD 2053710 + DD 1644455 + DD 1234209 + DD 823219 + DD 411733 + DD 0 + DD -411733 + DD -823219 + DD -1234209 + DD -1644455 + DD -2053710 + DD -2461729 + DD -2868265 + DD -3273072 + DD -3675909 + DD -4076531 + DD -4474698 + DD -4870169 + DD -5262706 + DD -5652074 + DD -6038037 + DD -6420363 + DD -6798821 + DD -7173184 + DD -7543226 + DD -7908725 + DD -8269459 + DD -8625213 + DD -8975771 + DD -9320922 + DD -9660458 + DD -9994176 + DD -10321873 + DD -10643353 + DD -10958422 + DD -11266890 + DD -11568571 + DD -11863283 + DD -12150850 + DD -12431097 + DD -12703856 + DD -12968963 + DD -13226258 + DD -13475586 + DD -13716797 + DD -13949745 + DD -14174291 + DD -14390298 + DD -14597637 + DD -14796184 + DD -14985817 + DD -15166424 + DD -15337895 + DD -15500126 + DD -15653022 + DD -15796488 + DD -15930439 + DD -16054795 + DD -16169479 + DD -16274424 + DD -16369565 + DD -16454846 + DD -16530216 + DD -16595628 + DD -16651044 + DD -16696429 + DD -16731757 + DD -16757007 + DD -16772163 + DD -16777216 + DD -16772163 + DD -16757007 + DD -16731757 + DD -16696429 + DD -16651044 + DD -16595628 + DD -16530216 + DD -16454846 + DD -16369565 + DD -16274424 + DD -16169479 + DD -16054795 + DD -15930439 + DD -15796488 + DD -15653022 + DD -15500126 + DD -15337895 + DD -15166424 + DD -14985817 + DD -14796184 + DD -14597637 + DD -14390298 + DD -14174291 + DD -13949745 + DD -13716797 + DD -13475586 + DD -13226258 + DD -12968963 + DD -12703856 + DD -12431097 + DD -12150850 + DD -11863283 + DD -11568571 + DD -11266890 + DD -10958422 + DD -10643353 + DD -10321873 + DD -9994176 + DD -9660458 + DD -9320922 + DD -8975771 + DD -8625213 + DD -8269459 + DD -7908725 + DD -7543226 + DD -7173184 + DD -6798821 + DD -6420363 + DD -6038037 + DD -5652074 + DD -5262706 + DD -4870169 + DD -4474698 + DD -4076531 + DD -3675909 + DD -3273072 + DD -2868265 + DD -2461729 + DD -2053710 + DD -1644455 + DD -1234209 + DD -823219 + DD -411733 +tblCos LABEL DWORD + DD 16777216 + DD 16772163 + DD 16757007 + DD 16731757 + DD 16696429 + DD 16651044 + DD 16595628 + DD 16530216 + DD 16454846 + DD 16369565 + DD 16274424 + DD 16169479 + DD 16054795 + DD 15930439 + DD 15796488 + DD 15653022 + DD 15500126 + DD 15337895 + DD 15166424 + DD 14985817 + DD 14796184 + DD 14597637 + DD 14390298 + DD 14174291 + DD 13949745 + DD 13716797 + DD 13475586 + DD 13226258 + DD 12968963 + DD 12703856 + DD 12431097 + DD 12150850 + DD 11863283 + DD 11568571 + DD 11266890 + DD 10958422 + DD 10643353 + DD 10321873 + DD 9994176 + DD 9660458 + DD 9320922 + DD 8975771 + DD 8625213 + DD 8269459 + DD 7908725 + DD 7543226 + DD 7173184 + DD 6798821 + DD 6420363 + DD 6038037 + DD 5652074 + DD 5262706 + DD 4870169 + DD 4474698 + DD 4076531 + DD 3675909 + DD 3273072 + DD 2868265 + DD 2461729 + DD 2053710 + DD 1644455 + DD 1234209 + DD 823219 + DD 411733 + DD 0 + DD -411733 + DD -823219 + DD -1234209 + DD -1644455 + DD -2053710 + DD -2461729 + DD -2868265 + DD -3273072 + DD -3675909 + DD -4076531 + DD -4474698 + DD -4870169 + DD -5262706 + DD -5652074 + DD -6038037 + DD -6420363 + DD -6798821 + DD -7173184 + DD -7543226 + DD -7908725 + DD -8269459 + DD -8625213 + DD -8975771 + DD -9320922 + DD -9660458 + DD -9994176 + DD -10321873 + DD -10643353 + DD -10958422 + DD -11266890 + DD -11568571 + DD -11863283 + DD -12150850 + DD -12431097 + DD -12703856 + DD -12968963 + DD -13226258 + DD -13475586 + DD -13716797 + DD -13949745 + DD -14174291 + DD -14390298 + DD -14597637 + DD -14796184 + DD -14985817 + DD -15166424 + DD -15337895 + DD -15500126 + DD -15653022 + DD -15796488 + DD -15930439 + DD -16054795 + DD -16169479 + DD -16274424 + DD -16369565 + DD -16454846 + DD -16530216 + DD -16595628 + DD -16651044 + DD -16696429 + DD -16731757 + DD -16757007 + DD -16772163 + DD -16777216 + DD -16772163 + DD -16757007 + DD -16731757 + DD -16696429 + DD -16651044 + DD -16595628 + DD -16530216 + DD -16454846 + DD -16369565 + DD -16274424 + DD -16169479 + DD -16054795 + DD -15930439 + DD -15796488 + DD -15653022 + DD -15500126 + DD -15337895 + DD -15166424 + DD -14985817 + DD -14796184 + DD -14597637 + DD -14390298 + DD -14174291 + DD -13949745 + DD -13716797 + DD -13475586 + DD -13226258 + DD -12968963 + DD -12703856 + DD -12431097 + DD -12150850 + DD -11863283 + DD -11568571 + DD -11266890 + DD -10958422 + DD -10643353 + DD -10321873 + DD -9994176 + DD -9660458 + DD -9320922 + DD -8975771 + DD -8625213 + DD -8269459 + DD -7908725 + DD -7543226 + DD -7173184 + DD -6798821 + DD -6420363 + DD -6038037 + DD -5652074 + DD -5262706 + DD -4870169 + DD -4474698 + DD -4076531 + DD -3675909 + DD -3273072 + DD -2868265 + DD -2461729 + DD -2053710 + DD -1644455 + DD -1234209 + DD -823219 + DD -411733 + DD 0 + DD 411733 + DD 823219 + DD 1234209 + DD 1644455 + DD 2053710 + DD 2461729 + DD 2868265 + DD 3273072 + DD 3675909 + DD 4076531 + DD 4474698 + DD 4870169 + DD 5262706 + DD 5652074 + DD 6038037 + DD 6420363 + DD 6798821 + DD 7173184 + DD 7543226 + DD 7908725 + DD 8269459 + DD 8625213 + DD 8975771 + DD 9320922 + DD 9660458 + DD 9994176 + DD 10321873 + DD 10643353 + DD 10958422 + DD 11266890 + DD 11568571 + DD 11863283 + DD 12150850 + DD 12431097 + DD 12703856 + DD 12968963 + DD 13226258 + DD 13475586 + DD 13716797 + DD 13949745 + DD 14174291 + DD 14390298 + DD 14597637 + DD 14796184 + DD 14985817 + DD 15166424 + DD 15337895 + DD 15500126 + DD 15653022 + DD 15796488 + DD 15930439 + DD 16054795 + DD 16169479 + DD 16274424 + DD 16369565 + DD 16454846 + DD 16530216 + DD 16595628 + DD 16651044 + DD 16696429 + DD 16731757 + DD 16757007 + DD 16772163 diff --git a/16/xw/modex/THREED.ASM b/16/xw/modex/THREED.ASM new file mode 100755 index 00000000..5ecd3ba3 --- /dev/null +++ b/16/xw/modex/THREED.ASM @@ -0,0 +1,872 @@ +COMMENT / + Fixed-point math functions and 3D transforms + Copyright (c) 1993,94 by Alessandro Scotti +/ +WARN PRO +P386 +JUMPS +LOCALS + +INCLUDE MATH.INC + +PUBLIC tdFixedMul +PUBLIC tdGetNormal +PUBLIC tdRotate +PUBLIC tdGetSurfaceLight +PUBLIC tdSetLight +PUBLIC tdSetRotation +PUBLIC tdSetTranslation +PUBLIC tdTransform +PUBLIC tdTransformToImage +PUBLIC tdTransformLight +PUBLIC tdBackPlaneCull +PUBLIC tdSetPerspective + +;----------------------------------------------------------- +; +; Data segment +; +MATH_DATA SEGMENT USE16 PARA PUBLIC 'DATA' + ASSUME ds:MATH_DATA + +INCLUDE SINCOS.INC ; Fixed 8:24 sin/cos table + +XRotation TPOINT <> ; 3x3 rotation matrix +YRotation TPOINT <> +ZRotation TPOINT <> + +Translation TPOINT <> ; Translation vector + +Light TPOINT <> ; Light vector +AmbientLight DW 00 ; Ambient light + +XScale DD 10000h ; Scaling factor for X coordinate +YScale DD 10000h ; Scaling factor for Y coordinate +PerspectiveDistance DD 20000000h + +MATH_DATA ENDS + +;----------------------------------------------------------- +; +; Code segment +; +MATH_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MATH_TEXT, es:NOTHING, fs:NOTHING + +tdSetPerspective PROC PASCAL FAR + ARG Perspective:DWORD, \ + ScaleX:DWORD, \ + ScaleY:DWORD + USES ds + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + mov eax, [Perspective] + mov [PerspectiveDistance], eax + mov eax, [ScaleX] + mov [XScale], eax + mov eax, [ScaleY] + mov [YScale], eax + + ret +tdSetPerspective ENDP + + +;----------------------------------------------------------- +; +; Sets the rotation matrix. +; +; Input: +; RX = X-axis rotation angle +; RY = X-axis rotation angle +; RZ = X-axis rotation angle +; Output: +; none +; +tdSetRotation PROC PASCAL FAR + ARG RX:WORD, \ + RY:WORD, \ + RZ:WORD + USES ds, si, di + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + mov bx, [RZ] + mov si, [RY] + mov di, [RX] + shl bx, 2 + shl si, 2 + shl di, 2 + + push ebp ; We use EBP as a scratch register + +; Set X rotation + mov eax, tblCos[bx] + imul tblCos[si] + mov [XRotation.X], edx + + mov eax, tblSin[bx] + imul tblCos[si] + mov [XRotation.Y], edx + + mov eax, tblSin[si] + sar eax, 8 ; Convert fixed 8:24 to fixed 16:16 + mov [XRotation.Z], eax + +; Set Y rotation + mov eax, tblCos[bx] + imul tblSin[si] ; EDX:EAX = fixed 16:48 + shrd eax, edx, 24 ; EAX = fixed 8:24 + imul tblSin[di] ; EDX:EAX = fixed 16:48 + mov ebp, eax + mov ecx, edx + mov eax, tblSin[bx] + imul tblCos[di] + add eax, ebp + adc edx, ecx ; EDX:EAX = fixed 16:48 + neg edx + mov [YRotation.X], edx + + mov eax, tblSin[bx] + imul tblSin[si] + shrd eax, edx, 24 + imul tblSin[di] + mov ebp, eax + mov ecx, edx + mov eax, tblCos[bx] + imul tblCos[di] + sub eax, ebp + sbb edx, ecx + mov [YRotation.Y], edx + + mov eax, tblCos[si] + imul tblSin[di] + mov [YRotation.Z], edx + +; Set Z rotation + mov eax, tblCos[bx] + imul tblSin[si] + shrd eax, edx, 24 + imul tblCos[di] + mov ebp, eax + mov ecx, edx + mov eax, tblSin[bx] + imul tblSin[di] + sub eax, ebp + sbb edx, ecx + mov [ZRotation.X], edx + + mov eax, tblSin[bx] + imul tblSin[si] + shrd eax, edx, 24 + imul tblCos[di] + mov ebp, eax + mov ecx, edx + mov eax, tblCos[bx] + imul tblSin[di] + add eax, ebp + add edx, ecx + neg edx + mov [ZRotation.Y], edx + + mov eax, tblCos[si] + imul tblCos[di] + mov [ZRotation.Z], edx + + pop ebp ; Restore EBP + + ret +tdSetRotation ENDP + +;----------------------------------------------------------- +; +; Sets the translation vector. +; +; Input: +; TV = pointer to translation vector +; Output: +; none +; +tdSetTranslation PROC PASCAL FAR + ARG TV:DWORD + USES ds, es, di + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + les di, [TV] + mov eax, es:[di].X + mov [Translation.X], eax + mov eax, es:[di].Y + mov [Translation.Y], eax + mov eax, es:[di].Z + mov [Translation.Z], eax + + ret +tdSetTranslation ENDP + +;----------------------------------------------------------- +; +; Transforms an array of TPOINT. +; +; Input: +; Source = pointer to source array of TPOINT +; Dest = pointer to destination array of TPOINT +; Count = number of entries to transform +; Output: +; none +; +tdTransform PROC PASCAL FAR + ARG Source:DWORD, \ + Dest:DWORD, \ + Count:WORD + LOCAL Adjust:DWORD + USES ds, si, es, di, fs + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + lfs si, [Source] + les di, [Dest] + + ALIGN DWORD +@@Loop: +; Transform Z coordinate + mov eax, fs:[si].X + imul [ZRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [ZRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [ZRotation.Z] + add eax, ecx + adc edx, ebx + mov ebx, eax + shrd eax, edx, 16 + add eax, [Translation.Z] ; EAX = new Z coord (fixed 16:16) + mov es:[di].Z, eax +; Get perspective factor + mov ebx, [PerspectiveDistance] + sub eax, ebx + neg eax ; EAX = PD - Z + xor edx, edx + shld edx, eax, 16 + shl eax, 16 + idiv ebx ; EAX = fixed 16:16 result + mov [Adjust], eax + +; Transform X coordinate + mov eax, fs:[si].X + imul [XRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [XRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [XRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + add eax, [Translation.X] + imul [Adjust] + shrd eax, edx, 16 + mov es:[di].X, eax + +; Transform Y coordinate + mov eax, fs:[si].X + imul [YRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [YRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [YRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + add eax, [Translation.Y] + imul [Adjust] + shrd eax, edx, 16 + mov es:[di].Y, eax + + add si, SIZE TPOINT + add di, SIZE TPOINT + dec [Count] + jnz @@Loop + + ret +tdTransform ENDP + +;----------------------------------------------------------- +; +; Transforms an array of TPOINT into an array of TIMAGEPOINT. +; +; Input: +; Source = pointer to source array of TPOINT +; Dest = pointer to destination array of TIMAGEPOINT +; Count = number of entries to transform +; DeltaX = translation distance for the X coordinate +; DeltaY = translation distance for the Y coordinate +; Output: +; the maximum Z value +; +tdTransformToImage PROC PASCAL FAR + ARG Source:DWORD, \ + Dest:DWORD, \ + Count:WORD, \ + DeltaX:WORD, \ + DeltaY:WORD + LOCAL Adjust:DWORD, \ + Max:DWORD + USES ds, si, es, di, fs + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + lfs si, [Source] + les di, [Dest] + mov [Max], 80000000h + +@@Loop: +; Check max Z + mov eax, fs:[si].Z + cmp eax, [Max] + jle @@1 + mov [Max], eax +@@1: + +; Transform X coordinate + mov ax, WORD PTR fs:[si].X[2] + add ax, [DeltaX] + mov es:[di].IX, ax + +; Transform Y coordinate + mov ax, WORD PTR fs:[si].Y[2] + add ax, [DeltaY] + mov es:[di].IY, ax + + add si, SIZE TPOINT + add di, SIZE TIMAGEPOINT + dec [Count] + jnz @@Loop + + mov eax, [Max] + shld edx, eax, 16 + ret +tdTransformToImage ENDP + +;----------------------------------------------------------- +; +; Sets the light source. +; +; Input: +; Light = pointer to light vector +; Output: +; none +; +tdSetLight PROC PASCAL FAR + ARG L:DWORD + USES ds, es, di + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + les di, [L] + mov eax, es:[di].X + mov [Light.X], eax + mov eax, es:[di].Y + mov [Light.Y], eax + mov eax, es:[di].Z + mov [Light.Z], eax + + ret +tdSetLight ENDP + +;----------------------------------------------------------- +; +; Computes light intensity for an array of surfaces. +; +; Input: +; Normals = pointer to an array of surface normals +; Lights = pointer to an array of integer to be filled with +; light intensity +; Count = number of elements to transform +; Output: +; none +; +tdTransformLight PROC PASCAL FAR + ARG Normals:DWORD, \ + Lights:DWORD, \ + Count:WORD + USES ds, si, es, di, fs + + mov ax, SEG MATH_DATA + mov fs, ax + ASSUME fs:MATH_DATA + + lds si, [Normals] + les di, [Lights] + ASSUME ds:NOTHING + +; Intensity is given by the dot product between the Light vector and +; the surface normal +@@Loop: + mov eax, ds:[si].Z + imul [Light.Z] + mov ebx, eax + mov ecx, edx + mov eax, ds:[si].Y + imul [Light.Y] + add ebx, eax + adc ecx, edx + mov eax, ds:[si].X + imul [Light.X] + add eax, ebx + adc edx, ecx ; EDX:EAX = fixed 32:32 intensity + add dx, [AmbientLight] + test dx, dx + jg @@1 + xor dx, dx ; Return 0 for no light +@@1: + mov es:[di], dx + inc di + inc di + add si, SIZE TPOINT + dec [Count] + jnz @@Loop + + ASSUME fs:NOTHING + ret +tdTransformLight ENDP + +;----------------------------------------------------------- +; +; Returns the light value given the normal to a surface. +; +; Input: +; Normal = pointer to TPOINT surface normal vector +; Output: +; AX = light intensity (>=0) +; Notes: +; the normal is rotated according to the current setting. +; +tdGetSurfaceLight PROC PASCAL FAR + ARG Normal:DWORD + USES ds, esi, es, di + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + les di, [Normal] + +; Transform Z coordinate + mov eax, es:[di].X + imul [ZRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, es:[di].Y + imul [ZRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, es:[di].Z + imul [ZRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + imul [Light.Z] + shrd eax, edx, 16 + mov esi, eax + +; Transform X coordinate + mov eax, es:[di].X + imul [XRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, es:[di].Y + imul [XRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, es:[di].Z + imul [XRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + imul [Light.X] + shrd eax, edx, 16 + add esi, eax + +; Transform Y coordinate + mov eax, es:[di].X + imul [YRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, es:[di].Y + imul [YRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, es:[di].Z + imul [YRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + imul [Light.X] + shrd eax, edx, 16 + add eax, esi + shr eax, 16 + +; Add ambient light + add ax, [AmbientLight] + test ax, ax + jge @@Exit + xor ax, ax + +@@Exit: + ret +tdGetSurfaceLight ENDP + +;----------------------------------------------------------- +; +; Rotates an array of TPOINT. +; +; Input: +; Source = pointer to source array of TPOINT +; Dest = pointer to destination array of TPOINT +; Count = number of entries to transform +; Output: +; none +; +tdRotate PROC PASCAL FAR + ARG Source:DWORD, \ + Dest:DWORD, \ + Count:WORD + USES ds, si, es, di, fs + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + lfs si, [Source] + les di, [Dest] + +@@Loop: +; Transform Z coordinate + mov eax, fs:[si].X + imul [ZRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [ZRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [ZRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + mov es:[di].Z, eax + +; Transform X coordinate + mov eax, fs:[si].X + imul [XRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [XRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [XRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + mov es:[di].X, eax + +; Transform Y coordinate + mov eax, fs:[si].X + imul [YRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [YRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [YRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + mov es:[di].Y, eax + + add si, SIZE TPOINT + add di, SIZE TPOINT + dec [Count] + jnz @@Loop + + ret +tdRotate ENDP + +tdFixedMul PROC PASCAL FAR + ARG F1:DWORD, \ + F2:DWORD + + mov eax, [F1] + imul [F2] + shr eax, 16 + + ret +tdFixedMul ENDP + +;----------------------------------------------------------- +; +; Returns in EAX the square root of EDX:EAX. +; +subSqrt PROC NEAR + push esi + push edi + + add eax, eax + adc edx, 0 + mov eax, edx ; Just discard the low bits + + mov esi, eax + xor edi, edi + shld edi, esi, 16 + shl esi, 16 +@@Loop: + mov ebx, eax + mul eax + add eax, esi + adc edx, edi + shrd eax, edx, 1 + shr edx, 1 + div ebx + cmp eax, ebx + jne @@Loop + +; Adjust EAX + shl eax, 8 + + pop edi + pop esi + ret +subSqrt ENDP + +;----------------------------------------------------------- +; +; Finds the unitary normal to a given surface. +; +; Input: +; Dest = pointer to TPOINT (vector) result +; P1, P2, P3 = pointer to TPOINT points on surface +; Output: +; none +; Notes: +; the normal is given by the cross-product between (P3-P1) and +; (P2-P1), so its orientation depends on the parameters order. +; +tdGetNormal PROC PASCAL FAR + ARG Dest:DWORD, \ + P1:DWORD, \ + P2:DWORD, \ + P3:DWORD + LOCAL V1:TPOINT, \ + V2:TPOINT, \ + N:TPOINT + USES ds, si, es, di + +; Get vector V1 + lds si, [P1] + les di, [P3] + mov eax, es:[di].X + sub eax, ds:[si].X + mov [V1.X], eax + mov eax, es:[di].Y + sub eax, ds:[si].Y + mov [V1.Y], eax + mov eax, es:[di].Z + sub eax, ds:[si].Z + mov [V1.Z], eax + +; Get vector V2 + les di, [P2] + mov eax, es:[di].X + sub eax, ds:[si].X + mov [V2.X], eax + mov eax, es:[di].Y + sub eax, ds:[si].Y + mov [V2.Y], eax + mov eax, es:[di].Z + sub eax, ds:[si].Z + mov [V2.Z], eax + +; Get normal vector (V1 x V2) + mov eax, [V1.Z] + imul [V2.Y] + mov ebx, eax + mov ecx, edx + mov eax, [V1.Y] + imul [V2.Z] + sub eax, ebx + sbb edx, ecx + shrd eax, edx, 16 + mov [N.X], eax + + mov eax, [V1.X] + imul [V2.Z] + mov ebx, eax + mov ecx, edx + mov eax, [V1.Z] + imul [V2.X] + sub eax, ebx + sbb edx, ecx + shrd eax, edx, 16 + mov [N.Y], eax + + mov eax, [V1.Y] + imul [V2.X] + mov ebx, eax + mov ecx, edx + mov eax, [V1.X] + imul [V2.Y] + sub eax, ebx + sbb edx, ecx + shrd eax, edx, 16 + mov [N.Z], eax + +; Get normal length + mov eax, [N.X] + imul eax + mov ebx, eax + mov ecx, edx + mov eax, [N.Y] + imul eax + add ebx, eax + adc ecx, edx + mov eax, [N.Z] + imul eax + add eax, ebx + adc edx, ecx ; EDX:EAX = N.X*N.X + N.Y*N.Y + N.Z*N.Z + call subSqrt ; EAX = normal length + mov ebx, eax + +; Adjust vector and save it + les di, [Dest] + mov eax, [N.X] + cdq + shld edx, eax, 16 + shl eax, 16 + idiv ebx + mov es:[di].X, eax + mov eax, [N.Y] + cdq + shld edx, eax, 16 + shl eax, 16 + idiv ebx + mov es:[di].Y, eax + mov eax, [N.Z] + cdq + shld edx, eax, 16 + shl eax, 16 + idiv ebx + mov es:[di].Z, eax + + ret +tdGetNormal ENDP + +TPOLY STRUC + Vtx DW 4 DUP(?) +TPOLY ENDS + +;----------------------------------------------------------- +; +; Performs surface removal on an array of polygons. +; +; Input: +; Poly = pointer to an array of TPOLY +; Vertex = pointer to an array of TPOINT +; Dest = pointer to an array of integer +; Count = number of polygons to check +; Step = size of TPOLY structure +; Output: +; if the n-th polygon is invisible the n-th entry of the +; Dest array is set to -1, other entries are not modified +; (so it's possible to use the Light array for Dest, because +; the light intensity is always >= 0) +; +tdBackPlaneCull PROC PASCAL FAR + ARG Step:WORD, \ + Poly:DWORD, \ + Vertex:DWORD, \ + Dest:DWORD, \ + Count:WORD + USES ds, si, es, di, fs + ASSUME ds:NOTHING + + mov ds, WORD PTR Vertex[2] + les di, [Poly] + mov fs, WORD PTR Dest[2] + +@@Loop: + mov ax, es:[di].Vtx[2] ; Index of 2nd vertex + shl ax, 2 + mov bx, ax + shl ax, 1 + add bx, ax ; BX = index*SIZE TPOINT + add bx, WORD PTR [Vertex] ; BX = offset of 2nd vertex + mov ax, es:[di].Vtx[4] ; Index of 3rd vertex + shl ax, 2 + mov si, ax + shl ax, 1 + add si, ax + add si, WORD PTR [Vertex] ; SI = offset of 3rd vertex + mov ecx, ds:[si].X + sub ecx, ds:[bx].X ; ECX = V3.X-V2.X + mov edx, ds:[si].Y + sub edx, ds:[bx].Y ; EDX = V3.Y-V2.Y + mov ax, es:[di].Vtx[0] ; Index of 1st vertex + shl ax, 2 + mov si, ax + shl ax, 1 + add si, ax + add si, WORD PTR [Vertex] ; SI = offset of 1st vertex + mov eax, ds:[si].X + sub eax, ds:[bx].X ; EAX = V1.X-V2.X + mov esi, ds:[si].Y + sub esi, ds:[bx].Y ; ESI = V1.Y-V2.Y + imul edx + mov ebx, eax + xchg ecx, edx ; ECX:EBX = (V1.X-V2.X)*(V3.Y-V2.Y) + mov eax, esi + imul edx ; EDX:EAX = (V1.Y-V2.Y)*(V3.X-V2.X) + sub eax, ebx + sbb edx, ecx + jl @@Next ; Polygon is visible + mov bx, WORD PTR [Dest] ; FS:BX -> current Dest entry + mov WORD PTR fs:[bx], -1 ; Remove polygon +@@Next: + add WORD PTR [Dest], 2 ; Next entry for dest + add di, [Step] ; Next polygon + dec [Count] + jnz @@Loop + + ret +tdBackPlaneCull ENDP + +MATH_TEXT ENDS +END diff --git a/16/xw/modex/THREED.H b/16/xw/modex/THREED.H new file mode 100755 index 00000000..b993ef86 --- /dev/null +++ b/16/xw/modex/THREED.H @@ -0,0 +1,32 @@ +typedef struct { + long x, y, z; +} TVECTOR; + +#define PVECTOR TVECTOR far * + +#define TPOINT TVECTOR +#define PPOINT PVECTOR + +#define VPTR void far * + +#ifdef __cplusplus +extern "C" { +#endif + +long far pascal tdFixedMul( long, long ); +int far pascal tdGetSurfaceLight( PPOINT ); +long far pascal tdTransformToImage( VPTR, VPTR, short, short, short ); + +void far pascal tdBackPlaneCull( VPTR, VPTR, VPTR, short, short ); +void far pascal tdGetNormal( VPTR, PPOINT, PPOINT, PPOINT ); +void far pascal tdRotate( VPTR, VPTR, short ); +void far pascal tdSetLight( PVECTOR ); +void far pascal tdSetRotation( short, short, short ); +void far pascal tdSetTranslation( PVECTOR ); +void far pascal tdSetPerspective( long, long, long ); +void far pascal tdTransform( VPTR, VPTR, short ); +void far pascal tdTransformLight( VPTR, VPTR, short ); + +#ifdef __cplusplus +} +#endif diff --git a/16/xw/modex/THREED.PAS b/16/xw/modex/THREED.PAS new file mode 100755 index 00000000..8b712c9d --- /dev/null +++ b/16/xw/modex/THREED.PAS @@ -0,0 +1,40 @@ +unit ThreeD; +interface + +type + TVector = record + X, Y, Z : longint; + end; + TPoint = TVector; + +function tdFixedMul( F1, F2: longint ): longint; +function tdGetSurfaceLight( var Normal: TPoint ): integer; +function tdTransformToImage( var Source, Dest; Count, DeltaX, DeltaY: integer ): longint; + +procedure tdBackPlaneCull( var Poly, Vertex, Dest; Count, Step: word ); +procedure tdGetNormal( var Dest, P1, P2, P3: TVector ); +procedure tdRotate( var Source, Dest; Count: word ); +procedure tdSetLight( var Light: TVector ); +procedure tdSetRotation( RX, RY, RZ: word ); +procedure tdSetTranslation( var TV: TVector ); +procedure tdSetPerspective( PD, XF, YF: longint ); +procedure tdTransform( var Source, Dest; Count: word ); +procedure tdTransformLight( var Source, Dest; Count: word ); + +implementation + +function tdGetSurfaceLight; external; +procedure tdSetRotation( RX, RY, RZ: word ); external; +procedure tdGetNormal; external; +procedure tdSetTranslation( var TV: TVector ); external; +procedure tdTransform( var Source, Dest; Count: word ); external; +procedure tdRotate; external; +function tdTransformToImage; external; +procedure tdSetLight( var Light: TVector ); external; +procedure tdSetPerspective; external; +procedure tdTransformLight; external; +function tdFixedMul( F1, F2: longint ): longint; external; +procedure tdBackPlaneCull; external; +{$L THREED} + +end. diff --git a/16/xw/modex/demo01.c b/16/xw/modex/demo01.c new file mode 100755 index 00000000..0c9f3b02 --- /dev/null +++ b/16/xw/modex/demo01.c @@ -0,0 +1,140 @@ +/* + * DEMO01 - Sprites, page flipping and palette rotation + * Copyright (c) 1994 Alessandro Scotti + */ +#include ../../x/modex.h + +#DEFINE MAX_SPRITE 100 + +typedef unsigned char byte; +typedef unsigned short word; +typedef unsigned long dword; + +/* Sprite structure */ +typedef struct { + int X, Y; /* Sprite coordinates */ + int DX,DY; /* Deltas for sprite movement */ + int W, H; /* Sprite width and height */ + byte Image[16,16]; /* Sprite image data */ +} TSprite; + +/* RGB color structure */ +typedef struct { + byte R, G, B; +} TRgb; +Tsprite S[MAX_SPRITE]; /* An array of sprites */ +TRgb Palette[ byte ]; /* Palette */ +word Page; /* Page offset */ +word i; + +/* Initializes a sprite structure */ +void sxInit(TSprite *S) +{ +//word i; + +S->X = rand( 320 ); /* Initialize position with random values */ +S->Y = rand( 240 ); +S->DX = rand( 7 )-3; /* Initialize speed with random values */ +S->DY = rand( 7 )-3; +S->W = 16; /* Size is fixed in this program */ +S->H = 16; +/* The image is a square with a hole inside */ +FillChar( S->Image, SizeOf(S->Image), rand(15)+1 ); + for(i=5; i<=12;i++) + { + FillChar( S->Image[ i, 5 ], 8, 0 ); + } +} + +/* Moves a sprite */ +void sxMove(TSprite *S) +{ +//Inc( S.X, S.DX ); /* Get new position */ +//Inc( S.Y, S.DY ); +/* Check sprite position, change delta if needed */ +if( S->X > 320 ){ + S->X = 320; +S->DX = -S->DX; +} +if( S->X < -16 ){ + S->X = -16; +S->DX = -S->DX; +} +if( S->Y > 240 ){ + S.Y = 240; + S->DY = -S->DY; +} +if( S->Y < -16 ){ + S->Y = -16; + S->DY = -S->DY; +} +/* Draw the sprite, note the Page offset added to the */ +/* Y coordinate of the image */ +mxPutImage( S.Image, S->X, Page+S->Y, S->W, S->H, OP_TRANS ); +} + +void main() +{ + int i; + //TSprite S; + /* Initialize library */ + mxInit(); + + /* Enter graphics mode */ + mxSetMode( MX_320x240 ); + + /* Print initialization message */ + mxSetTextColor( 15, OP_TRANS ); + mxOutStr( 4, 4, 'Initializing...' ); + + /* Initialize sprites */ + for(i=1;i<=MAX_SPRITE;i++) + sxInit( &S[i] ); + + /* Draw background */ + for(i=1;i<=192;i++) + { + mxCircle( 160, 480+120, I, I+63 ); + mxCircle( 161, 480+120, I, I+63 ); + } + + /* Compute and set palette */ + for(i=1;i<= 192;Palette[i+63]) + { + short R = 0; + short G = 0; + short B = 0; + if( i < 64 ) + R = i >> 1+31; + else if( i < 128 ) + G = (i-64) >> 1+31; + else + B = (i-128) >> 1+31; + } + mxSetPalette( @Palette[64], 64, 192 ); + + /* Main loop */ + short Page = 240; + while(!kbhit()) + { + /* Set clip region to current page */ + mxSetClipRegion( 0, Page, 320, 240 ); + mxSetClip( TRUE ); + /* Restore background */ + mxBitBlt( 0, 480, 320, 240, 0, Page ); + /* Draw sprites */ + for(i=1; i <= MAX_SPRITE; sxMove( S[i] )); + /* Print message */ + mxOutStr( 4, Page+4, 'Some sprites moving...' ); + /* Flip page */ + mxStartLine( Page ); + Page = 240-Page; + /* Animate palette */ + mxSetPalette( @Palette[64], 64, 192 ); + mxRotatePalette( @Palette[64], 192, 3 ); + } + + mxSetMode( MX_TEXT ); + mxTerm; + +} diff --git a/16/xw/mxbb.asm b/16/xw/mxbb.asm new file mode 100755 index 00000000..ed24a27c --- /dev/null +++ b/16/xw/mxbb.asm @@ -0,0 +1,278 @@ +;----------------------------------------------------------- +; +; MXBB.ASM - Bit block transfer +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +;WARN PRO +;NOWARN RES +INCLUDE modex.def + +PUBLIC mxBitBlt + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN subHorizontalLineInfo : NEAR + +EXTRN mx_VideoSegment : WORD +EXTRN mx_BytesPerLine : WORD + +;----------------------------------------------------------- +; +; Moves a block of video memory. +; +; Input: +; SX, SY = source coordinates +; Width = source width +; Height = source height +; DX, DY = destination coordinates +; Output: +; none +; +; Note: overlapping regions are not allowed. +; +mxBitBlt PROC FAR + ARG DestY:WORD, \ + DestX:WORD, \ + Height:WORD, \ + Width:WORD, \ + SY:WORD, \ + SX:WORD = ARG_SIZE + LOCAL PlaneWidth:WORD:4, \ + SourceOffset:WORD, \ + DestOffset:WORD, \ + Count:BYTE, \ + ReadPlane:BYTE, \ + WritePlane:BYTE, \ + LeftMask:BYTE, \ + RightMask:BYTE = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, es, di + +; Exit now if null width + cmp [Width], 0 + je @@Exit + +; Calls the proper procedure to handle transfer + mov ax, [SX] + and al, 03h ; AL = source plane + mov dx, [DestX] + and dl, 03h ; DL = destination plane + mov bx, OFFSET subPlaneBlt + cmp al, dl ; Same source and destination plane? + jne @@BitBlt ; No, use slow procedure + mov bx, OFFSET subMoveBlt +@@BitBlt: + call bx + +@@Exit: + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE + +;----------------------------------------------------------- +; Uses write mode 1 for maximum speed. Only works if source +; and destination are plane-aligned. +; +subMoveBlt PROC NEAR +; Get horizontal line info and address of destination + mov bx, [DestX] + mov ax, [DestY] + mov cx, [Width] + call subHorizontalLineInfo + mov [LeftMask], al + mov [RightMask], ah + mov [Width], cx + +; Setup segments + mov ax, [mx_VideoSegment] + mov ds, ax + mov es, ax + +; Get address of source pixel + mov ax, [SY] + mul [mx_BytesPerLine] + mov si, [SX] + .shr si, 2 + add si, ax + +; Set write mode 1 + mov dx, GDC + mov ax, 4105h + out dx, ax + cld + +; Move left block +@@L0: + mov ah, [LeftMask] + or ah, ah + jz @@C0 + mov dx, TS + mov al, 02h + out dx, ax ; Set write plane mask + mov ax, [mx_BytesPerLine] + dec ax + mov cx, [Height] + .push si, di +@@L1: + movsb + add si, ax + add di, ax + dec cx + jnz @@L1 + .pop si, di + inc si + inc di + +; Move center block +@@C0: + mov bx, [Width] + test bx, bx + jz @@R0 + mov dx, TS + mov ax, 0F02h + out dx, ax ; Enable all planes + mov ax, [mx_BytesPerLine] + sub ax, bx + mov dx, [Height] + .push si, di +@@C1: + mov cx, bx ; CX = image width + rep movsb ; Cannot use "movsw" here! + add si, ax ; Next scan line + add di, ax ; Next scan line + dec dx ; All lines processed? + jnz @@C1 ; No, continue + .pop si, di + add si, bx + add di, bx + +; Move right block +@@R0: + mov ah, [RightMask] + or ah, ah + jz @@Done + mov dx, TS + mov al, 02h + out dx, ax ; Set write plane mask + mov ax, [mx_BytesPerLine] + dec ax + mov cx, [Height] +@@R1: + movsb + add si, ax + add di, ax + dec cx + jnz @@R1 + +@@Done: + mov dx, GDC + mov ax, 4005h + out dx, ax ; Restore write mode 0 + +@@Exit: + ret +subMoveBlt ENDP + +;----------------------------------------------------------- +; Moves one plane at a time. +; +subPlaneBlt PROC NEAR +; Compute extra bytes and width count for each plane + mov cx, [Width] + mov bx, cx + shr bx, 1 + shr bx, 1 ; Width for each plane + and cl, 03h + mov al, 00001000b + shr al, cl + mov si, 3 SHL 1 +@@PatchLoop: + mov PlaneWidth[si], bx + shr al, 1 + adc bx, 0 + dec si + dec si + jge @@PatchLoop + +; Get pixel addresses + mov ax, [mx_VideoSegment] + mov ds, ax + mov es, ax + mov ax, [SY] + mul [mx_BytesPerLine] + mov si, [SX] + shr si, 1 + shr si, 1 + add si, ax ; DS:SI points to source + mov [SourceOffset], si + mov ax, [DestY] + mul [mx_BytesPerLine] + mov di, [DestX] + shr di, 1 + shr di, 1 + add di, ax ; ES:DI points to destination + mov [DestOffset], di + +; Adjust plane for output to VGA registers + mov ax, [SX] + and al, 03h + mov [ReadPlane], al + mov cx, [DestX] + and cl, 03h + mov al, 00010001b + shl al, cl + mov [WritePlane], al + +; Ready to move now + cld + mov [Count], 4 ; Four planes + lea bx, PlaneWidth ; SS:[BX] = width in bytes for plane +@@PlaneLoop: + cmp WORD PTR ss:[bx], 0 + je @@Done + mov ah, [WritePlane] + and ah, 0Fh + mov al, 02h + mov dx, TS + out dx, ax ; Select write plane + mov ah, [ReadPlane] + mov al, 04h + mov dx, GDC + out dx, ax ; Select read plane + mov dx, [Height] + mov ax, [mx_BytesPerLine] + sub ax, ss:[bx] ; AX = extra bytes per line +@@Loop: + mov cx, ss:[bx] + shr cx, 1 + rep movsw + rcl cx, 1 + rep movsb + add si, ax + add di, ax + dec dx + jnz @@Loop ; Repeat for all lines + inc bx + inc bx ; Select width for next plane + inc [ReadPlane] + and [ReadPlane], 03h ; Should be faster on 386 using + jnz @@ReadPlaneOk ; BTR and ADC... + inc [SourceOffset] +@@ReadPlaneOk: + rol [WritePlane], 1 + adc [DestOffset], 0 + mov si, [SourceOffset] + mov di, [DestOffset] + dec [Count] + jnz @@PlaneLoop ; Repeat for all planes + +@@Done: + ret +subPlaneBlt ENDP + +mxBitBlt ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxcc.asm b/16/xw/mxcc.asm new file mode 100755 index 00000000..4f78adb9 --- /dev/null +++ b/16/xw/mxcc.asm @@ -0,0 +1,644 @@ +;----------------------------------------------------------- +; +; MXCC.ASM - Fast clip line function +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC xsubClipLine + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD +EXTRN mx_VideoSegment : WORD + +EXTRN mx_ClipX1 : WORD +EXTRN mx_ClipY1 : WORD +EXTRN mx_ClipX2 : WORD +EXTRN mx_ClipY2 : WORD + +tblGroups LABEL WORD + DW 10, tbl00 + DW 10, tbl10 + DW 9, tbl20 + DW -1, 0 + DW 10, tbl40 + DW 10, tbl50 + DW 9, tbl60 + DW -1, 0 + DW 6, tbl80 + DW 6, tbl90 + DW 5, tblA0 + DW -1, 0 + DW -1, 0 + DW -1, 0 + DW -1, 0 + DW -1, 0 +tbl00 DW cc00, cc01, cc02, ccFF, cc04, cc05, cc06, ccFF, cc08, cc09, cc0A +tbl10 DW cc10, ccFF, cc12, ccFF, cc14, ccFF, cc16, ccFF, cc18, ccFF, cc1A +tbl20 DW cc20, cc21, ccFF, ccFF, cc24, cc25, ccFF, ccFF, cc28, cc29 +tbl40 DW cc40, cc41, cc42, ccFF, ccFF, ccFF, ccFF, ccFF, cc48, cc49, cc4A +tbl50 DW cc50, ccFF, cc52, ccFF, ccFF, ccFF, ccFF, ccFF, cc58, ccFF, cc5A +tbl60 DW cc60, cc61, ccFF, ccFF, ccFF, ccFF, ccFF, ccFF, cc68, cc69 +tbl80 DW cc80, cc81, cc82, ccFF, cc84, cc85, cc86 +tbl90 DW cc90, ccFF, cc92, ccFF, cc94, ccFF, cc96 +tblA0 DW ccA0, ccA1, ccFF, ccFF, ccA4, ccA5 + +ccTT: clc + ret +ccFF: stc + ret + +; Group 00 ------------------------------------------------- +; +cc00: + clc + ret +cc01: + jmp ClipQLeft +cc02: + jmp ClipQRight +cc04: + jmp ClipQTop +cc05: + call ClipQLeft + cmp si, [mx_ClipY1] + jge ccTT + jmp ClipQTop +cc06: + call ClipQRight + cmp si, [mx_ClipY1] + jge ccTT + jmp ClipQTop +cc08: + jmp ClipQBottom +cc09: + call ClipQLeft + cmp si, [mx_ClipY2] + jle ccTT + jmp ClipQBottom +cc0A: + call ClipQRight + cmp si, [mx_ClipY2] + jle ccTT + jmp ClipQBottom + +; Group 10 ------------------------------------------------- +; +cc10FF: + stc + ret +cc10TT: + clc + ret +cc10: + jmp ClipPLeft +cc12: + call ClipPLeft + jmp ClipQRight +cc14: + call ClipPLeft + cmp bx, [mx_ClipY1] + jl cc10FF + jmp ClipQTop +cc16: + call ClipPLeft + cmp bx, [mx_ClipY1] + jl cc10FF + call ClipQTop + cmp cx, [mx_ClipX2] + jle cc10TT + jmp ClipQRight +cc18: + call ClipPLeft + cmp bx, [mx_ClipY2] + jg cc10FF + jmp ClipQBottom +cc1A: + call ClipPLeft + cmp bx, [mx_ClipY2] + jg cc10FF + call ClipQBottom + cmp cx, [mx_ClipX2] + jle cc10TT + jmp ClipQRight + +; Group 20 ------------------------------------------------- +; +cc20TT: + clc + ret +cc20FF: + stc + ret +cc20: + jmp ClipPRight +cc21: + call ClipPRight + jmp ClipQLeft +cc24: + call ClipPRight + cmp bx, [mx_ClipY1] + jl cc20FF + jmp ClipQTop +cc25: + call ClipPRight + cmp bx, [mx_ClipY1] + jl cc20FF + call ClipQTop + cmp cx, [mx_ClipX1] + jge cc20TT + jmp ClipQLeft +cc28: + call ClipPRight + cmp bx, [mx_ClipY2] + jg cc20FF + jmp ClipQBottom +cc29: + call ClipPRight + cmp bx, [mx_ClipY2] + jg cc20FF + call ClipQBottom + cmp cx, [mx_ClipX1] + jge cc20TT + jmp ClipQLeft + +; Group 40 ------------------------------------------------- +; +cc40TT: + clc + ret +cc40FF: + stc + ret +cc40: + jmp ClipPTop +cc41: + call ClipPTop + cmp di, [mx_ClipX1] + jl cc40FF + call ClipQLeft + cmp si, [mx_ClipY1] + jge cc40TT + jmp ClipQTop +cc42: + call ClipPTop + cmp di, [mx_ClipX2] + jg cc40FF + jmp ClipQRight +cc48: + call ClipPTop + jmp ClipQBottom +cc49: + call ClipPTop + cmp di, [mx_ClipX1] + jl cc40FF + call ClipQLeft + cmp si, [mx_ClipY2] + jle cc40TT + jmp ClipQBottom +cc4A: + call ClipPTop + cmp di, [mx_ClipX2] + jg cc40FF + call ClipQRight + cmp si, [mx_ClipY2] + jle cc40TT + jmp ClipQBottom + + +; Group 50 ------------------------------------------------- +; +cc50TT: + clc + ret +cc50FF: + stc + ret +cc50: + call ClipPLeft + cmp bx, [mx_ClipY1] + jge cc50TT + jmp ClipPTop +cc52: + call ClipQRight + cmp si, [mx_ClipY1] + jl cc50FF + call ClipPTop + cmp di, [mx_ClipX1] + jge cc50TT + jmp ClipPLeft +cc58: + call ClipQBottom + cmp cx, [mx_ClipX1] + jl cc50FF + call ClipPTop + cmp di, [mx_ClipX1] + jge cc50TT + jmp ClipPLeft +cc5A: + call ClipPLeft + cmp bx, [mx_ClipY2] + jg cc50FF + call ClipQRight + cmp bx, [mx_ClipY1] + jl cc50FF + cmp si, [mx_ClipY2] + jle cc50TT + jmp ClipQBottom + +; Group 60 ------------------------------------------------- +; +cc60TT: + clc + ret +cc60FF: + stc + ret +cc60: + call ClipPRight + cmp bx, [mx_ClipY1] + jge cc60TT + jmp ClipPTop +cc61: + call ClipQLeft + cmp si, [mx_ClipY2] + jl cc60FF + call ClipPTop + cmp di, [mx_ClipX2] + jle cc60TT + jmp ClipPRight +cc68: + call ClipQBottom + cmp cx, [mx_ClipX2] + jg cc60FF + call ClipPRight + cmp bx, [mx_ClipY1] + jge cc60TT + jmp ClipPTop +cc69: + call ClipQLeft + cmp si, [mx_ClipY1] + jl cc60FF + call ClipPRight + cmp bx, [mx_ClipY2] + jg cc60FF + cmp si, [mx_ClipY2] + jle cc69_1 + call ClipQBottom +cc69_1: + cmp bx, [mx_ClipY1] + jge cc60TT + jmp ClipPTop + +; Group 80 ------------------------------------------------- +; +cc80TT: + clc + ret +cc80FF: + stc + ret +cc80: + jmp ClipPBottom +cc81: + call ClipPBottom + cmp di, [mx_ClipX1] + jl cc80FF + jmp ClipQLeft +cc82: + call ClipPBottom + cmp di, [mx_ClipX2] + jg cc80FF + jmp ClipQRight +cc84: + call ClipPBottom + jmp ClipQTop +cc85: + call ClipPBottom + cmp di, [mx_ClipX1] + jl cc80FF + call ClipQLeft + cmp si, [mx_ClipY1] + jge cc80FF + jmp ClipQTop +cc86: + call ClipPBottom + cmp di, [mx_ClipX2] + jg cc80FF + call ClipQRight + cmp si, [mx_ClipY1] + jge cc80TT + jmp ClipQTop + +; Group 90 ------------------------------------------------- +; +cc90TT: + clc + ret +cc90FF: + stc + ret +cc90: + call ClipPLeft + cmp bx, [mx_ClipY2] + jle cc90TT + jmp ClipPBottom +cc92: + call ClipQRight + cmp si, [mx_ClipY2] + jg cc90FF + call ClipPBottom + cmp di, [mx_ClipX1] + jge cc90TT + jmp ClipPLeft +cc94: + call ClipQTop + cmp cx, [mx_ClipX1] + jl cc90FF + call ClipPLeft + cmp bx, [mx_ClipY2] + jle cc90TT + jmp ClipPBottom +cc96: + call ClipPLeft + cmp bx, [mx_ClipY1] + jl cc90FF + call ClipQRight + cmp si, [mx_ClipY2] + jg cc90FF + cmp bx, [mx_ClipY2] + jle cc96_1 + call ClipPBottom +cc96_1: + cmp si, [mx_ClipY1] + jge cc90TT + jmp ClipQTop + +; Group A0 ------------------------------------------------- +; +ccA0TT: + clc + ret +ccA0FF: + stc + ret +ccA0: + call ClipPRight + cmp bx, [mx_ClipY2] + jle ccA0TT + jmp ClipPBottom +ccA1: + call ClipQLeft + cmp si, [mx_ClipY2] + jg ccA0FF + call ClipPBottom + cmp di, [mx_ClipX2] + jle ccA0TT + jmp ClipPRight +ccA4: + call ClipQTop + cmp cx, [mx_ClipX2] + jg ccA0FF + call ClipPRight + cmp bx, [mx_ClipY2] + jle ccA0TT + jmp ClipPBottom +ccA5: + call ClipQLeft + cmp si, [mx_ClipY2] + jg ccA0FF + call ClipPRight + cmp bx, [mx_ClipY1] + jl ccA0FF + cmp si, [mx_ClipY1] + jge ccA5_1 + call ClipQTop +ccA5_1: + cmp bx, [mx_ClipY2] + jle ccA0TT + jmp ClipPBottom + +; Y1 = (Y2-Y1)*(mx_ClipX1-X1)/(X2-X1)+Y1 = (SI-BX)*(mx_ClipX1-DI)/(CX-DI)+BX +; X1 = mx_ClipX1 +ClipPLeft: + mov ax, si + sub ax, bx + mov dx, [mx_ClipX1] + sub dx, di + imul dx + mov bp, cx + sub bp, di + idiv bp + add bx, ax + mov di, [mx_ClipX1] + clc + ret + +; Y1 = (Y2-Y1)*(mx_ClipX2-X1)/(X2-X1)+Y1 = (SI-BX)*(mx_ClipX2-DI)/(CX-DI)+BX +; X1 = mx_ClipX2 +ClipPRight: + mov ax, si + sub ax, bx + mov dx, [mx_ClipX2] + sub dx, di + imul dx + mov bp, cx + sub bp, di + idiv bp + add bx, ax + mov di, [mx_ClipX2] + clc + ret + +; X1 = (X2-X1)*(mx_ClipY2-Y1)/(Y2-Y1)+X1 = (CX-DI)*(mx_ClipY2-BX)/(SI-BX)+DI +; Y1 = mx_ClipY2 +ClipPBottom: + mov ax, cx + sub ax, di + mov dx, [mx_ClipY2] + sub dx, bx + imul dx + mov bp, si + sub bp, bx + idiv bp + add di, ax + mov bx, [mx_ClipY2] + clc + ret + +; X1 = (X2-X1)*(mx_ClipY1-Y1)/(Y2-Y1)+X1 = (CX-DI)*(mx_ClipY1-BX)/(SI-BX)+DI +; Y1 = mx_ClipY1 +ClipPTop: + mov ax, cx + sub ax, di + mov dx, [mx_ClipY1] + sub dx, bx + imul dx + mov bp, si + sub bp, bx + idiv bp + add di, ax + mov bx, [mx_ClipY1] + clc + ret + +; Y2 = (Y1-Y2)*(mx_ClipX1-X2)/(X1-X2)+Y2 = (BX-SI)*(mx_ClipX1-CX)/(DI-CX)+SI +; X2 = mx_ClipX1 +ClipQLeft: + mov ax, bx + sub ax, si + mov dx, [mx_ClipX1] + sub dx, cx + imul dx + mov bp, di + sub bp, cx + idiv bp + add si, ax + mov cx, [mx_ClipX1] + clc + ret + +; Y2 = (Y1-Y2)*(mx_ClipX2-X2)/(X1-X2)+Y2 = (BX-SI)*(mx_ClipX2-CX)/(DI-CX)+SI +; X2 = mx_ClipX1 +ClipQRight: + mov ax, bx + sub ax, si + mov dx, [mx_ClipX2] + sub dx, cx + imul dx + mov bp, di + sub bp, cx + idiv bp + add si, ax + mov cx, [mx_ClipX2] + clc + ret + +; X2 = (X1-X2)*(mx_ClipY2-Y2)/(Y1-Y2)+X2 = (DI-CX)*(mx_ClipY2-SI)/(BX-SI)+CX +; Y2 = mx_ClipY1 +ClipQBottom: + mov ax, di + sub ax, cx + mov dx, [mx_ClipY2] + sub dx, si + imul dx + mov bp, bx + sub bp, si + idiv bp + add cx, ax + mov si, [mx_ClipY2] + clc + ret + +; X2 = (X1-X2)*(mx_ClipY1-Y2)/(Y1-Y2)+X2 = (DI-CX)*(mx_ClipY1-SI)/(BX-SI)+CX +; Y2 = mx_ClipY1 +ClipQTop: + mov ax, di + sub ax, cx + mov dx, [mx_ClipY1] + sub dx, si + imul dx + mov bp, bx + sub bp, si + idiv bp + add cx, ax + mov si, [mx_ClipY1] + clc + ret + +;----------------------------------------------------------- +; +; Checks the coordinates of a line against the active +; clip region. +; Uses the Sobkow-Pospisil-Yang (SPY) algorithm: this was +; supposed to be twice as fast as Cohen-Sutherland, but my +; tests show only a very small increase in speed and a noticeable +; increase of the program size! Maybe this is caused by the +; slow speed of VGA cards, so probably a better test should +; be performed with lines drawn in RAM. +; +; Input: +; AX, BX = X1, Y1 +; CX, DX = X2, Y2 +; Output: +; CF = set if line is full clipped +; AX, BX = clipped X1, Y1 +; CX, DX = clipped X2, Y2 +; Note: +; destroys SI, DI +; +xsubClipLine PROC NEAR + push bp + xor si, si ; SPY code + + cmp dx, [mx_ClipY2] + jle @@1 + or si, 08h + jmp @@2 +@@1: + cmp dx, [mx_ClipY1] + jge @@2 + or si, 04h +@@2: + + cmp cx, [mx_ClipX2] + jle @@3 + or si, 02h + jmp @@4 +@@3: + cmp cx, [mx_ClipX1] + jge @@4 + or si, 01h +@@4: + + cmp bx, [mx_ClipY2] + jle @@5 + or si, 80h + jmp @@6 +@@5: + cmp bx, [mx_ClipY1] + jge @@6 + or si, 40h +@@6: + + cmp ax, [mx_ClipX2] + jle @@7 + or si, 20h + jmp @@8 +@@7: + cmp ax, [mx_ClipX1] + jge @@8 + or si, 10h +@@8: + + mov di, si + and di, 000Fh ; Index of procedure + and si, 00F0h + .shr si, 2 ; Index of group (times 4) + cmp di, cs:tblGroups[si] ; Is index within range? + jg @@Exit ; No, line is full clipped + mov si, cs:tblGroups[si+2] ; Get offset of group table + shl di, 1 ; We must index word elements + add si, di ; Make full offset + mov di, ax ; Move X1 to DI and free AX + mov si, cs:[si] ; Get subroutine address + xchg dx, si ; Move Y2 to SI and free DX + call dx ; Call the proper subroutine + mov ax, di ; Restore AX to X1 + mov dx, si ; Restore DX to Y2 + pop bp + ret + +@@Exit: + pop bp + stc + ret +xsubClipLine ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxcg.asm b/16/xw/mxcg.asm new file mode 100755 index 00000000..42163d7a --- /dev/null +++ b/16/xw/mxcg.asm @@ -0,0 +1,69 @@ +;----------------------------------------------------------- +; +; MXCG.ASM - Color to gray conversion +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxColorToGray + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Converts RGB colors to gray shades. +; +; Input: +; CPal = pointer to color palette +; GPal = pointer to destination (gray) palette +; Count = number of colors to convert +; Output: +; none +; +; Note: CPal and GPal may point to the same buffer. +; +mxColorToGray PROC FAR + ARG Count:WORD, \ + DPal:DWORD, \ + SPal:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si, es, di + + mov cx, [Count] + jcxz @@Exit + lds si, [SPal] + les di, [DPal] + cld +; We use the standard formula +; gray=(red*30 + green*59 + blue*11)/100 +; in the equivalent form +; gray=(red*77 + green*151 + blue*28)/256 +; which doesn't need the last divide. + mov bx, 77 SHL 8 + 151 +@@Loop: + lodsb ; Red + mul bh + mov dx, ax + lodsb ; Green + mul bl + add dx, ax + lodsb ; Blue + mov ah, 28 + mul ah + add ax, dx + mov al, ah + stosw ; Save new RGB + stosb + loop @@Loop + +@@Exit: + .pop ds, si, es, di + .leave ARG_SIZE +mxColorToGray ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxcl.asm b/16/xw/mxcl.asm new file mode 100755 index 00000000..aaa0bac3 --- /dev/null +++ b/16/xw/mxcl.asm @@ -0,0 +1,151 @@ +;----------------------------------------------------------- +; +; MXCL.ASM - Bresenham circle +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxCircle + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD +EXTRN mx_VideoSegment : WORD +EXTRN mx_ClipX1 : WORD +EXTRN mx_ClipY1 : WORD +EXTRN mx_ClipX2 : WORD +EXTRN mx_ClipY2 : WORD + +;----------------------------------------------------------- +; +; Draws a circle using the Bresenham algorithm. +; +; Input: +; XC, YC = center coordinates +; Radius = circle radius +; Color = circle color +; Output: +; none +; Note: +; computes only points in the first octant, all other +; points are obtained by symmetry. +; +mxCircle PROC FAR + ARG Color:BYTE:2, \ + Radius:WORD, \ + YC:WORD, \ + XC:WORD = ARG_SIZE + LOCAL Delta:WORD = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, di + + xor si, si ; X + mov di, [Radius] ; Y + mov ax, 3 + sub ax, di + sub ax, di + mov [Delta], ax ; Delta = 3-R*2 + + mov ds, [mx_VideoSegment] + +@@Loop: + cmp si, di ; + jg @@Done ; Exit when X > Y +; Draw points + mov ax, si + mov bx, di + call @@subPutPixel + mov ax, si + neg ax + mov bx, di + call @@subPutPixel + mov ax, si + mov bx, di + neg bx + call @@subPutPixel + mov ax, si + neg ax + mov bx, di + neg bx + call @@subPutPixel + mov ax, di + mov bx, si + call @@subPutPixel + mov ax, di + neg ax + mov bx, si + call @@subPutPixel + mov ax, di + mov bx, si + neg bx + call @@subPutPixel + mov ax, di + neg ax + mov bx, si + neg bx + call @@subPutPixel +; Moves coordinates to next point + mov ax, [Delta] + test ax, ax + jl @@Next + mov ax, di + .shl ax, 2 + sub ax, 4 + sub [Delta], ax + dec di +@@Next: + mov ax, si + .shl ax, 2 + add ax, 6 + add [Delta], ax + inc si + jmp @@Loop + +@@Done: + xor ax, ax + .pop ds, si, di + .leave ARG_SIZE + +;--------------------------------------- +; Put pixel function. +; Input: +; BX = X coordinate (relative to center) +; AX = Y coordinate (relative to center) +; DS = video segment +@@subPutPixel: + add bx, [XC] ; Get absolute coordinates + add ax, [YC] + + cmp bx, [mx_ClipX1] ; Clip pixel + jl @@subExit + cmp bx, [mx_ClipX2] + jg @@subExit + cmp ax, [mx_ClipY1] + jl @@subExit + cmp ax, [mx_ClipY2] + jg @@subExit + + mul [mx_BytesPerLine] ; Get pixel offset + mov cx, bx ; Save X coordinate + .shr bx, 2 + add bx, ax ; DS:BX = pixel offset + + and cl, 3 ; Set write plane + mov ax, 0102h + shl ah, cl + mov dx, TS + out dx, ax + + mov al, [Color] ; Write pixel + mov ds:[bx], al + +@@subExit: + retn +mxCircle ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxcr.asm b/16/xw/mxcr.asm new file mode 100755 index 00000000..ca1fa7bb --- /dev/null +++ b/16/xw/mxcr.asm @@ -0,0 +1,380 @@ +;----------------------------------------------------------- +; +; MXCR.ASM - Clip functions +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxSetSysClipRegion +PUBLIC mxGetClipRegion +PUBLIC mxSetClipRegion +PUBLIC mxSetClip +PUBLIC mxGetClip + +PUBLIC subClipBox +PUBLIC subClipImage + +PUBLIC mx_ClipX1 +PUBLIC mx_ClipY1 +PUBLIC mx_ClipX2 +PUBLIC mx_ClipY2 + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_CodeSegment : WORD + +mx_ClipX1 DW ? ; Clip coordinates +mx_ClipY1 DW ? +mx_ClipX2 DW ? +mx_ClipY2 DW ? + +mx_SysClipX1 DW ? ; System clip coordinates +mx_SysClipY1 DW ? ; (active when mx_ClipStatus is FALSE) +mx_SysClipX2 DW ? +mx_SysClipY2 DW ? + +mx_UserClipX1 DW ? ; User clip coordinates +mx_UserClipY1 DW ? ; (active when mx_ClipStatus is TRUE) +mx_UserClipX2 DW ? +mx_UserClipY2 DW ? + +mx_ClipStatus DB ? + +;----------------------------------------------------------- +; +; Toggles clipping between user and system regions. +; +; Input: +; ClipStatus = TRUE (FALSE) to enable (disable) clipping +; Output: +; AX = old clip status +; +mxSetClip PROC FAR + ARG ClipStatus:BYTE:2 = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, [mx_UserClipX1] + mov bx, [mx_UserClipY1] + mov cx, [mx_UserClipX2] + mov dx, [mx_UserClipY2] + cmp [ClipStatus], TRUE + je @@Done + mov ax, [mx_SysClipX1] + mov bx, [mx_SysClipY1] + mov cx, [mx_SysClipX2] + mov dx, [mx_SysClipY2] +@@Done: + mov [mx_ClipX1], ax + mov [mx_ClipY1], bx + mov [mx_ClipX2], cx + mov [mx_ClipY2], dx + + mov al, [ClipStatus] + xchg al, [mx_ClipStatus] + xor ah, ah + + .pop ds + .leave ARG_SIZE +mxSetClip ENDP + +;----------------------------------------------------------- +; +; Returns the current clipping status. +; +; Input: +; none +; Output: +; TRUE (FALSE) if clipping enabled (disabled) +; +mxGetClip PROC FAR + ASSUME ds:NOTHING + mov al, [mx_ClipStatus] + xor ah, ah + ret +mxGetClip ENDP + +;----------------------------------------------------------- +; +; Sets the system clip region and disables user clipping. +; +; Input: +; Width = width in pixels of clip region +; Height = height in pixels of clip region +; Output: +; old clip status. +; +mxSetSysClipRegion PROC FAR + ARG Height:WORD, \ + Width:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + xor ax, ax ; Sys clip region always starts at (0,0) + mov [mx_SysClipX1], ax + mov [mx_SysClipY1], ax + mov ax, [Width] + dec ax + mov [mx_SysClipX2], ax + mov ax, [Height] + dec ax + mov [mx_SysClipY2], ax + + IF USE286 EQ TRUE + push FALSE + ELSE + mov ax, FALSE + push ax + ENDIF + call mxSetClip + + .pop ds + .leave ARG_SIZE +mxSetSysClipRegion ENDP + +;----------------------------------------------------------- +; +; Sets the clip region. +; +; Input: +; X, Y = coordinates of top left corner of clip region +; Width = width in pixels of clip region +; Height = height in pixels of clip region +; Output: +; none (no checking on parameters) +; +mxSetClipRegion PROC FAR + ARG Height:WORD, \ + Width:WORD, \ + Y:WORD, \ + X:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, [X] + mov [mx_UserClipX1], ax + mov ax, [Y] + mov [mx_UserClipY1], ax + mov ax, [Width] + add ax, [X] + dec ax + mov [mx_UserClipX2], ax + mov ax, [Height] + add ax, [Y] + dec ax + mov [mx_UserClipY2], ax + + mov al, [mx_ClipStatus] + cmp al, TRUE + jne @@Exit + push ax + call mxSetClip + +@@Exit: + xor ax, ax + .pop ds + .leave ARG_SIZE +mxSetClipRegion ENDP + +;----------------------------------------------------------- +; +; Returns the current user clip region. +; +; Input: +; X, Y = pointers to integer coordinates of top left corner +; Width = pointer to word width of clip region +; Height = pointer to word height of clip region +; Output: +; AX = current clip status +; +mxGetClipRegion PROC FAR + ARG Height:DWORD, \ + Width:DWORD, \ + Y:DWORD, \ + X:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push es, di + + mov ax, [mx_UserClipX1] + les di, [X] + mov es:[di], ax + mov ax, [mx_UserClipY1] + les di, [Y] + mov es:[di], ax + + mov ax, [mx_UserClipX2] + sub ax, [mx_UserClipX1] + inc ax + les di, [Width] + mov es:[di], ax + mov ax, [mx_UserClipY2] + sub ax, [mx_UserClipY1] + inc ax + les di, [Height] + mov es:[di], ax + + mov al, [mx_ClipStatus] + xor ah, ah + .pop es, di + .leave ARG_SIZE +mxGetClipRegion ENDP + +;----------------------------------------------------------- +; +; Internal use: checks the coordinates of a rectangle against +; the active clip region. +; This function assumes that a "raw" image has to be clipped, +; so it returns in SI the number of "raw" bytes to skip if +; X, Y were clipped. +; +; Input: +; BX, AX = X, Y coordinates of rectangle (signed) +; CX = box width +; DX = box height +; Output: +; CF = set if rectangle is full clipped +; BX, AX = new X, Y coordinates of rectangle +; CX, DX = clipped width and height +; SI = number of bytes to skip before copying a buffer +; DI destroyed +; +subClipImage PROC NEAR + ASSUME ds:NOTHING + xor si, si + +; Check clip height + mov di, [mx_ClipY1] + cmp ax, di + jge @@CheckBottom + sub di, ax ; Number of lines to clip + sub dx, di ; New box height + jle @@Exit + mov ax, di + mov di, dx ; Save box height into DI + mul cx ; DX:AX = number of bytes to skip + mov si, ax + mov dx, di ; Restore box height + mov ax, [mx_ClipY1] +@@CheckBottom: + mov di, [mx_ClipY2] + cmp ax, di + jg @@Exit + inc di + sub di, dx + sub di, ax + jge @@DoneHeight ; None, continue + add dx, di ; Clip lines +@@DoneHeight: + +; Check clip width +@@CheckLeft: + mov di, [mx_ClipX1] + cmp bx, di + jge @@CheckRight + sub di, bx ; Number of columns to clip left + sub cx, di + jle @@Exit + add si, di ; Update skip count + mov bx, [mx_ClipX1] +@@CheckRight: + mov di, [mx_ClipX2] + cmp bx, di + jg @@Exit + inc di + sub di, bx + sub di, cx + jge @@DoneWidth ; None, exit + add cx, di ; New box width +@@DoneWidth: + +; Set return flag and exit +@@Done: + clc + ret +@@Exit: + stc + ret +subClipImage ENDP + +;----------------------------------------------------------- +; +; Internal use: checks the coordinates of a rectangle against +; the active clip region. +; +; Input: +; BX, AX = X, Y coordinates of rectangle (signed) +; CX = box width +; DX = box height +; Output: +; CF = set if rectangle is full clipped +; BX, AX = new X, Y coordinates of rectangle +; CX, DX = clipped width and height +; DI destroyed +; +subClipBox PROC NEAR + ASSUME ds:NOTHING + +; Check clip height + mov di, [mx_ClipY1] + cmp ax, di + jge @@CheckBottom + sub di, ax ; Number of lines to clip + sub dx, di ; New box height + jle @@Exit + mov ax, [mx_ClipY1] +@@CheckBottom: + mov di, [mx_ClipY2] + cmp ax, di + jg @@Exit + inc di + sub di, dx + sub di, ax ; Clipped some point? + jge @@DoneHeight ; No, continue + add dx, di ; Clip lines (DI is negative) +@@DoneHeight: + +; Check clip width +@@CheckLeft: + mov di, [mx_ClipX1] + cmp bx, di + jge @@CheckRight + sub di, bx ; Number of columns to clip left + sub cx, di + jle @@Exit + mov bx, [mx_ClipX1] +@@CheckRight: + mov di, [mx_ClipX2] + cmp bx, di + jg @@Exit + inc di + sub di, bx + sub di, cx ; Clipped some point? + jge @@DoneWidth ; No, exit + add cx, di ; New box width (DI is negative) +@@DoneWidth: + +; Set return flag and exit +@@Done: + clc + ret +@@Exit: + stc + ret +subClipBox ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxel.asm b/16/xw/mxel.asm new file mode 100755 index 00000000..2c9dda2a --- /dev/null +++ b/16/xw/mxel.asm @@ -0,0 +1,167 @@ +;----------------------------------------------------------- +; +; MXEL.ASM - Mid-point ellipse +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxEllipse + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD +EXTRN mx_VideoSegment : WORD +EXTRN mx_ClipX1 : WORD +EXTRN mx_ClipY1 : WORD +EXTRN mx_ClipX2 : WORD +EXTRN mx_ClipY2 : WORD + +;----------------------------------------------------------- +; +; Draws an ellipse using the mid-point algorithm. +; +; Input: +; XC, YC = center coordinates +; A = horizontal radius +; B = vertical radius +; Color = ellipse color +; Output: +; none +; Note: +; computes only points in the first quadrant, all other +; points are obtained by symmetry. +; +mxEllipse PROC FAR + ARG Color:BYTE:2, \ + B:WORD, \ + A:WORD, \ + YC:WORD, \ + XC:WORD = ARG_SIZE + LOCAL A2:DWORD, \ + B2:DWORD, \ + CC:DWORD, \ + DD:DWORD, \ + X:DWORD, \ + Y:DWORD = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, di + + .chk386 mxEllipse, @@Exit + +; Initialize variables + xor eax, eax + mov [X], ax ; X = 0 + mov ax, [A] + mul eax ; EAX = A*A + mov [DD], eax ; DD = A*A + shl eax, 1 + mov [CC], eax ; CC = 2*A*A + shl eax, 1 + mov [A2], eax ; A2 = 4*A*A + movzx edx, [B] + mov [Y], edx + mul edx ; EAX = 4*A*A*B + sub [DD], eax ; DD = A*A - 4*A*A*B + movzx eax, [B] + mul eax ; EAX = B*B + shl eax, 2 ; EAX = 4*B*B + mov [B2], eax ; B2 = 4*B*B + add [CC], eax ; CC = 2*A*A + 4*B*B + add [D1], eax ; DD = A*A - 4*A*A*B + 4*B*B + +; Draw initial points + call subPlot4 + +; First loop +@@Loop1: + mov eax, [X] ; Check slope + mul [B2] + mov ecx, eax + mov eax, [Y] + mul [A2] + sub eax, ecx + sub eax, [CC] ; EAX = Y*A2 - X*B2 - CC + jle @@Done1 ; Crossed critical point, jump to next loop + + mov ecx, [DD] ; Get error + test ecx, ecx ; Positive? + jl @@Draw1 ; No, use default step + + mov eax, 1 + sub eax, [Y] + mul [A2] + shl eax, 1 + add ecx, eax ; Bump error + dec WORD PTR [Y] ; Decrement Y coordinate + +@@Draw1: + mov eax, [X] + shl eax, 1 + add eax, 3 + mul [B2] + add ecx, eax ; Bump error + mov [DD], ecx ; Save error + inc WORD PTR [X] ; Increment X coordinate + + call subPlot4 ; Draw points + jmp @@Loop1 +@@Done1: + +; Initialize variables + shr [B2], 2 + mov eax, [X] + mul eax + add [X] + shl eax, 2 + inc eax + mul [B2] + mov [DD], eax + mov eax, [Y] + mul eax + add [Y] + dec eax + add [Y] + sub eax, [B2] + add [DD], eax + shl [B2], 3 + inc WORD PTR [X] + +; Second loop +@@Loop2: + cmp WORD PTR [Y], 0 + ja @@Done2 + + mov ecx, [DD] + test ecx, ecx + jge @@Draw2 + + mov eax, [X] + inc eax + mul [B2] + add ecx, eax + inc WORD PTR [X] + +@@Draw2: + mov eax, [Y] + shl eax, 1 + sub eax, 3 + neg eax + imul [A2] + add ecx, eax + dec WORD PTR [Y] + + call subPlot4 + jmp @@Loop2 +@@Done2: + +@@Exit: + xor ax, ax + .leave ARG_SIZE +mxEllipse ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxfb.asm b/16/xw/mxfb.asm new file mode 100755 index 00000000..41ea5deb --- /dev/null +++ b/16/xw/mxfb.asm @@ -0,0 +1,194 @@ +;----------------------------------------------------------- +; +; MXFB.ASM - Fill box function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxFillBox + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD +EXTRN mx_VideoSegment : WORD +EXTRN subClipBox : NEAR +EXTRN subHorizontalLineInfo : NEAR + +;----------------------------------------------------------- +; +; Raster op functions. Raster op is limited to OP_MOVE, +; OP_AND, OP_OR and OP_XOR. The VGA hardware is used to +; perform the selected logical functions on up to four +; pixel at a time. +; +subRepFill PROC NEAR + mov ah, al + shr cx, 1 + rep stosw + rcl cx, 1 + rep stosb + ret +subRepFill ENDP +; +subFill PROC NEAR +@@Loop: + mov ds:[bx], al + add bx, dx + loop @@Loop + ret +subFill ENDP +; +subRepMove PROC NEAR + mov si, di +@@Loop: + mov ah, ds:[si] ; Dummy read to latch the data + mov ds:[si], al + inc si + loop @@Loop + ret +subRepMove ENDP +; +subMove PROC NEAR +@@Loop: + mov ah, ds:[bx] ; Dummy read to latch the data + mov ds:[bx], al + add bx, dx + loop @@Loop + ret +subMove ENDP + +;----------------------------------------------------------- +; +; Fills a rectangle with a specified color. +; +; Input: +; X, Y = X, Y coordinates of rectangle +; Width = width of rectangle +; Height = height of rectangle +; Color = fill color +; Op = raster operator +; Output: +; none +; +; Note: raster op is limited to OP_MOVE, OP_AND, OP_OR and OP_XOR. +; +mxFillBox PROC FAR + ARG Op:WORD, \ + Color:BYTE:2, \ + Height:WORD, \ + Width:WORD, \ + Y:WORD, \ + X:WORD = ARG_SIZE + LOCAL LeftMask:BYTE, \ + RightMask:BYTE, \ + FillFunction:WORD, \ + RepFillFunction:WORD = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, es, di + ASSUME ds:NOTHING + +; Clip rectangle + mov bx, [X] + mov ax, [Y] + mov cx, [Width] + mov dx, [Height] + call subClipBox + jc @@Exit ; Full clipped + + mov [Height], dx ; Save clipped height + call subHorizontalLineInfo ; Get additional info, init DI + mov [Width], cx + mov [LeftMask], al + mov [RightMask], ah + +; Initialize segments + mov ax, [mx_VideoSegment] + mov es, ax ; ES:DI points to pixel + mov ds, ax + cld ; Clear direction flag + +; Select fill functions + mov [FillFunction], OFFSET subFill + mov [RepFillFunction], OFFSET subRepFill + mov ax, [Op] ; Get raster op + cmp al, OP_XOR + ja @@1 ; Assume it's a fill + cmp al, OP_MOVE + je @@1 + .shl al, 3 + mov ah, al + mov al, 03h + mov dx, GDC + out dx, ax ; Set GDC logical function + mov [FillFunction], OFFSET subMove + mov [RepFillFunction], OFFSET subRepMove +@@1: + +; Fill left block +@@L0: + mov ah, [LeftMask] + or ah, ah + jz @@C0 ; Nothing to do, go to center block + mov dx, TS + mov al, 02h + out dx, ax ; Set write plane mask + mov dx, [mx_BytesPerLine] + mov cx, [Height] + mov bx, di + mov al, [Color] + call [FillFunction] ; Fill this column + inc di ; Update starting video offset + +; Fill center block +@@C0: + mov cx, [Width] + jcxz @@R0 ; Nothing to do, go to right block + mov dx, TS + mov ax, 0F02h + out dx, ax ; Write to all planes + mov al, [Color] + mov bx, di + mov dx, [Height] + push di ; Save pixel address +@@C1: + mov di, bx ; Update video offset + call [RepFillFunction] ; Fill current scan line + mov cx, [Width] ; Restore byte count + add bx, [mx_BytesPerLine] ; Bump to next scan line + dec dx ; Done all lines? + jnz @@C1 ; No, continue + pop di ; Restore pixel address + add di, [Width] ; Go to right block + +; Fill right block +@@R0: + mov ah, [RightMask] + or ah, ah + jz @@Done ; Nothing to do, exit + mov dx, TS + mov al, 02h + out dx, ax ; Set write plane mask + mov dx, [mx_BytesPerLine] + mov cx, [Height] + mov bx, di + mov al, [Color] + call [FillFunction] ; Fill this column + +; Restore VGA registers +@@Done: + mov dx, GDC + mov ax, 0003h + out dx, ax ; Set logical function to "move" + +@@Exit: + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxFillBox ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxfp.asm b/16/xw/mxfp.asm new file mode 100755 index 00000000..8eea25be --- /dev/null +++ b/16/xw/mxfp.asm @@ -0,0 +1,326 @@ +;----------------------------------------------------------- +; +; MXFP.ASM - Fade palette function +; Copyright (c) 1992-1994 ARTIS s.r.l. +; Author: Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxFadePalette + +MAXCOLOR EQU 256 +FADE_IN EQU 0 +FADE_OUT EQU 1 + +; The actual speed of fading depends on the number of passes (FADE_SPEED) and +; the delay between two consecutive passes (FADE_DELAY). Below are the +; default values, used when no parameters are specified. +; +FADE_DELAY EQU 1 ; Vert. retraces between video updates +FADE_SPEED EQU 48 ; Speed of effect (max 127) + +; Bit field record for fade commands +; +FADE_COMMAND RECORD fpDELAY:8,fpSPEED:7,fpDIRECTION:1 + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +DB 'Copyright (c) 1992-1994 ARTIS s.r.l. All rights reserved.' + +;----------------------------------------------------------- +; +; Fades a VGA palette. +; +; Input: +; Buffer = pointer to source/destination palette +; Command = fading direction and optional parameters +; Start = index of first color to fade +; Count = number of color to fade +; Red = destination red +; Green = destination green +; Blue = destination blue +; Output: +; none +; Notes: +; - about 1.5 Kbytes of stack space are needed for internal buffers; +; - the Command argument usually is 0 to fade in and 1 to fade out, +; however additional parameters may be specified. To set the effect +; speed, i.e. the number of iterations needed to completely fade a +; palette, shift the value one bit left and "or" it with the +; direction bit (range is 0..127). To set the delay between two +; consecutive passes, shift it eight bits left (range is 0..255). +; +mxFadePalette PROC FAR + ARG bBlue:WORD, \ + bGreen:WORD, \ + bRed:WORD, \ + wCount:WORD, \ + wStartIdx:WORD, \ + wCommand:WORD, \ + vfpPalette:DWORD = ARG_SIZE + LOCAL bSPalette:BYTE:MAXCOLOR*3, \ + bDPalette:BYTE:MAXCOLOR*3, \ + bLoopIndex:BYTE, \ + bLoopStep:BYTE, \ + bLoopCount:BYTE, \ + wDelay:WORD, \ + wSpeed:WORD = AUTO_SIZE + ASSUME ds:NOTHING + .enter AUTO_SIZE + .push si, di, ds, es ; Save registers +; +; Check parameters and setup variables +; +@@GetDelay: + mov [wDelay], FADE_DELAY ; Set default delay + mov ax, [wCommand] ; Get command word + and ax, MASK fpDELAY ; Mask delay command + jz @@GetSpeed ; No command, get speed + IF USE286 EQ TRUE + shr ax, fpDELAY + ELSE + mov cl, fpDELAY ; Get size of delay field + shr ax, cl ; Right justify the field + ENDIF + mov [wDelay], ax ; Set new delay + +@@GetSpeed: + mov ax, [wCommand] ; Get command + and ax, MASK fpSPEED ; Mask speed + IF USE286 EQ TRUE + shr ax, fpSPEED + ELSE + mov cl, fpSPEED ; Get size of speed field + shr ax, cl ; Right justify the field + ENDIF + or ax, ax ; Any speed specified? + jnz @@SetVariables ; Yes, set variables + mov ax, FADE_SPEED ; Set default speed + +@@SetVariables: + mov [wSpeed], ax ; Set speed + inc ax ; Number of iterations + mov [bLoopCount], al ; Set loop count + mov [bLoopStep], 1 ; Assume we're fading in + mov [bLoopIndex], 0 +; +; Check bounds for bad values +; + mov ax, [wStartIdx] ; Get first index + cmp ax, MAXCOLOR ; Is in the valid range? + jae @@Exit ; No, exit + add ax, [wCount] ; Get last index + cmp ax, MAXCOLOR ; Is in the valid range? + jbe @@BoundsOk ; Yes, continue + mov ax, MAXCOLOR + sub ax, [wStartIdx] + mov [wCount], ax ; Set count to maximum value + or ax, ax + jz @@Exit ; Nothing to do, exit +@@BoundsOk: +; +; Copy the source palette in a local array: if we fade in it's ready to +; use, otherwise we'll overwrite it later +; + mov cx, [wCount] + mov ax, cx + shl ax, 1 + add cx, ax ; CX = wCount * 3 + mov ax, ss + mov es, ax + lea di, [bSPalette] ; ES:DI points to local palette + mov ax, [wStartIdx] + mov si, ax + shl ax, 1 + add ax, si + lds si, [vfpPalette] ; DS:SI points to user palette + add si, ax ; Skip unused entries + cld + shr cx, 1 + rep movsw + rcl cx, 1 + rep movsb +; +; Check direction +; + test [wCommand], MASK fpDIRECTION ; Are we fading in? + jz @@Main ; Yes, ok to continue + mov ax, [wSpeed] ; Get speed + mov [bLoopIndex], al ; Exchange first and last index + mov [bLoopStep], -1 ; Move backward + mov ax, ss ; Overwrite our copy of + mov ds, ax ; user palette with the + mov es, ax ; current active palette + lea di, [bSPalette] + mov ax, [wStartIdx] + mov cx, [wCount] + call ReadPalette ; Read current palette +; +; Prepare variables and registers for fading +; +@@Main: + mov bh, BYTE PTR [bRed] ; Destination red + and bh, 00111111b ; Be sure it's a valid VGA value + mov bl, BYTE PTR [bGreen] ; Destination green + and bl, 00111111b ; Be sure it's a valid VGA value + mov dh, BYTE PTR [bBlue] ; Destination blue + and dh, 00111111b ; Be sure it's a valid VGA value + mov dl, [bLoopIndex] ; Loop index + mov ax, ss ; All tables are stored + mov ds, ax ; in the stack segment, + mov es, ax ; set DS and ES +; +; Main loop +; +@@Loop: + mov ax, [wCount] ; Store count in AX + mov cx, [wSpeed] ; Set maximum speed in CX + lea si, [bSPalette] ; DS:SI points to source palette + lea di, [bDPalette] ; ES:DI points to dest. palette + call RecalcPalette ; Build a faded palette + + .push bx, dx ; Save registers we need + lea si, [bDPalette] ; DS:SI points to palette + mov ax, [wStartIdx] ; First index to write + mov bx, [wCount] ; Total entries to write + mov cx, [wDelay] ; Fade delay between updates + call WritePalette ; Write palette + .pop bx, dx ; Restore BX and DX + + add dl, [bLoopStep] ; Change fade intensity + dec [bLoopCount] ; Done? + jnz @@Loop ; No, loop again + +@@Exit: + .pop si, di, ds, es ; Restore registers + .leave ARG_SIZE +mxFadePalette ENDP + +;------- INTERNAL USE ONLY ------------------------------------------------ +; +; Calculates a partially faded palette. +; +; Input: +; AX = number of entries in palette +; CX = maximum fade intensity (same as fade speed) +; DS:SI = pointer to source palette +; ES:DI = pointer to destination palette +; BH = destination red +; BL = destination green +; DH = destination blue +; DL = relative intensity of destination palette +; Note: +; it's important that a new palette can be calculated in less +; than 1/70th of second. Fading to any RGB value requires use +; of "imul" instructions: "idiv" may be replaced with faster +; "sar", but only when the number of passes is a power of two, +; thus reducing the range of selectable speeds. +; In both cases an extimate of CPU cycles required by this +; procedure shows that it's too slow to run on a 4.77 Mhz 8086 +; CPU and a 256 color palette, so we keep "idiv" and hope +; the target machine to be at least a 6 Mhz 80286 (that's not +; asking too much...). +; +RecalcPalette PROC NEAR + cld + push bp ; Save BP + mov bp, ax ; Copy counter in BP +@@Loop: + lodsb ; Red: read value + sub al, bh ; Subtract destination value + imul dl ; Scale to desired weight + idiv cl ; Put value in AL + add al, bh ; Add destination value... + stosb ; ...and store it + lodsb ; Green: read value + sub al, bl ; Subtract destination value + imul dl ; Scale to desired weight + idiv cl ; Put value in AL + add al, bl ; Add destination value... + stosb ; ...and store it + lodsb ; Blue: read value + sub al, dh ; Subtract destination value + imul dl ; Scale to desired weight + idiv cl ; Put value in AL + add al, dh ; Add destination value... + stosb ; ...and store it + dec bp + jnz @@Loop + pop bp ; Restore BP + ret +RecalcPalette ENDP + +;------- INTERNAL USE ONLY ------------------------------------------------ +; +; Writes a 256 color palette. +; +; Input: +; AX = index of first color to write +; BX = number of colors to write (each color is an RGB triplet) +; CX = number of vertical retraces to wait before writing to DACs +; DS:SI = pointer to first entry of palette +; +WritePalette PROC NEAR + ASSUME ds:NOTHING + mov ah, al ; Save index + mov dx, 03DAh ; Input status register +@@Delay1: + in al, dx + test al, 08h + jnz @@Delay1 ; Wait for display mode +@@Delay2: + in al, dx + test al, 08h + jz @@Delay2 ; Wait for vertical retrace mode + loop @@Delay1 ; Repeat CX times +@@Write: + mov cx, bx ; Get number of colors + mov dx, 03C8h ; PEL write address register + mov al, ah ; Restore index + out dx, al ; Select index of first color + inc dx ; PEL data register + cld ; Move forward + cli ; Disable interrupts +@@Loop: + lodsb + out dx, al ; Red + lodsb + out dx, al ; Green + lodsb + out dx, al ; Blue + loop @@Loop ; Loop until done + sti ; Enable interrupts + ret +WritePalette ENDP + +;------- INTERNAL USE ONLY ------------------------------------------------ +; +; Reads the current palette. +; +; Input: +; AX = index of first color to read +; CX = number of colors +; ES:DI = pointer to destination buffer +; +ReadPalette PROC NEAR + mov dx, 03C7h + out dx, al + inc dx + inc dx + cld +@@Loop: + in al, dx + stosb + in al, dx + stosb + in al, dx + stosb + loop @@Loop + ret +ReadPalette ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxgc.asm b/16/xw/mxgc.asm new file mode 100755 index 00000000..85edf7a6 --- /dev/null +++ b/16/xw/mxgc.asm @@ -0,0 +1,54 @@ +;----------------------------------------------------------- +; +; MXGC.ASM - Get color function +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxGetColor + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Returns the current setting of the selected DAC register. +; +; Input: +; Index = color index (0-255) +; R, G, B = byte pointers to red, green and blue +; Output: +; none +; +mxGetColor PROC FAR + ARG B:DWORD, \ + G:DWORD, \ + R:DWORD, \ + Index:WORD = ARG_SIZE + .enter 0 + .push ds, si + + mov ax, [Index] + mov dx, 3C7h ; PEL read address register + out dx, al + inc dx + inc dx + + lds si, [R] + in al, dx + mov ds:[si], al + lds si, [G] + in al, dx + mov ds:[si], al + lds si, [B] + in al, dx + mov ds:[si], al + + .pop ds, si + .leave ARG_SIZE +mxGetColor ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxgi.asm b/16/xw/mxgi.asm new file mode 100755 index 00000000..7037d411 --- /dev/null +++ b/16/xw/mxgi.asm @@ -0,0 +1,132 @@ +;----------------------------------------------------------- +; +; MXGI.ASM - Get image +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxGetImage + +EXTRN subClipImage : NEAR + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_VideoSegment : WORD +EXTRN mx_BytesPerLine : WORD + +;----------------------------------------------------------- +; +; Copies an image from screen to memory. +; +; Input: +; Image = pointer to buffer for image +; X, Y = coordinates of image on screen +; Width = width of image in pixels +; Height = height of image in pixels +; Output: +; none +; +mxGetImage PROC FAR + ARG Height:WORD, \ + Width:WORD, \ + Y:WORD, \ + X:WORD, \ + Image:DWORD = ARG_SIZE + LOCAL PlaneWidth:WORD:4, \ + PixelOffset:WORD, \ + MoveFunction:WORD, \ + ReadPlane:BYTE, \ + Count:BYTE = AUTO_SIZE + ASSUME ds:NOTHING + .enter AUTO_SIZE + .push ds, si, es, di + +; Clip image + mov bx, [X] + mov ax, [Y] + mov cx, [Width] + mov dx, [Height] + call subClipImage + jc @@Exit ; Full clipped + mov [Height], dx + add WORD PTR Image[0], si ; Skip clipped pixels + +; Get pixel address + mul [mx_BytesPerLine] + mov si, bx + shr si, 1 + shr si, 1 + add si, ax + mov [PixelOffset], si + mov ds, [mx_VideoSegment] ; DS:SI points to pixel + and bl, 03h + mov [ReadPlane], bl + +; Compute extra bytes and width count for each plane + mov bx, cx + shr bx, 1 + shr bx, 1 ; Width for each plane + and cl, 03h + mov al, 00001000b + shr al, cl + mov di, 3 SHL 1 +@@PatchLoop: + mov PlaneWidth[di], bx + shr al, 1 + adc bx, 0 + dec di + dec di + jge @@PatchLoop + +; Get image + cld + mov [Count], 4 ; Four planes + lea bx, PlaneWidth ; SS:[BX] = width in bytes for plane + mov es, WORD PTR Image[2] ; ES:DI will point to image + mov ah, [ReadPlane] +@@PlaneLoop: + cmp WORD PTR ss:[bx], 0 ; Exit if nothing more to do + je @@Exit ; (also, never try to move zero bytes!) + mov di, WORD PTR Image[0] + mov al, 04h + mov dx, GDC + out dx, ax ; Select read plane + mov dx, [Height] + mov si, [PixelOffset] ; DS:SI points to video memory +@@Loop: + .push si, di + mov cx, WORD PTR ss:[bx] ; Number of bytes to move +@@MoveLoop: + movsb + add di, 3 + dec cx + jnz @@MoveLoop + .pop si, di + add di, [Width] ; Go to next image line + add si, [mx_BytesPerLine] ; Go to next screen row + dec dx + jnz @@Loop ; Repeat for all lines + inc bx + inc bx ; Select width for next plane + inc ah + test ah, 04h ; Plane wraparound? + jz @@PlaneOk ; No + inc [PixelOffset] ; Yes, bump video pointer + and ah, 03h +@@PlaneOk: + inc WORD PTR Image[0] + dec [Count] + jnz @@PlaneLoop ; Repeat for all planes + +@@Exit: + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxGetImage ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxgm.asm b/16/xw/mxgm.asm new file mode 100755 index 00000000..a67476a0 --- /dev/null +++ b/16/xw/mxgm.asm @@ -0,0 +1,63 @@ +;----------------------------------------------------------- +; +; MXGM.ASM - Gamma correction +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxGammaCorrect + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +mx_tblGamma LABEL BYTE + DB 00, 10, 14, 17, 19, 21, 23, 24, 26, 27, 28, 29, 31, 32, 33, 34 + DB 35, 36, 37, 37, 38, 39, 40, 41, 41, 42, 43, 44, 44, 45, 46, 46 + DB 47, 48, 48, 49, 49, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55 + DB 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63 + +;----------------------------------------------------------- +; +; Correct palette colors (gamma is 2.3). +; +; Input: +; CPal = pointer to color palette +; GPal = pointer to destination (gamma corrected) palette +; Count = number of colors to convert +; Output: +; none +; +; Note: CPal and GPal may point to the same buffer. +; +mxGammaCorrect PROC FAR + ARG Count:WORD, \ + DPal:DWORD, \ + SPal:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si, es, di + + mov cx, [Count] + jcxz @@Exit ; Exit now if nothing to do + lds si, [SPal] + les di, [DPal] + mov bx, OFFSET mx_tblGamma ; Setup BX for XLAT instruction + cld + mov ax, cx ; AX = Count + add cx, cx ; CX = Count*2 + add cx, ax ; CX = Count*3 +@@Loop: + lodsb + xlat mx_tblGamma + stosb + loop @@Loop + +@@Exit: + .pop ds, si, es, di + .leave ARG_SIZE +mxGammaCorrect ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxgp.asm b/16/xw/mxgp.asm new file mode 100755 index 00000000..6c143173 --- /dev/null +++ b/16/xw/mxgp.asm @@ -0,0 +1,56 @@ +;----------------------------------------------------------- +; +; MXGP.ASM - Get palette function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxGetPalette + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Returns the current setting of the VGA palette. +; +; Input: +; Buffer = pointer to palette data (R,G,B) +; Start = index of first color to get +; Count = number of color to get +; Output: +; none +; +mxGetPalette PROC FAR + ARG Count:WORD, \ + Start:WORD, \ + Buffer:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push es, di + + les di, [Buffer] + mov cx, [Count] + mov ax, [Start] + mov dx, 3C7h ; PEL read address register + out dx, al + inc dx + inc dx + cld +@@Loop: + in al, dx + stosb + in al, dx + stosb + in al, dx + stosb + loop @@Loop ; Loop until done + + .pop es, di + .leave ARG_SIZE +mxGetPalette ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxgv.asm b/16/xw/mxgv.asm new file mode 100755 index 00000000..2a54b1d0 --- /dev/null +++ b/16/xw/mxgv.asm @@ -0,0 +1,25 @@ +;----------------------------------------------------------- +; +; MXGV.ASM - Get version function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxGetVersion + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Returns the library version. +; +mxGetVersion PROC FAR + mov ax, MXVERSION + ret +mxGetVersion ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxhl.asm b/16/xw/mxhl.asm new file mode 100755 index 00000000..049a0566 --- /dev/null +++ b/16/xw/mxhl.asm @@ -0,0 +1,76 @@ +;----------------------------------------------------------- +; +; MXHL.ASM - Horizontal line mask utility +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC subHorizontalLineInfo + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD + +tblLeftSize DW 00h, 03h, 02h, 01h +tblLeftMask DB 00h, 0Eh, 0Ch, 08h +tblRightMask DB 00h, 01h, 03h, 07h +tblPatchMask DB 02h, 06h + +;----------------------------------------------------------- +; +; Prepares register for fast horizontal line drawing. +; +; Input: +; BX, AX = X, Y address of left pixel +; CX = line width +; Output: +; DI = left pixel offset in video memory +; AL = left block write plane mask (0 = none) +; AH = right block write plane mask (0 = none) +; CX = center block width in 4-pixel blocks +; +subHorizontalLineInfo PROC NEAR + ASSUME ds:NOTHING + + mul [mx_BytesPerLine] + mov di, bx + shr di, 1 + shr di, 1 + add di, ax ; Offset of left pixel + + and bx, 03h + mov al, tblLeftMask[bx] + shl bx, 1 + sub cx, tblLeftSize[bx] + jge @@1 ; Ok to continue + +; Special case: start and end in the middle of a 4-pixel block. +; There are only three cases: +; Pixels Left mask CX CX+2 Patch mask Result +; 1) ..o. ..xx -1 1 .xx. ..x. +; 2) .oo. .xxx -1 1 .xx. .xx. +; 3) .o.. .xxx -2 0 .x.. .x.. +; All other cases are automatically handled with the standard masks. + mov bx, cx + inc bx + inc bx + and al, tblPatchMask[bx] ; Combine masks + xor ah, ah ; No right block + xor cx, cx ; No center block + jmp @@Exit + +@@1: + mov bx, cx + and bx, 03h + mov ah, tblRightMask[bx] + shr cx, 2 + +@@Exit: + ret +subHorizontalLineInfo ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxit.asm b/16/xw/mxit.asm new file mode 100755 index 00000000..c0d9cedd --- /dev/null +++ b/16/xw/mxit.asm @@ -0,0 +1,98 @@ +;----------------------------------------------------------- +; +; MXIT.ASM - Initialization/termination functions +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxInit +PUBLIC mxTerm + +PUBLIC mx_VideoSegment +PUBLIC mx_CodeSegment + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +DB 'MODEX library - Copyright (c) 1992-1994 Alessandro Scotti' + +mx_VideoSegment DW 0A000h +mx_CodeSegment DW SEG MX_TEXT + +;----------------------------------------------------------- +; +; Initialization. +; +; Input: +; none +; Output: +; AX = 0 on success +; +mxInit PROC FAR + LOCAL Result:WORD, \ + VideoSeg:WORD, \ + CStoDSalias:WORD = AUTO_SIZE + ASSUME ds:NOTHING + .enter AUTO_SIZE + .push ds, si, es, di + + mov [Result], -1 ; Assume an error + mov [VideoSeg], 0A000h ; Real mode video segment + mov [CStoDSalias], cs ; Real mode data alias for CS + +; Check if running in protected mode under DPMI + mov ax, 1686h + int 2Fh + or ax, ax + jnz @@1 ; DPMI not found, continue in real mode + +; Get a data alias for CS + mov ax, 000Ah ; DMPI: create data alias + mov bx, cs + int 31h + jc @@Exit ; Exit if service failed + mov [CStoDSalias], ax ; Save data alias for CS +; Get a protected-mode selector for the video segment + mov ax, 0002h + mov bx, 0A000h ; Real mode segment of video + int 31h ; DPMI: get segment selector + jc @@Exit ; Exit if service failed + mov [VideoSeg], ax ; Save protected mode video selector + +; Initialize variables +@@1: + mov ds, [CStoDSalias] + ASSUME ds:MX_TEXT + mov [mx_CodeSegment], ds + mov ax, [VideoSeg] + mov [mx_VideoSegment], ax + +; Don't bother with VGA check for now... + + mov [Result], 0 + +@@Exit: + mov ax, [Result] + .pop ds, si, es, di + .leave +mxInit ENDP + +;----------------------------------------------------------- +; +; Termination. +; +; Input: +; none +; Output: +; always 0. +; +mxTerm PROC FAR + ASSUME ds:NOTHING + xor ax, ax + ret +mxTerm ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxll.asm b/16/xw/mxll.asm new file mode 100755 index 00000000..34fec043 --- /dev/null +++ b/16/xw/mxll.asm @@ -0,0 +1,82 @@ +;----------------------------------------------------------- +; +; MXLL.ASM - Load latches +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxLoadLatches + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_VideoSegment : WORD + +;----------------------------------------------------------- +; +; Loads the specified value into the VGA latches. +; +; Input: +; BL = value to load into latches +; Output: +; none +; Changes: +; bit mask register to FFh; +; function select register to "move"; +; write mode to 00h. +; Note: +; this is for internal use only. +; +mxLoadLatches PROC NEAR + ASSUME ds:NOTHING + + .push ds, si + mov dx, GDC + mov ax, 0FF08h + out dx, ax ; Set bit mask to FFh + mov ax, 0003h + out dx, ax ; Set function to "move" + mov ax, 0005h + out dx, ax ; Set write mode + mov ax, [mx_VideoSegment] + mov ds, ax + mov si, 0FFFFh + mov bh, 8 ; BH = write plane mask + mov cx, 3 ; CX = count = read plane +; Saves old values and force BL into latches +@@SetLoop: + mov dx, GDC + mov al, 04h + mov ah, cl + out dx, ax ; Select read plane + mov dx, TS + mov al, 02h + mov ah, bh + out dx, ax ; Select write plane + mov al, ds:[si] + push ax + mov ds:[si], bl + mov al, ds:[di] ; Force value into latch + shr bh, 1 ; Next write plane + loop @@SetLoop +; Restore previous values + mov cx, 3 + mov bh, 8 + mov dx, TS +@@ResetLoop: + mov al, 02h + mov ah, bh + out dx, ax ; Select write plane + pop ax + mov ds:[si], al + shr bh, 1 ; Next write plane + loop @@ResetLoop +; Exit + .pop ds, si + ret +mxLoadLatches ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxln.asm b/16/xw/mxln.asm new file mode 100755 index 00000000..fbc4ab94 --- /dev/null +++ b/16/xw/mxln.asm @@ -0,0 +1,414 @@ +;----------------------------------------------------------- +; +; MXLN.ASM - Line function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxLine + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD +EXTRN mx_VideoSegment : WORD + +EXTRN mx_ClipX1 : WORD +EXTRN mx_ClipY1 : WORD +EXTRN mx_ClipX2 : WORD +EXTRN mx_ClipY2 : WORD + +tblDrawFunc LABEL WORD + DW subWidthMove + DW subHeightMove + DW subWidthOp + DW subHeightOp + +;----------------------------------------------------------- +; +; Draws a line from (X1,Y1) to (X2,Y2) using the Bresenham +; algorithm. +; +; Input: +; X1, Y1 = start point +; X2, Y2 = end point +; Color = line color +; Op = raster operator +; Output: +; none +; +; Note: the end point (X2,Y2) *IS* drawed. I don't like this very much +; but clipping is much simpler. +; +mxLine PROC FAR + ARG Op:WORD, \ + Color:WORD, \ + Y2:WORD, \ + X2:WORD, \ + Y1:WORD, \ + X1:WORD = ARG_SIZE + LOCAL Width:WORD, \ + Height:WORD, \ + ErrorAdd:WORD, \ + ErrorSub:WORD, \ + DeltaX:WORD, \ + DeltaY:WORD, \ + P1:BYTE, \ + P2:BYTE, \ + WritePlane:BYTE = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, di + ASSUME ds:NOTHING + + mov ax, [X1] + mov bx, [Y1] + mov cx, [X2] + mov dx, [Y2] + call subClipLine + jc @@Exit ; Line is full clipped + +; Get width + mov si, cx + xchg ax, si ; SI = X1, AX = X2 + sub ax, si + jge @@1 +; Swap points, we want X1 < X2 + xchg si, cx ; Swap X1 and X2 + xchg bx, dx ; Swap Y1 and Y2 + neg ax +@@1: + mov [Width], ax + +; Get height + mov cx, [mx_BytesPerLine] ; We don't need X2 anymore + mov ax, dx + sub ax, bx + jge @@2 + neg cx ; Move from bottom to top + neg ax ; Get absolute value of AX +@@2: + mov [Height], ax + mov [DeltaY], cx + +; Get pixel address and write plane + mov ax, bx + mul [mx_BytesPerLine] + mov cx, si ; CX = X1 + shr si, 1 + shr si, 1 + add si, ax ; SI = pixel offset + and cl, 03h + mov ax, 1102h + shl ah, cl + mov [WritePlane], ah + mov dx, TS + out dx, ax ; Set write plane + mov ax, [mx_VideoSegment] + mov ds, ax ; DS:SI points to (X1,Y1) + +; Select the function to handle the drawing loop + xor bx, bx + mov al, BYTE PTR [Op] + cmp al, OP_MOVE + je @@3 + and al, 03h + shl al, 1 + shl al, 1 + shl al, 1 + mov ah, al + mov al, 03h + mov dx, GDC + out dx, ax ; Set logical function + inc bx + inc bx +@@3: + mov ax, [Width] + mov cx, [Height] +; Horizontal, vertical and diagonal lines are not optimized yet + cmp ax, cx + jae @@4 + inc bx +@@4: + shl bx, 1 + call tblDrawFunc[bx] + +; Reset logical function if needed + cmp BYTE PTR [Op], OP_MOVE + je @@Exit + mov ax, 0003h + mov dx, GDC + out dx, ax + +@@Exit: + xor ax, ax + .pop ds, si, di + .leave ARG_SIZE + +;----------------------------------------------------------- +; +; Checks the coordinates of a line against the active +; clip region. +; Uses a variation of the Cohen-Sutherland algorithm developed +; by Victor Duvanenko. +; +; Input: +; AX, BX = X1, Y1 +; CX, DX = X2, Y2 +; Output: +; CF = set if line is full clipped +; AX, BX = clipped X1, Y1 +; CX, DX = clipped X2, Y2 +; Note: +; destroys SI, DI +; +subClipLine PROC NEAR + mov di, ax ; Copy X1 to DI and free AX + mov si, dx ; Copy Y2 to SI and free DX +; Compute clip codes for point (X2,Y2)=(CX,SI) + xor al, al +@@P2X1: cmp cx, [mx_ClipX1] + jge @@P2X2 + or al, 1 +@@P2X2: cmp cx, [mx_ClipX2] + jle @@P2Y1 + or al, 2 +@@P2Y1: cmp si, [mx_ClipY1] + jge @@P2Y2 + or al, 4 +@@P2Y2: cmp si, [mx_ClipY2] + jle @@P2XY + or al, 8 +@@P2XY: mov [P2], al +; Compute clip codes for point (X1,Y1)=(DI,BX) + xor al, al +@@P1X1: cmp di, [mx_ClipX1] + jge @@P1X2 + or al, 1 +@@P1X2: cmp di, [mx_ClipX2] + jle @@P1Y1 + or al, 2 +@@P1Y1: cmp bx, [mx_ClipY1] + jge @@P1Y2 + or al, 4 +@@P1Y2: cmp bx, [mx_ClipY2] + jle @@P1XY + or al, 8 +@@P1XY: mov [P1], al +; Check codes for trivial cases + mov ah, [P2] + test al, ah ; Is line invisible? + jnz @@FullClip ; Yes, exit + or ah, al ; Both points clipped? + jz @@Done ; Yes, exit +; Calculate deltas + mov ax, cx + sub ax, di + mov [DeltaX], ax + mov ax, si + sub ax, bx + mov [DeltaY], ax + mov al, [P1] ; Init clipping code +; Clipping loop +@@ClipLoop: + test al, al ; Is first point clipped? + jnz @@ClipX1 ; No, continue + xchg cx, di ; Swap points... + xchg bx, si + xchg al, [P2] ; ...and codes +; Clip left: Y1 = Y1 + DeltaY*(mx_ClipX1-X1)/DeltaX +@@ClipX1: + test al, 1 + jz @@ClipX2 + mov ax, [mx_ClipX1] + sub ax, di + mov di, [mx_ClipX1] + jmp @@ClipX1X2 +; Clip right: Y1 = Y1 + DeltaY*(mx_ClipX2-X1)/DeltaX +@@ClipX2: + test al, 2 + jz @@ClipY1 + mov ax, [mx_ClipX2] + sub ax, di + mov di, [mx_ClipX2] +@@ClipX1X2: + imul [DeltaY] + idiv [DeltaX] + add bx, ax + mov al, 8 + cmp bx, [mx_ClipY2] + jg @@CheckLoop + mov al, 4 + cmp bx, [mx_ClipY1] + jl @@CheckLoop + xor al, al + jmp @@CheckLoop +; Clip top: X1 = X1 + DeltaX*(mx_ClipY1-Y1)/DeltaY +@@ClipY1: + test al, 4 + jz @@ClipY2 + mov ax, [mx_ClipY1] + sub ax, bx + mov bx, [mx_ClipY1] + jmp @@ClipY1Y2 +; Clip bottom: X1 = X1 + DeltaX*(mx_ClipY2-Y1)/DeltaY +@@ClipY2: + mov ax, [mx_ClipY2] + sub ax, bx + mov bx, [mx_ClipY2] +@@ClipY1Y2: + imul [DeltaX] + idiv [DeltaY] + add di, ax + mov al, 1 + cmp di, [mx_ClipX1] + jl @@CheckLoop + mov al, 2 + cmp di, [mx_ClipX2] + jg @@CheckLoop + xor al, al +@@CheckLoop: + mov ah, [P2] + test al, ah + jnz @@FullClip + or ah, al + jnz @@ClipLoop + +@@Done: + mov ax, di + mov dx, si + clc + ret +@@FullClip: + stc + ret +subClipLine ENDP + +; Called when Width >= Height and Op = OP_MOVE +subWidthMove PROC NEAR + mov di, ax + neg di ; Initialize error term + shl cx, 1 + mov [ErrorAdd], cx + mov cx, ax + shl ax, 1 + mov [ErrorSub], ax + mov al, 02h + mov ah, [WritePlane] + mov bl, BYTE PTR [Color] + mov dx, TS + inc cx +@@Loop: + mov ds:[si], bl + dec cx + jz @@Exit + rol ah, 1 + adc si, 0 + out dx, ax + add di, [ErrorAdd] + jl @@Loop + add si, [DeltaY] + sub di, [ErrorSub] + jmp @@Loop +@@Exit: + ret +subWidthMove ENDP + +; Called when Width < Height and Op = OP_MOVE +subHeightMove PROC NEAR + mov di, cx + neg di ; Initialize error term + shl ax, 1 + mov [ErrorAdd], ax + mov ax, cx + shl ax, 1 + mov [ErrorSub], ax + mov bl, BYTE PTR [Color] + mov ah, [WritePlane] + mov al, 02h + mov dx, TS + inc cx +@@Loop: + mov ds:[si], bl + dec cx + jz @@Exit + add si, [DeltaY] + add di, [ErrorAdd] + jl @@Loop + rol ah, 1 ; Next write plane + adc si, 0 ; Bump video offset if plane overflows + out dx, ax + sub di, [ErrorSub] ; Adjust error down + jmp @@Loop +@@Exit: + ret +subHeightMove ENDP + +; Called when Width >= Height and Op <> OP_MOVE +subWidthOp PROC NEAR + mov di, ax + neg di ; Initialize error term + shl cx, 1 + mov [ErrorAdd], cx + mov cx, ax + shl ax, 1 + mov [ErrorSub], ax + mov al, 02h + mov ah, [WritePlane] + mov bl, BYTE PTR [Color] + mov dx, TS + inc cx +@@Loop: + mov bh, ds:[si] ; Latch data + mov ds:[si], bl + dec cx + jz @@Exit + rol ah, 1 + adc si, 0 + out dx, ax + add di, [ErrorAdd] + jl @@Loop + add si, [DeltaY] + sub di, [ErrorSub] + jmp @@Loop +@@Exit: + ret +subWidthOp ENDP + +; Called when Width < Height and Op <> OP_MOVE +subHeightOp PROC NEAR + mov di, cx + neg di ; Initialize error term + shl ax, 1 + mov [ErrorAdd], ax + mov ax, cx + shl ax, 1 + mov [ErrorSub], ax + mov bl, BYTE PTR [Color] + mov ah, [WritePlane] + mov al, 02h + mov dx, TS + inc cx +@@Loop: + mov bh, ds:[si] + mov ds:[si], bl + dec cx + jz @@Exit + add si, [DeltaY] + add di, [ErrorAdd] + jl @@Loop + rol ah, 1 ; Next write plane + adc si, 0 ; Bump video offset if plane overflows + out dx, ax + sub di, [ErrorSub] ; Adjust error down + jmp @@Loop +@@Exit: + ret +subHeightOp ENDP + +mxLine ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxot.asm b/16/xw/mxot.asm new file mode 100755 index 00000000..62547665 --- /dev/null +++ b/16/xw/mxot.asm @@ -0,0 +1,330 @@ +;----------------------------------------------------------- +; +; MXOT.ASM - Text functions +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES ; We use the reserved name 'WIDTH' +INCLUDE MODEX.DEF + +PUBLIC mxOutChar +PUBLIC mxOutText +PUBLIC mxSetFont +PUBLIC mxSetTextColor +PUBLIC mxGetTextStep +PUBLIC mxSetTextStep + +MAX_WIDTH EQU 16 ; Must be <= 16 +MAX_HEIGHT EQU 32 + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_CodeSegment : WORD +EXTRN mxPutImage : FAR + +; Default 8x8 font +fnt_Default LABEL + 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 OP_MOVE ; Raster op +mx_DeltaX DW 8 ; Horizontal step +mx_DeltaY DW 0 ; Vertical step + +;----------------------------------------------------------- +; +; Sets the current font. +; +; Input: +; Font = pointer to font data +; Width = width of font character in pixels +; Height = height of font character in pixels +; Output: +; AX = 0 on success, else invalid parameters +; +; Note: when the high word of Font (i.e. the segment) is zero, the low +; word is used to select one of the system fonts. +; +mxSetFont PROC FAR + ARG Height:WORD, \ + Width:WORD, \ + Font:DWORD = ARG_SIZE + .enter 0 + .push ds + + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, WORD PTR Font[2] ; Get font segment + test ax, ax ; Null segment? + jnz @@UserFont ; No, install user font + +; Install system font + mov ax, WORD PTR Font[0] ; Get font number + cmp ax, MX_MAXSYSFONT ; Check range + jb @@SystemFont + xor ax, ax ; Out of range, use default font +@@SystemFont: + shl ax, 1 + shl ax, 1 + mov bx, ax + mov ax, tbl_SystemFont[bx] ; Get font offset + mov WORD PTR mx_FontPtr[0], ax + mov WORD PTR mx_FontPtr[2], cs + mov al, BYTE PTR tbl_SystemFont[bx+2] + xor ah, ah + mov [mx_FontWidth], ax + mov [mx_DeltaX], ax + mov dl, BYTE PTR tbl_SystemFont[bx+3] + xor dh, dh + mov [mx_FontHeight], dx + mul dx + mov [mx_FontCharSize], ax + mov [mx_DeltaX], ax + xor ax, ax + mov [mx_DeltaY], ax + jmp @@Exit + +; Install user font +@@UserFont: + mov ax, -1 ; Assume an error + mov bx, [Width] + cmp bx, MAX_WIDTH + ja @@Exit ; Invalid character width + mov dx, [Height] + cmp dx, MAX_HEIGHT + ja @@Exit ; Invalid character height + mov [mx_FontWidth], bx + mov [mx_FontHeight], dx + mov ax, bx + add ax, 7 + .shr ax, 3 + mul dx + mov [mx_FontCharSize], ax + mov ax, WORD PTR Font[0] + mov WORD PTR mx_FontPtr[0], ax + mov ax, WORD PTR Font[2] + mov WORD PTR mx_FontPtr[2], ax + xor ax, ax + +@@Exit: + .pop ds + ASSUME ds:NOTHING + .leave ARG_SIZE +mxSetFont ENDP + +;----------------------------------------------------------- +; +; Sets the text color and raster op. +; +; Input: +; Color = text color (foreground + background*256) +; Op = raster op +; Output: +; none +; +mxSetTextColor PROC FAR + ARG Op:WORD, \ + Color:WORD = ARG_SIZE + .enter 0 + .push ds + + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, [Color] + mov [mx_FontColor], ax + mov ax, [Op] + mov [mx_FontOp], ax + + xor ax, ax + .pop ds + ASSUME ds:NOTHING + .leave ARG_SIZE +mxSetTextColor ENDP + +;----------------------------------------------------------- +; +; Writes a character using the current font and attributes. +; +; Input: +; X, Y = video coordinates +; C = character to print +; Output: +; none +; +mxOutChar PROC FAR + ARG C:BYTE:2, \ + Y:WORD, \ + X:WORD = ARG_SIZE + LOCAL Image:BYTE:MAX_WIDTH*MAX_HEIGHT, \ + Count:WORD = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, es, di + ASSUME ds:NOTHING + +; Gets the pointer to font data for the selected character + lds si, DWORD PTR [mx_FontPtr] + mov al, [C] + xor ah, ah + mul [mx_FontCharSize] ; Offset into font + add si, ax ; DS:SI -> font data for character + +; Converts font data into a 256-color linear image + mov ax, ss + mov es, ax + lea di, [Image] + mov dx, [mx_FontColor] + mov ax, [mx_FontHeight] + mov [Count], ax +@@HeightLoop: + mov cx, [mx_FontWidth] + mov bh, ds:[si] + inc si ; Get a byte from font data + cmp cx, 8 + jbe @@WidthLoop ; Ok for width <= 8 + mov bl, ds:[si] ; Get another byte + inc si +@@WidthLoop: + mov al, dl ; Assume foreground color + shl bx, 1 ; Is font bit set? + jc @@1 ; Yes, foreground is just great + mov al, dh ; Get background color +@@1: + mov es:[di], al ; Put pixel into image + inc di + dec cx + jnz @@WidthLoop + dec [Count] + jnz @@HeightLoop + +; Now pass image to mx_PutImage + lea ax, [Image] + push es + push ax ; Pointer to image + push [X] + push [Y] ; Image coordinates + push [mx_FontWidth] + push [mx_FontHeight] ; Image size + push [mx_FontOp] ; Raster op + call mxPutImage ; Write character + + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxOutChar ENDP + +;----------------------------------------------------------- +; +; Writes a string at the coordinates specified. +; +; Input: +; X, Y = text coordinates +; S = pointer to ASCIIZ string +; Output: +; none +; +mxOutText PROC FAR + ARG S:DWORD, \ + Y:WORD, \ + X:WORD = ARG_SIZE + .enter 0 + .push ds, si + ASSUME ds:NOTHING + + lds si, [S] +@@Loop: + mov al, ds:[si] + test al, al ; End of string? + jz @@Exit ; Yes, exit + inc si + push [X] ; Display character + push [Y] + push ax + call mxOutChar + mov ax, [mx_DeltaX] + add [X], ax ; Bump X coordinate + mov ax, [mx_DeltaY] + add [Y], ax ; Bump Y coordinate + dec [Count] + jnz @@Loop + +@@Exit: + xor ax, ax + .pop ds, si + .leave ARG_SIZE + ret +mxOutText ENDP + +;----------------------------------------------------------- +; +; Sets the distance between characters. +; +; Input: +; DeltaX = horizontal distance in pixels +; DeltaY = vertical distance in pixels +; Output: +; none +; +; Note: this function may be used to set the text direction. +; +mxSetTextStep PROC FAR + ARG DeltaY:WORD, \ + DeltaX:WORD = ARG_SIZE + .enter 0 + .push ds + + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, [DeltaX] + mov [mx_DeltaX], ax + mov ax, [DeltaY] + mov [mx_DeltaY], ax + + .pop ds + .leave ARG_SIZE +mxSetTextStep ENDP + +;----------------------------------------------------------- +; +; Gets the current distance between characters. +; +; Input: +; DeltaX = pointer to horizontal distance in pixels (integer) +; DeltaY = pointer to vertical distance in pixels (integer) +; Output: +; none +; +mxGetTextStep PROC FAR + ARG DeltaY:DWORD, \ + DeltaX:DWORD = ARG_SIZE + .enter 0 + .push ds, si + ASSUME ds:NOTHING + + mov ax, [mx_DeltaX] + lds si, [DeltaX] + mov ds:[si], ax + mov ax, [mx_DeltaY] + lds si, [DeltaY] + mov ds:[si], ax + + .pop ds, si + .leave ARG_SIZE +mxGetTextStep ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxpb.asm b/16/xw/mxpb.asm new file mode 100755 index 00000000..8c6aa449 --- /dev/null +++ b/16/xw/mxpb.asm @@ -0,0 +1,22 @@ +;----------------------------------------------------------- +; +; MXPB.ASM - Scan buffer for convex polygon fills +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mx_ScanBuffer + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +ALIGN 4 + +mx_ScanBuffer LABEL + DW POLYSCANBUFSIZE DUP(?) + +MX_TEXT ENDS +END diff --git a/16/xw/mxpf.asm b/16/xw/mxpf.asm new file mode 100755 index 00000000..db0da898 --- /dev/null +++ b/16/xw/mxpf.asm @@ -0,0 +1,420 @@ +;----------------------------------------------------------- +; +; MXPG.ASM - Convex polygon fill +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxFillPoly + +;----------------------------------------------------------- +; +; "Local" definitions +; +TPOINT STRUC + X DW ? + Y DW ? +TPOINT ENDS + +; Do NOT change order! +TSCAN STRUC + Y1 DW ? + Y2 DW ? +TSCAN ENDS + +MAXSCANCOLUMNS EQU POLYSCANBUFSIZE / SIZE TSCAN + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_VideoSegment : WORD +EXTRN mx_CodeSegment : WORD +EXTRN mx_BytesPerLine : WORD +EXTRN mx_ClipX1 : WORD +EXTRN mx_ClipY1 : WORD +EXTRN mx_ClipX2 : WORD +EXTRN mx_ClipY2 : WORD +EXTRN mx_ScanBuffer : NEAR + +;----------------------------------------------------------- +; +; Scans an edge using the DDA (digital differential analyzer) algorithm. +; +; Input: +; DS:BX = pointer to start point (X1, Y1) +; DS:SI = pointer to end point (X2, Y2) +; ES:DI = pointer to edge buffer +; Output: +; ES:DI = updated pointer to edge buffer +; Notes: +; must preserve DS:SI. +; +subScan PROC NEAR + mov cx, ds:[si].X + sub cx, ds:[bx].X ; Get width + jg @@1 + ret +@@1: + push bp ; Save BP + + mov ax, ds:[si].Y + mov bx, ds:[bx].Y + sub ax, bx ; Get height + jg @@T2B ; Scan top to bottom + jl @@B2T ; Scan bottom to top + +; Special case: vertical line + mov ax, bx +@@V: + mov es:[di].Y1, ax + add di, SIZE TSCAN + dec cx + jnz @@V + jmp @@Exit + +; Scan top to bottom +@@T2B: + cwd + div cx + mov bp, ax + xor ax, ax + div cx + xchg ax, bx ; BP:BX = fixed 16:16 step + mov dx, 8000h +@@T2BLoop: + mov es:[di].Y1, ax + add di, SIZE TSCAN + add dx, bx + adc ax, bp + dec cx + jnz @@T2BLoop + jmp @@Exit + +; Scan bottom to top +@@B2T: + neg ax + cwd + div cx + mov bp, ax + xor ax, ax + div cx + xchg ax, bx + mov dx, 8000h +@@B2TLoop: + mov es:[di].Y1, ax + add di, SIZE TSCAN + sub dx, bx + sbb ax, bp + dec cx + jnz @@B2TLoop + +@@Exit: + pop bp ; Restore BP + ret +subScan ENDP + +;----------------------------------------------------------- +; +; Fills a convex polygon with the specified color. +; +; Input: +; Count = number of vertexes +; Map = indexes of points and colors (integer) +; Points = array of points (integer X, Y coordinates) +; Color = base color +; Output: +; none +; Notes: +; vertexes must be in counterclockwise order, arrays are 0-based. +; +mxFillPoly PROC FAR + ARG Color:WORD, \ + Points:DWORD, \ + Map:DWORD, \ + Count:WORD = ARG_SIZE + LOCAL WritePlane:BYTE:2, \ + ScanOffsetT:WORD, \ + ScanOffsetB:WORD, \ + ScanCount:WORD, \ + Holder:WORD, \ + Height:WORD, \ + MinIdxT:WORD, \ + MinIdxB:WORD, \ + MaxIdx:WORD, \ + Width:WORD, \ + BoxX1:WORD, \ + BoxY1:WORD, \ + BoxX2:WORD, \ + BoxY2::WORD = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, es, di + ASSUME ds:NOTHING + +; Check that at least three vertexes are specified + mov cx, [Count] + cmp cx, 3 + jb @@Exit + +;------------------------------ +; Find bounding box for polygon + les di, [Map] + lds si, [Points] ; Pointer to vertex array + mov [BoxX1], 32767 + mov [BoxX2], -32768 + mov [BoxY1], 32767 + mov [BoxY2], -32768 + + xor dx, dx +@@MinMaxLoop: + mov bx, es:[di] ; Get index of vertex + .shl bx, 2 ; Get offset in point array + add bx, si + +; Check X range +@@CheckMinX: + mov ax, ds:[bx].X ; Get X coordinate + cmp ax, [BoxX1] + jge @@CheckMaxX + mov [BoxX1], ax + mov [MinIdxT], dx + mov [MinIdxB], dx +@@CheckMaxX: + cmp ax, [BoxX2] + jle @@CheckMinY + mov [BoxX2], ax + mov [MaxIdx], dx + +; Check Y range +@@CheckMinY: + mov ax, ds:[bx].Y + cmp ax, [BoxY1] + jge @@CheckMaxY + mov [BoxY1], ax +@@CheckMaxY: + cmp ax, [BoxY2] + jle @@CheckDone + mov [BoxY2], ax + +; Repeat thru all points +@@CheckDone: + inc di ; Next map entry + inc dx + inc di + inc dx + dec cx + jnz @@MinMaxLoop + +;--------------------------------- +; Check if polygon is full clipped + mov ax, [BoxX2] + cmp ax, [mx_ClipX1] ; Is poly full clipped? + jl @@Exit + mov bx, [BoxX1] + cmp bx, [mx_ClipX2] ; Is poly full clipped? + jg @@Exit + sub ax, bx ; Get width + jle @@Exit ; Exit if not positive + mov ax, [BoxY2] + cmp ax, [mx_ClipY1] ; Is poly full clipped? + jl @@Exit + mov bx, [BoxY1] + cmp bx, [mx_ClipY2] ; Is poly full clipped? + jg @@Exit + sub ax, bx ; Get height + jle @@Exit ; Exit if not positive + + dec [Count] + shl [Count], 1 ; We'll work with word offsets + mov es, [mx_CodeSegment] + +;-------------- +; Scan top edge + mov ax, OFFSET mx_ScanBuffer + mov [ScanOffsetT], ax + mov si, [MinIdxT] ; Offset of bottom point index +@@STLoop: + lds bx, [Map] ; DS:BX -> map table + mov di, ds:[bx+si] ; Index of top point #1 + dec si ; Next point + dec si + test si, si + jnl @@ST1 + mov si, [Count] +@@ST1: + mov [MinIdxT], si ; Save new index of top point + mov si, ds:[bx+si] ; Get index of top point #2 + .shl di, 2 ; Convert indexes to offsets + .shl si, 2 + lds bx, [Points] ; DS:BX -> point array + add si, bx ; DS:SI -> top point #2 + add bx, di ; DS:BX -> top point #1 + mov di, [ScanOffsetT] + call subScan ; Scan edge + mov [ScanOffsetT], di + mov si, [MinIdxT] + cmp si, [MaxIdx] ; End of edge? + jne @@STLoop ; No, continue + +;----------------- +; Scan bottom edge + mov ax, OFFSET mx_ScanBuffer + OFFSET Y2 + mov [ScanOffsetB], ax + mov si, [MinIdxB] ; Offset of bottom point index +@@SBLoop: + lds bx, [Map] ; DS:BX -> map table + mov di, ds:[bx+si] ; Index of bottom point #1 + inc si ; Next bottom point + inc si + cmp si, [Count] + jbe @@SB1 + xor si, si +@@SB1: + mov [MinIdxB], si ; Save new index of bottom point + mov si, ds:[bx+si] ; Get index of bottom point #2 + .shl di, 2 ; Convert indexes to offsets + .shl si, 2 + lds bx, [Points] ; DS:BX -> point array + add si, bx ; DS:SI -> top point #2 + add bx, di ; DS:BX -> top point #1 + mov di, [ScanOffsetB] + call subScan ; Scan edge + mov [ScanOffsetB], di + mov si, [MinIdxB] + cmp si, [MaxIdx] ; End of edge? + jne @@SBLoop ; No, continue + +;-------------------- +; Clip left and right + mov si, OFFSET mx_ScanBuffer + mov ax, [BoxX1] + mov cx, [BoxX2] + sub cx, ax ; CX = bounding box width + mov bx, [mx_ClipX1] + sub bx, ax + jle @@ClipL1 ; No need to clip left + sub cx, bx ; Update width + add ax, bx ; BoxX1 = mx_ClipX1 + mov [BoxX1], ax + .shl bx, 2 ; Warning!!! This is an hand-coded + add si, bx ; multiply by the size of TSCAN +@@ClipL1: + mov bx, ax + add bx, cx ; Last scan column + sub bx, [mx_ClipX2] + jle @@ClipL2 ; No need to clip right + sub cx, bx ; Clip right +@@ClipL2: + test cx, cx ; Is clipped width positive? + jle @@Exit ; No, exit + mov [ScanCount], cx ; Save number of columns to draw + mov [ScanOffsetT], si ; Remember offset of (clipped) buffer + mov ds, [mx_CodeSegment] ; DS:SI -> scan buffer + +;------------------------------ +; Check if Y clipping is needed + mov ax, [BoxY1] + cmp ax, [mx_ClipY1] + jl @@ClipTB ; Need to clip top + mov ax, [BoxY2] + cmp ax, [mx_ClipY2] + jg @@ClipTB ; Need to clip bottom + jmp @@ClipYExit ; Skip Y clipping + +;-------------------- +; Clip top and bottom +@@ClipTB: + mov di, cx ; DI = scan count + inc di ; Increment count for pre-loop test + sub si, SIZE TSCAN +@@ClipYLoop: + dec di ; Any column left? + jz @@ClipYExit ; No, exit + add si, SIZE TSCAN + mov ax, ds:[si].Y1 ; Y1 + mov cx, ds:[si].Y2 ; Y2 + mov dx, [mx_ClipY2] + cmp ax, dx ; Full clipped? + jg @@ClipYClip ; Yes, skip this column + cmp cx, dx ; Need to clip bottom? + jle @@ClipY1 ; No, continue +; Clip bottom + mov ds:[si].Y2, dx + mov bx, cx + sub bx, dx ; Clip distance + sub cx, ax ; Height + jle @@ClipYClip + mov cx, ds:[si].Y2 +@@ClipY1: + mov dx, [mx_ClipY1] + cmp cx, dx ; Full top clipped? + jl @@ClipYClip ; Yes, skip + sub cx, ax ; Get height + jle @@ClipYClip ; Skip if not positive + cmp ax, dx ; Need to clip top? + jge @@ClipYLoop ; No, continue +; Clip top + mov ds:[si].Y1, dx ; Y1 = mx_ClipY1 + sub dx, ax ; DX = number of pixels clipped + cmp cx, dx + ja @@ClipYLoop ; Not clipped, continue +@@ClipYClip: + mov ds:[si].Y1, -1 ; Mark column as clipped + jmp @@ClipYLoop +@@ClipYExit: + +;------------- +; Draw columns + mov es, [mx_VideoSegment] + mov si, [ScanOffsetT] + mov cl, BYTE PTR [BoxX1] ; Init write plane + and cl, 03h + mov al, 11h + shl al, cl + mov [WritePlane], al + .shr [BoxX1], 2 +@@DrawLoop: + mov ax, ds:[si].Y1 + test ax, ax ; Was column clipped? + js @@DrawNext ; Yes, skip + mov cx, ds:[si].Y2 + sub cx, ax ; CX = height + jle @@DrawNext + mul [mx_BytesPerLine] ; Get pixel address + add ax, [BoxX1] + mov di, ax + mov ah, [WritePlane] + mov dx, TS + mov al, 02h + out dx, ax + mov ax, [Color] + mov dx, [mx_BytesPerLine] + shr cx, 1 + jnc @@FillScan + mov es:[di], al + add di, dx + jcxz @@DrawNext +@@FillScan: + mov es:[di], al + add di, dx + mov es:[di], al + add di, dx + dec cx + jnz @@FillScan +@@DrawNext: + rol [WritePlane], 1 + adc [BoxX1], 0 ; Bump pointer to video memory if needed + add si, SIZE TSCAN + dec [ScanCount] + jnz @@DrawLoop + +@@Exit: + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxFillPoly ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxpg.asm b/16/xw/mxpg.asm new file mode 100755 index 00000000..caa7cf1b --- /dev/null +++ b/16/xw/mxpg.asm @@ -0,0 +1,589 @@ +;----------------------------------------------------------- +; +; MXPG.ASM - Convex polygon fill with Gouraud shading +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxGouraudPoly + +;----------------------------------------------------------- +; +; "Local" definitions +; +TPOINT STRUC + X DW ? + Y DW ? +TPOINT ENDS + +; Do NOT change order! +TSCAN STRUC + Y1 DW ? + E1 DB ? + C1 DB ? + Y2 DW ? + E2 DB ? + C2 DB ? +TSCAN ENDS + +MAXSCANCOLUMNS EQU POLYSCANBUFSIZE / SIZE TSCAN + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_VideoSegment : WORD +EXTRN mx_CodeSegment : WORD +EXTRN mx_BytesPerLine : WORD +EXTRN mx_ClipX1 : WORD +EXTRN mx_ClipY1 : WORD +EXTRN mx_ClipX2 : WORD +EXTRN mx_ClipY2 : WORD +EXTRN mx_ScanBuffer : NEAR + +;----------------------------------------------------------- +; +; Scans an edge using the DDA (digital differential analyzer) algorithm. +; Also interpolates color for shading. +; +; Input: +; DS:BX = pointer to start point (X1, Y1) +; DS:SI = pointer to end point (X2, Y2) +; ES:DI = pointer to edge buffer +; DX = start color +; AX = end color +; Output: +; ES:DI = updated pointer to edge buffer +; Notes: +; must preserve DS:SI. +; +subScan PROC NEAR + mov cx, ds:[si].X + sub cx, ds:[bx].X ; Get width + jg @@1 + ret +@@1: + push bp ; Save BP + push di ; Save scan info offset + push cx ; Save height + push ax ; Save colors + push dx + + mov ax, ds:[si].Y + mov bx, ds:[bx].Y + sub ax, bx ; Get height + jg @@T2B ; Scan top to bottom + jl @@B2T ; Scan bottom to top + +; Special case: vertical line + mov ax, bx +@@V: + mov es:[di].Y1, ax + add di, SIZE TSCAN + dec cx + jnz @@V + jmp @@GetColorInfo + +; Scan top to bottom +@@T2B: + cwd + div cx + mov bp, ax + xor ax, ax + div cx + xchg ax, bx ; BP:BX = fixed 16:16 step + mov dx, 8000h +@@T2BLoop: + mov es:[di].Y1, ax + add di, SIZE TSCAN + add dx, bx + adc ax, bp + dec cx + jnz @@T2BLoop + jmp @@GetColorInfo + +; Scan bottom to top +@@B2T: + neg ax + cwd + div cx + mov bp, ax + xor ax, ax + div cx + xchg ax, bx + mov dx, 8000h +@@B2TLoop: + mov es:[di].Y1, ax + add di, SIZE TSCAN + sub dx, bx + sbb ax, bp + dec cx + jnz @@B2TLoop + +; Now get the color info +@@GetColorInfo: + pop bx ; Restore colors + pop ax + pop cx ; Height + pop di ; ES:DI -> scan info + + sub ax, bx ; Get color range + jg @@CL2R + jl @@CR2L + +; Special case: same color + mov ah, bl + mov al, 80h +@@CV: + mov WORD PTR es:[di].E1, ax + add di, SIZE TSCAN + dec cx + jnz @@CV + jmp @@Exit + +; Scan left to right +@@CL2R: + cwd + div cx + mov bp, ax + xor ax, ax + div cx + xchg ax, bx ; BP:BX = fixed 16:16 step + mov dx, 8000h +@@CL2RLoop: + mov es:[di].C1, al + mov es:[di].E1, dh + add di, SIZE TSCAN + add dx, bx + adc ax, bp + dec cx + jnz @@CL2RLoop + jmp @@Exit + +; Scan right to left +@@CR2L: + neg ax + cwd + div cx + mov bp, ax + xor ax, ax + div cx + xchg ax, bx + mov dx, 8000h + +@@CR2LLoop: + mov es:[di].C1, al + mov es:[di].E1, dh + add di, SIZE TSCAN + sub dx, bx + sbb ax, bp + dec cx + jnz @@CR2LLoop + +@@Exit: + pop bp + ret +subScan ENDP + +;----------------------------------------------------------- +; +; Fills a scan column. +; +; Input: +; DS:SI = current TSCAN +; ES:DI = address of top pixel +; CX = number of pixels to write +; DX = base color +; Output: +; none +; +subFillScan PROC NEAR + mov ax, WORD PTR ds:[si].E2 + mov bx, WORD PTR ds:[si].E1 + cmp ah, bh + jg @@L2R ; Color increases + jl @@R2L ; Color decreases + +; Special case: color doesn't change + add ax, dx + mov dx, [mx_BytesPerLine] +@@V: + mov es:[di], ah + add di, dx + dec cx + jnz @@V + ret + +; Color increases +@@L2R: + .push bp, si + mov si, bx + add si, dx ; Relocate color + sub ax, bx + xor dx, dx + div cx + mov bp, ax ; BP = color step, integer part + xor ax, ax + div cx + mov bx, ax ; BX = color step, fractional part + mov dx, 8000h + mov ax, [mx_BytesPerLine] + xchg si, ax +@@L2RLoop: + mov es:[di], ah + add dx, bx + adc ax, bp + add di, si + dec cx + jnz @@L2RLoop + .pop bp, si + ret + +; Color decreases +@@R2L: + .push bp, si + mov si, bx + add si, dx ; Relocate color + sub ax, bx + neg ax + xor dx, dx + div cx + mov bp, ax ; BP = color step, integer part + xor ax, ax + div cx + mov bx, ax ; BX = color step, fractional part + mov dx, 8000h + mov ax, [mx_BytesPerLine] + xchg si, ax +@@R2LLoop: + mov es:[di], ah + sub dx, bx + sbb ax, bp + add di, si + dec cx + jnz @@R2LLoop + .pop bp, si + ret +subFillScan ENDP + +;----------------------------------------------------------- +; +; Fills a convex polygon with the specified color. +; Interpolates pixel colors using the Gouraud algorithm. +; +; Input: +; Count = number of vertexes +; Map = indexes of points and colors (integer) +; Points = array of points (integer X, Y coordinates) +; Colors = array of colors (integer) +; Color = base color +; Output: +; none +; Notes: +; vertexes must be in counterclockwise order, arrays are 0-based. +; +mxGouraudPoly PROC FAR + ARG Color:WORD, \ + Colors:DWORD, \ + Points:DWORD, \ + Map:DWORD, \ + Count:WORD = ARG_SIZE + LOCAL WritePlane:BYTE:2, \ + ScanOffsetT:WORD, \ + ScanOffsetB:WORD, \ + ScanCount:WORD, \ + Holder:WORD, \ + Height:WORD, \ + MinIdxT:WORD, \ + MinIdxB:WORD, \ + MaxIdx:WORD, \ + Width:WORD, \ + BoxX1:WORD, \ + BoxY1:WORD, \ + BoxX2:WORD, \ + BoxY2::WORD = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, es, di + ASSUME ds:NOTHING + +; Check that at least three vertexes are specified + mov cx, [Count] + cmp cx, 3 + jb @@Exit + +;------------------------------ +; Find bounding box for polygon + les di, [Map] + lds si, [Points] ; Pointer to vertex array + mov [BoxX1], 32767 + mov [BoxX2], -32768 + mov [BoxY1], 32767 + mov [BoxY2], -32768 + + xor dx, dx +@@MinMaxLoop: + mov bx, es:[di] ; Get index of vertex + .shl bx, 2 ; Get offset in point array + add bx, si + +; Check X range +@@CheckMinX: + mov ax, ds:[bx].X ; Get X coordinate + cmp ax, [BoxX1] + jge @@CheckMaxX + mov [BoxX1], ax + mov [MinIdxT], dx + mov [MinIdxB], dx +@@CheckMaxX: + cmp ax, [BoxX2] + jle @@CheckMinY + mov [BoxX2], ax + mov [MaxIdx], dx + +; Check Y range +@@CheckMinY: + mov ax, ds:[bx].Y + cmp ax, [BoxY1] + jge @@CheckMaxY + mov [BoxY1], ax +@@CheckMaxY: + cmp ax, [BoxY2] + jle @@CheckDone + mov [BoxY2], ax + +; Repeat thru all points +@@CheckDone: + inc di ; Next map entry + inc di + inc dx + inc dx + dec cx + jnz @@MinMaxLoop + +;--------------------------------- +; Check if polygon is full clipped + mov ax, [BoxX2] + cmp ax, [mx_ClipX1] ; Is poly full clipped? + jl @@Exit + mov bx, [BoxX1] + cmp bx, [mx_ClipX2] ; Is poly full clipped? + jg @@Exit + sub ax, bx ; Get width + jle @@Exit ; Exit if not positive + mov ax, [BoxY2] + cmp ax, [mx_ClipY1] ; Is poly full clipped? + jl @@Exit + mov bx, [BoxY1] + cmp bx, [mx_ClipY2] ; Is poly full clipped? + jg @@Exit + sub ax, bx ; Get height + jle @@Exit ; Exit if not positive + + dec [Count] + shl [Count], 1 ; We'll work with word offsets + mov es, [mx_CodeSegment] + +;-------------- +; Scan top edge + mov ax, OFFSET mx_ScanBuffer + mov [ScanOffsetT], ax + mov si, [MinIdxT] ; Offset of bottom point index +@@STLoop: + lds bx, [Map] ; DS:BX -> map table + mov di, ds:[bx+si] ; Index of top point #1 + dec si ; Next point + dec si + test si, si + jnl @@ST1 + mov si, [Count] +@@ST1: + mov [MinIdxT], si ; Save new index of top point + mov si, ds:[bx+si] ; Get index of top point #2 + lds bx, [Colors] ; Get pointer to color array + shl di, 1 ; Convert indexes to offsets + shl si, 1 + mov ax, ds:[bx+si] ; Get colors + mov dx, ds:[bx+di] + lds bx, [Points] ; DS:BX -> point array + shl si, 1 + shl di, 1 + add si, bx ; DS:SI -> top point #2 + add bx, di ; DS:BX -> top point #1 + mov di, [ScanOffsetT] + call subScan ; Scan edge + mov [ScanOffsetT], di + mov si, [MinIdxT] + cmp si, [MaxIdx] ; End of edge? + jne @@STLoop ; No, continue + +;----------------- +; Scan bottom edge + mov ax, OFFSET mx_ScanBuffer + OFFSET Y2 + mov [ScanOffsetB], ax + mov si, [MinIdxB] ; Offset of bottom point index +@@SBLoop: + lds bx, [Map] ; DS:BX -> map table + mov di, ds:[bx+si] ; Index of bottom point #1 + inc si ; Next bottom point + inc si + cmp si, [Count] + jbe @@SB1 + xor si, si +@@SB1: + mov [MinIdxB], si ; Save new index of bottom point + mov si, ds:[bx+si] ; Get index of bottom point #2 + lds bx, [Colors] ; Get pointer to color array + shl di, 1 ; Convert indexes to offsets + shl si, 1 + mov ax, ds:[bx+si] ; Get colors + mov dx, ds:[bx+di] + lds bx, [Points] ; DS:BX -> point array + shl si, 1 + shl di, 1 + add si, bx ; DS:SI -> top point #2 + add bx, di ; DS:BX -> top point #1 + mov di, [ScanOffsetB] + call subScan ; Scan edge + mov [ScanOffsetB], di + mov si, [MinIdxB] + cmp si, [MaxIdx] ; End of edge? + jne @@SBLoop ; No, continue + +;-------------------- +; Clip left and right + mov si, OFFSET mx_ScanBuffer + mov ax, [BoxX1] + mov cx, [BoxX2] + sub cx, ax ; CX = bounding box width + mov bx, [mx_ClipX1] + sub bx, ax + jle @@ClipL1 ; No need to clip left + sub cx, bx ; Update width + add ax, bx ; BoxX1 = mx_ClipX1 + mov [BoxX1], ax + .shl bx, 3 ; Warning!!! This is an hand-coded + add si, bx ; multiply by the size of TSCAN +@@ClipL1: + mov bx, ax + add bx, cx ; Last scan column + sub bx, [mx_ClipX2] + jle @@ClipL2 ; No need to clip right + sub cx, bx ; Clip right +@@ClipL2: + test cx, cx ; Is clipped width positive? + jle @@Exit ; No, exit + mov [ScanCount], cx ; Save number of columns to draw + mov [ScanOffsetT], si ; Remember offset of (clipped) buffer + mov ds, [mx_CodeSegment] ; DS:SI -> scan buffer + +;------------------------------ +; Check if Y clipping is needed + mov ax, [BoxY1] + cmp ax, [mx_ClipY1] + jl @@ClipTB ; Need to clip top + mov ax, [BoxY2] + cmp ax, [mx_ClipY2] + jg @@ClipTB ; Need to clip bottom + jmp @@ClipYExit ; Skip Y clipping + +;-------------------- +; Clip top and bottom +@@ClipTB: + mov di, cx ; DI = scan count + inc di ; Increment count for pre-loop test + sub si, SIZE TSCAN +@@ClipYLoop: + dec di ; Any column left? + jz @@ClipYExit ; No, exit + add si, SIZE TSCAN + mov ax, ds:[si].Y1 ; Y1 + mov cx, ds:[si].Y2 ; Y2 + mov dx, [mx_ClipY2] + cmp ax, dx ; Full clipped? + jg @@ClipYClip ; Yes, skip this column + cmp cx, dx ; Need to clip bottom? + jle @@ClipY1 ; No, continue +; Clip bottom, need to scale colors too + mov ds:[si].Y2, dx + mov bx, cx + sub bx, dx ; Clip distance + sub cx, ax ; Height + jle @@ClipYClip + mov ax, WORD PTR ds:[si].E1 + sub ax, WORD PTR ds:[si].E2 + imul bx + idiv cx + add WORD PTR ds:[si].E2, ax + mov ax, ds:[si].Y1 ; Restore AX and CX + mov cx, ds:[si].Y2 +@@ClipY1: + mov dx, [mx_ClipY1] + cmp cx, dx ; Full top clipped? + jl @@ClipYClip ; Yes, skip + sub cx, ax ; Get height + jle @@ClipYClip ; Skip if not positive + cmp ax, dx ; Need to clip top? + jge @@ClipYLoop ; No, continue +; Clip top, need to scale colors too + mov ds:[si].Y1, dx ; Y1 = mx_ClipY1 + sub dx, ax ; DX = number of pixels clipped + cmp cx, dx + jbe @@ClipYClip ; Full clipped, skip + mov ax, WORD PTR ds:[si].E2 + sub ax, WORD PTR ds:[si].E1 ; AX = color distance + imul dx + idiv cx + add WORD PTR ds:[si].E1, ax ; Update starting color + jmp @@ClipYLoop +@@ClipYClip: + mov ds:[si].Y1, -1 ; Mark column as clipped + jmp @@ClipYLoop +@@ClipYExit: + +;------------- +; Draw columns + mov es, [mx_VideoSegment] + mov si, [ScanOffsetT] + mov cl, BYTE PTR [BoxX1] ; Init write plane + and cl, 03h + mov al, 11h + shl al, cl + mov [WritePlane], al + .shr [BoxX1], 2 + mov ax, [Color] ; Make 8:8 fixed color + mov ah, al + xor al, al + mov [Color], ax +@@DrawLoop: + mov ax, ds:[si].Y1 + test ax, ax ; Was column clipped? + js @@DrawNext ; Yes, skip + mov cx, ds:[si].Y2 + sub cx, ax ; CX = height + jle @@DrawNext + mul [mx_BytesPerLine] ; Get pixel address + add ax, [BoxX1] + mov di, ax + mov ah, [WritePlane] + mov al, 02h + mov dx, TS + out dx, ax + mov dx, [Color] + call subFillScan +@@DrawNext: + rol [WritePlane], 1 + adc [BoxX1], 0 ; Bump pointer to video memory if needed + add si, SIZE TSCAN + dec [ScanCount] + jnz @@DrawLoop + +@@Exit: + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxGouraudPoly ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxpi.asm b/16/xw/mxpi.asm new file mode 100755 index 00000000..9e8525f5 --- /dev/null +++ b/16/xw/mxpi.asm @@ -0,0 +1,267 @@ +;----------------------------------------------------------- +; +; MXPI.ASM - Put image +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxPutImage + +EXTRN subClipImage : NEAR + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_VideoSegment : WORD +EXTRN mx_BytesPerLine : WORD + +mxTable LABEL WORD ; Raster ops + DW subMove + DW subAnd + DW subOr + DW subXor + DW subTrans + DW subAdd + +;----------------------------------------------------------- +; +; Move functions. +; Note: loops unrolled and optimized for CX even, no check for CX = 0. +; +subMove PROC NEAR + shr cx, 1 ; Make CX even + jc @@Odd ; Special case if odd byte +@@Loop: movsb + add si, 3 + movsb + add si, 3 + dec cx + jnz @@Loop +@@Exit: ret +@@Odd: movsb + add si, 3 + jcxz @@Exit + jmp @@Loop +subMove ENDP +; +subAnd PROC NEAR + shr cx, 1 + jc @@Odd +@@Loop: mov al, ds:[si] + mov ah, ds:[si+4] + and es:[di], ax + inc di + inc di + add si, 8 + dec cx + jnz @@Loop +@@Exit: ret +@@Odd: lodsb + and es:[di], al + inc di + add si, 3 + jcxz @@Exit + jmp @@Loop +subAnd ENDP +; +subOr PROC NEAR + shr cx, 1 + jc @@Odd +@@Loop: mov al, ds:[si] + mov ah, ds:[si+4] + or es:[di], ax + inc di + inc di + add si, 8 + dec cx + jnz @@Loop +@@Exit: ret +@@Odd: lodsb + or es:[di], al + inc di + add si, 3 + jcxz @@Exit + jmp @@Loop +subOr ENDP +; +subXor PROC NEAR + shr cx, 1 + jc @@Odd +@@Loop: mov al, ds:[si] + mov ah, ds:[si+4] + xor es:[di], ax + inc di + inc di + add si, 8 + dec cx + jnz @@Loop +@@Exit: ret +@@Odd: lodsb + xor es:[di], al + inc di + add si, 3 + jcxz @@Exit + jmp @@Loop +subXor ENDP +; +subTrans PROC NEAR +@@Loop: mov al, ds:[si] + cmp al, ah + je @@Skip + mov es:[di], al +@@Skip: inc di + add si, 4 + dec cx + jnz @@Loop +@@Exit: ret +subTrans ENDP +; +subAdd PROC NEAR +@@Loop: mov al, ds:[si] + add es:[di], al + inc di + add si, 4 + dec cx + jnz @@Loop + ret +subAdd ENDP + +;----------------------------------------------------------- +; +; Copies a "raw" image from memory to screen. +; +; Input: +; Image = pointer to image +; X, Y = coordinates of destination +; Width = width of image in pixels +; Height = height of image in pixels +; Op = raster op (OP_xxx) +; Output: +; none +; +mxPutImage PROC FAR + ARG Op:WORD, \ + Height:WORD, \ + Width:WORD, \ + Y:WORD, \ + X:WORD, \ + Image:DWORD = ARG_SIZE + LOCAL PlaneWidth:WORD:4, \ + PixelOffset:WORD, \ + MoveFunction:WORD, \ + Count:BYTE, \ + ReadPlane:BYTE, \ + OpInfo:BYTE, \ + WritePlane:BYTE = AUTO_SIZE + ASSUME ds:NOTHING + .enter AUTO_SIZE + .push ds, si, es, di + +; Clip image + mov bx, [X] + mov ax, [Y] + mov cx, [Width] + mov dx, [Height] + call subClipImage + jc @@Exit ; Full clipped + mov [Height], dx + add WORD PTR Image[0], si ; Skip clipped pixels + +; Get pixel address + mul [mx_BytesPerLine] + mov di, bx + shr di, 1 + shr di, 1 + add di, ax + mov [PixelOffset], di + mov es, [mx_VideoSegment] ; ES:DI points to pixel + and bl, 03h + mov [ReadPlane], bl + +; Compute extra bytes and width count for each plane + mov bx, cx + shr bx, 1 + shr bx, 1 ; Width for each plane + and cl, 03h + mov al, 00001000b + shr al, cl + mov si, 3 SHL 1 +@@PatchLoop: + mov PlaneWidth[si], bx + shr al, 1 + adc bx, 0 + dec si + dec si + jge @@PatchLoop + +; Setup planes for output to VGA registers + mov cl, [ReadPlane] + mov al, 00010001b + shl al, cl + mov [WritePlane], al + +; Install move function + mov bx, [Op] + mov [OpInfo], bh ; Remember additional info if needed + xor bh, bh + cmp bl, OP_ADD + jbe @@SetMoveFunction + xor bl, bl +@@SetMoveFunction: + shl bx, 1 + mov ax, mxTable[bx] + mov [MoveFunction], ax + +; Put image + cld + mov [Count], 4 ; Four planes + lea bx, PlaneWidth ; SS:[BX] = width in bytes for plane + mov ds, WORD PTR Image[2] +@@PlaneLoop: + cmp WORD PTR ss:[bx], 0 ; Exit if nothing more to do + je @@Exit ; (also, never try to move zero bytes!) + mov si, WORD PTR Image[0] + mov ah, [WritePlane] + and ah, 0Fh + mov al, 02h + mov dx, TS + out dx, ax ; Select write plane + mov ah, [ReadPlane] + and ah, 03h + mov al, 04h + mov dx, GDC + out dx, ax ; Select read plane + mov dx, [Height] + mov di, [PixelOffset] +@@Loop: + push si + push di + mov cx, WORD PTR ss:[bx] ; Number of bytes to move + mov ah, [OpInfo] ; Transparent color for subTrans + call [MoveFunction] + pop di + pop si + add si, [Width] ; Go to next image line + add di, [mx_BytesPerLine] ; Go to next screen row + dec dx + jnz @@Loop ; Repeat for all lines + inc bx + inc bx ; Select width for next plane + inc [ReadPlane] + rol [WritePlane], 1 + adc [PixelOffset], 0 + inc WORD PTR Image[0] + dec [Count] + jnz @@PlaneLoop ; Repeat for all planes + +@@Exit: + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxPutImage ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxpn.asm b/16/xw/mxpn.asm new file mode 100755 index 00000000..eaaf61b4 --- /dev/null +++ b/16/xw/mxpn.asm @@ -0,0 +1,60 @@ +;----------------------------------------------------------- +; +; MXPN.ASM - Panning function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxPan + +EXTRN mxWaitDisplay : FAR +EXTRN mxStartAddress : FAR + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD + +;----------------------------------------------------------- +; +; Moves the screen. +; +; Input: +; X, Y = new X, Y coordinates of view screen +; Output: +; none +; +mxPan PROC FAR + ARG Y:WORD, \ + X:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + + mov ax, [Y] + mul [mx_BytesPerLine] + mov dx, [X] + shr dx, 1 + shr dx, 1 + add ax, dx + push ax ; Push the start address + call mxWaitDisplay + call mxStartAddress + + mov dx, 03DAh ; Set the pixel pan register + in al, dx + mov dx, 03C0h + mov al, 33h + out dx, al + mov al, BYTE PTR [X] + and al, 3 + shl al, 1 + out dx, al + + xor ax, ax + .leave ARG_SIZE +mxPan ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxpp.asm b/16/xw/mxpp.asm new file mode 100755 index 00000000..fc1755a3 --- /dev/null +++ b/16/xw/mxpp.asm @@ -0,0 +1,121 @@ +;----------------------------------------------------------- +; +; MXPP.ASM - Get/put pixel functions +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxGetPixel +PUBLIC mxPutPixel + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD +EXTRN mx_VideoSegment : WORD +EXTRN mx_ClipX1 : WORD +EXTRN mx_ClipY1 : WORD +EXTRN mx_ClipX2 : WORD +EXTRN mx_ClipY2 : WORD + +;----------------------------------------------------------- +; +; Gets a pixel. +; +; Input: +; X, Y = pixel coordinates +; Output: +; pixel color +; +mxGetPixel PROC FAR + ARG Y:WORD, \ + X:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si + + xor ax, ax + mov si, [X] + cmp si, [mx_ClipX1] + jl @@Exit + cmp si, [mx_ClipX2] + jg @@Exit + mov bx, [Y] + cmp bx, [mx_ClipY1] + jl @@Exit + cmp bx, [mx_ClipY2] + jg @@Exit + + mov al, 04h ; Set read plane + mov ah, BYTE PTR [X] + and ah, 3 + mov dx, GDC + out dx, ax + + mov ds, [mx_VideoSegment] + mov ax, bx + mul [mx_BytesPerLine] + .shr si, 2 + add si, ax + + mov al, ds:[si] ; Get pixel value + xor ah, ah + +@@Exit: + .pop ds, si + .leave ARG_SIZE +mxGetPixel ENDP + +;----------------------------------------------------------- +; +; Puts a pixel of the specified color. +; +; Input: +; X, Y = pixel coordinates +; Color = pixel color +; Output: +; none +; +mxPutPixel PROC FAR + ARG Color:BYTE:2, \ + Y:WORD, \ + X:WORD = ARG_SIZE + .enter 0 + .push ds, si + + mov si, [X] + cmp si, [mx_ClipX1] + jl @@Exit + cmp si, [mx_ClipX2] + jg @@Exit + mov ax, [Y] + cmp ax, [mx_ClipY1] + jl @@Exit + cmp ax, [mx_ClipY2] + jg @@Exit + + mov ds, [mx_VideoSegment] + mul [mx_BytesPerLine] + .shr si, 2 + add si, ax + + mov cl, BYTE PTR [X] ; Set write plane + and cl, 3 + mov ax, 0102h + shl ah, cl + mov dx, TS + out dx, ax + + mov al, [Color] ; Write pixel + mov ds:[si], al + +@@Exit: + xor ax, ax + .pop ds, si + .leave ARG_SIZE +mxPutPixel ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxra.asm b/16/xw/mxra.asm new file mode 100755 index 00000000..dd8e6839 --- /dev/null +++ b/16/xw/mxra.asm @@ -0,0 +1,37 @@ +;----------------------------------------------------------- +; +; MXRA.ASM - Row address +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxRowAddress + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Sets the row address register. +; +; Input: +; RowAddress = row size in words +; Output: +; none +; +mxRowAddress PROC FAR + ARG RowAddress:BYTE:2 = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + mov dx, CRTC + mov al, 13h + mov ah, [RowAddress] + out dx, ax + xor ax, ax + .leave ARG_SIZE +mxRowAddress ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxrp.asm b/16/xw/mxrp.asm new file mode 100755 index 00000000..de820c16 --- /dev/null +++ b/16/xw/mxrp.asm @@ -0,0 +1,101 @@ +;----------------------------------------------------------- +; +; MXRP.ASM - Rotate palette function +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxRotatePalette + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Rotates the palette of the specified number of colors. +; +; Input: +; Palette = pointer to palette +; Count = number of colors to rotate +; Step = step size +; Output: +; none +; +; Note: if Step is positive palette is rotated left to right, otherwise +; right to left. +; +mxRotatePalette PROC FAR + ARG Step:WORD, \ + Count:WORD, \ + Palette:DWORD = ARG_SIZE + LOCAL Holder:BYTE:768 = AUTO_SIZE + ASSUME ds:NOTHING + .enter AUTO_SIZE + .push ds, si, es, di + + mov bx, [Count] + add bx, bx + add bx, [Count] ; BX = Count*3 + + lds si, [Palette] ; DS:SI -> palette + push ss + pop es + lea di, Holder ; ES:DI -> local space + cld + + mov ax, [Step] + mov dx, ax + test ax, ax + jz @@Exit ; Nothing to do, exit + jl @@RightToLeft + +@@LeftToRight: + add ax, ax + add dx, ax ; DX = Step*3 + sub bx, dx ; BX = (Count-Step)*3 + add si, bx + push si + mov cx, dx + rep movsb + mov es, WORD PTR Palette[2] + mov di, si + dec di ; ES:DI -> last byte of palette + pop si + dec si + mov cx, bx + std + rep movsb + push ss + pop ds + lea si, Holder + les di, [Palette] + mov cx, dx + cld + rep movsb + jmp @@Exit + +@@RightToLeft: + add ax, ax + add dx, ax + neg dx ; DX = Step*3 + sub bx, dx ; BX = (Count-Step)*3 + mov cx, dx + rep movsb + les di, [Palette] + mov cx, bx + rep movsb + push ss + pop ds + lea si, Holder + mov cx, dx + rep movsb + +@@Exit: + .pop ds, si, es, di + .leave ARG_SIZE +mxRotatePalette ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxsa.asm b/16/xw/mxsa.asm new file mode 100755 index 00000000..3ebae67d --- /dev/null +++ b/16/xw/mxsa.asm @@ -0,0 +1,44 @@ +;----------------------------------------------------------- +; +; MXSA.ASM - Start address function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxStartAddress + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Modifies the starting address of video memory. +; +; Input: +; StartAddr = new start address of video memory +; Output: +; none +; +mxStartAddress PROC FAR + ARG StartAddr:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + + mov bx, [StartAddr] + mov dx, CRTC + mov al, 0Ch ; Linear Starting Address high + mov ah, bh + cli + out dx, ax + mov al, 0Dh ; Linear Starting Address low + mov ah, bl + out dx, ax + sti + + .leave ARG_SIZE +mxStartAddress ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxsc.asm b/16/xw/mxsc.asm new file mode 100755 index 00000000..bcae45e6 --- /dev/null +++ b/16/xw/mxsc.asm @@ -0,0 +1,50 @@ +;----------------------------------------------------------- +; +; MXSC.ASM - Set color function +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxSetColor + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Updates the selected DAC register. +; +; Input: +; Index = index of color to set +; R, G, B = color components +; Output: +; none +; +mxSetColor PROC FAR + ARG B:BYTE:2, \ + G:BYTE:2, \ + R:BYTE:2, \ + Index:WORD = ARG_SIZE + .enter 0 + .push ds, si + + mov ax, [Index] + mov dx, 3C8h ; PEL write address register + out dx, al + inc dx + + mov al, [R] + out dx, al + mov al, [G] + out dx, al + mov al, [B] + out dx, al + + .pop ds, si + .leave ARG_SIZE +mxSetColor ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxsi.asm b/16/xw/mxsi.asm new file mode 100755 index 00000000..b88d3b11 --- /dev/null +++ b/16/xw/mxsi.asm @@ -0,0 +1,317 @@ +;----------------------------------------------------------- +; +; MXPI.ASM - Stretch image +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxStretchImage + +EXTRN subClipBox : NEAR + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_VideoSegment : WORD +EXTRN mx_BytesPerLine : WORD + +mxTable LABEL WORD ; Raster ops + DW subMove + DW subAnd + DW subOr + DW subXor + DW subTrans + DW subAdd + +;----------------------------------------------------------- +; +; Stretches and copies a "raw" image from memory to screen. +; +; Input: +; Image = pointer to image +; X, Y = coordinates of destination +; Width = width of image in pixels +; Height = height of image in pixels +; NewWidth = new width of image in pixels +; NewHeight = new height of image in pixels +; Op = raster op (OP_xxx) +; Output: +; none +; +mxStretchImage PROC FAR + ARG Op:WORD, \ + NewHeight:WORD, \ + NewWidth:WORD, \ + Height:WORD, \ + Width:WORD, \ + Y:WORD, \ + X:WORD, \ + Image:DWORD = ARG_SIZE + LOCAL PixelOffset:WORD, \ + MoveFunction:WORD, \ + ReadPlane:BYTE, \ + OpInfo:BYTE, \ + WidthStep:DWORD, \ + HeightStep:DWORD, \ + ImageLo:WORD, \ + WritePlane:BYTE = AUTO_SIZE + ASSUME ds:NOTHING + .enter AUTO_SIZE + .push ds, si, es, di + +; Get width stretch factor + IF USE386 EQ TRUE + movzx edx, [Width] + xor eax, eax + movzx ebx, [NewWidth] + shl ebx, 16 + idiv ebx + mov [WidthStep], eax + ELSE + xor dx, dx ; Width stretch factor + mov ax, [Width] + mov bx, [NewWidth] + div bx + mov WORD PTR WidthStep[2], ax + xor ax, ax + div bx + mov WORD PTR WidthStep[0], ax + ENDIF +; Get height stretch factor + IF USE386 EQ TRUE + movzx edx, [Height] + xor eax, eax + movzx ebx, [NewHeight] + shl ebx, 16 + idiv ebx + mov [HeightStep], eax + ELSE + xor dx, dx + mov ax, [Height] + mov bx, [NewHeight] + div bx + mov WORD PTR HeightStep[2], ax + xor ax, ax + div bx + mov WORD PTR HeightStep[0], ax + ENDIF + +; Clip image + mov bx, [X] + mov ax, [Y] + mov cx, [NewWidth] + mov dx, [NewHeight] + call subClipBox + jc @@Exit ; Full clipped + mov [NewWidth], cx + mov [NewHeight], dx + sub [X], bx + sub [Y], ax + +; Get pixel address + mul [mx_BytesPerLine] + mov di, bx + shr di, 1 + shr di, 1 + add di, ax + mov [PixelOffset], di + mov es, [mx_VideoSegment] ; ES:DI points to pixel + and bl, 03h + mov [ReadPlane], bl ; Set read plane + mov cl, bl + mov al, 00010001b + shl al, cl + mov [WritePlane], al ; Set write plane + +; Relocate image origin if previously clipped + mov ax, [Y] + test ax, ax + jz @@OriginYDone + IF USE386 EQ TRUE + shl eax, 16 + imul [HeightStep] + mov ax, [Width] + mul dx + ELSE + mov bx, ax + mul WORD PTR HeightStep[0] + mov cx, dx + mov ax, bx + mul WORD PTR HeightStep[2] + add ax, cx + mul [Width] + ENDIF + add WORD PTR [Image], ax +@@OriginYDone: + mov ax, [X] + test ax, ax + jz @@OriginXDone + IF USE386 EQ TRUE + shl eax, 16 + imul [WidthStep] + add WORD PTR [Image], dx + ELSE + mov bx, ax + mul WORD PTR WidthStep[0] + mov cx, dx + mov ax, bx + mul WORD PTR WidthStep[2] + add ax, cx + add WORD PTR [Image], ax + ENDIF +@@OriginXDone: + mov ax, WORD PTR HeightStep[2] + mul [Width] + mov WORD PTR HeightStep[2], ax + +; Install move function + mov bx, [Op] + mov [OpInfo], bh ; Remember additional info if needed + xor bh, bh + cmp bl, OP_ADD + jbe @@SetMoveFunction + xor bl, bl +@@SetMoveFunction: + shl bx, 1 + mov ax, mxTable[bx] + mov [MoveFunction], ax + +; Put image + mov ds, WORD PTR Image[2] + xor ax, ax + mov [ImageLo], ax +@@Loop: + mov si, WORD PTR Image[0] ; Get pointer to image + mov ah, [WritePlane] + and ah, 0Fh + mov al, 02h + mov dx, TS + out dx, ax ; Select write plane + mov ah, [ReadPlane] + and ah, 03h + mov al, 04h + mov dx, GDC + out dx, ax ; Select read plane + mov cx, [NewHeight] + mov di, [PixelOffset] ; ES:DI points to video memory + mov ah, [OpInfo] ; Additional raster op info + xor bx, bx + mov dx, [mx_BytesPerLine] + call [MoveFunction] ; Draw column + inc [ReadPlane] ; Next read plane + rol [WritePlane], 1 ; Next write plane + adc [PixelOffset], 0 ; Update video offset if needed + mov dx, WORD PTR WidthStep[0] + mov ax, WORD PTR WidthStep[2] + add [ImageLo], dx + adc WORD PTR Image[0], ax ; Next image column + dec [NewWidth] + jnz @@Loop ; Repeat for all columns + +@@Exit: + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE + +;----------------------------------------------------------- +; +; Move functions, on entry: +; AH = additional raster op info (e.g. transparent color) +; BX = 0, +; CX = pixel count, +; DX = mx_BytesPerLine. +; +subMove PROC NEAR +@@Loop: mov al, ds:[si] + mov es:[di], al + add di, dx + dec cx + jz @@Exit + add si, WORD PTR HeightStep[2] + add bx, WORD PTR HeightStep[0] + jnc @@Loop + add si, [Width] + jmp @@Loop +@@Exit: ret +subMove ENDP +; +subAnd PROC NEAR +@@Loop: mov al, ds:[si] + and es:[di], al + add di, dx + dec cx + jz @@Exit + add si, WORD PTR HeightStep[2] + add bx, WORD PTR HeightStep[0] + jnc @@Loop + add si, [Width] + jmp @@Loop +@@Exit: ret +subAnd ENDP +; +subOr PROC NEAR +@@Loop: mov al, ds:[si] + or es:[di], al + add di, dx + dec cx + jz @@Exit + add si, WORD PTR HeightStep[2] + add bx, WORD PTR HeightStep[0] + jnc @@Loop + add si, [Width] + jmp @@Loop +@@Exit: ret +subOr ENDP +; +subXor PROC NEAR +@@Loop: mov al, ds:[si] + xor es:[di], al + add di, dx + dec cx + jz @@Exit + add si, WORD PTR HeightStep[2] + add bx, WORD PTR HeightStep[0] + jnc @@Loop + add si, [Width] + jmp @@Loop +@@Exit: ret +subXor ENDP +; +subTrans PROC NEAR +@@Loop: mov al, ds:[si] + cmp al, ah + je @@Skip + mov es:[di], al +@@Skip: + add di, dx + dec cx + jz @@Exit + add si, WORD PTR HeightStep[2] + add bx, WORD PTR HeightStep[0] + jnc @@Loop + add si, [Width] + jmp @@Loop +@@Exit: ret +subTrans ENDP +; +subAdd PROC NEAR +@@Loop: mov al, ds:[si] + add es:[di], al + add di, dx + dec cx + jz @@Exit + add si, WORD PTR HeightStep[2] + add bx, WORD PTR HeightStep[0] + jnc @@Loop + add si, [Width] + jmp @@Loop +@@Exit: ret +subAdd ENDP + +mxStretchImage ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxsl.asm b/16/xw/mxsl.asm new file mode 100755 index 00000000..d7908855 --- /dev/null +++ b/16/xw/mxsl.asm @@ -0,0 +1,62 @@ +;----------------------------------------------------------- +; +; MXLN.ASM - Start line function +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxStartLine + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD + +;----------------------------------------------------------- +; +; Changes the video start address to the specified line. +; +; Input: +; Line = new start line +; Output: +; none +; +mxStartLine PROC FAR + ARG Line:WORD = ARG_SIZE + .enter 0 + ASSUME ds:NOTHING + + mov ax, [Line] ; Get video offset + mul [mx_BytesPerLine] + xchg ax, bx ; Copy it into BX + +; Wait display + mov dx, STATUS +@@1: in al, dx + test al, 08h + jnz @@1 + +; Set starting address + mov dx, CRTC + mov al, 0Ch ; Linear Starting Address high + mov ah, bh + cli + out dx, ax + mov al, 0Dh ; Linear Starting Address low + mov ah, bl + out dx, ax + sti + +; Wait retrace + mov dx, STATUS +@@2: in al,dx + test al, 08h + jz @@2 + + xor ax, ax + .leave ARG_SIZE +MX_TEXT ENDS +END diff --git a/16/xw/mxsm.asm b/16/xw/mxsm.asm new file mode 100755 index 00000000..183fba1e --- /dev/null +++ b/16/xw/mxsm.asm @@ -0,0 +1,508 @@ +;----------------------------------------------------------- +; +; MXSM.ASM - Set/change mode functions +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxChangeMode +PUBLIC mxGetAspect +PUBLIC mxGetScreenSize +PUBLIC mxSetMode + +PUBLIC mx_ScreenWidth +PUBLIC mx_ScreenHeight +PUBLIC mx_BytesPerLine + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mxSetSysClipRegion : FAR + +EXTRN mx_VideoSegment : WORD +EXTRN mx_CodeSegment : WORD + +mx_ScreenWidth DW ? ; Current screen width +mx_ScreenHeight DW ? +mx_AspectX DW ? ; Aspect ratio for current mode +mx_AspectY DW ? +mx_BytesPerLine DW 0 ; Bytes per line + +; +; Tables for setting video modes, sources: +; - MODEX.ASM, Matt Pritchard +; - Dr. Dobb's Journal, Michael Abrash +; - Fractint VIDEO.ASM module +; +TBL_SingleLine LABEL WORD ; CRTC + DW 04009h ; Cell height: 1 scan line + DW 00014h ; Double word mode off + DW 0E317h ; Byte mode on + DW 0 +TBL_DoubleLine LABEL WORD ; CRTC + DW 04109h ; Cell height: 2 scan lines + DW 00014h + DW 0E317h + DW 0 +TBL_Width320 LABEL WORD ; CRTC + DW 05F00h ; Horizontal total + DW 04F01h ; Horizontal displayed + DW 05002h ; Start horizontal blanking + DW 08203h ; End horizontal blanking + DW 05404h ; Start horizontal sync + DW 08005h ; End horizontal sync + DW 02813h ; Row address + DW 0 +TBL_Width360 LABEL WORD ; CRTC + DW 06B00h ; Horizontal total + DW 05901h ; Horizontal displayed + DW 05A02h ; Start horizontal blanking + DW 08E03h ; End horizontal blanking + DW 05E04h ; Start horizontal sync + DW 08A05h ; End horizontal sync + DW 02D13h ; Row address + DW 0 +TBL_Height175 LABEL WORD ; CRTC + DW 0BF06h ; Vertical total + DW 01F07h ; Overflow + DW 08310h ; Start vertical sync + DW 08511h ; End vertical sync + DW 05D12h ; Vertical displayed + DW 06315h ; Start vertical blanking + DW 0BA16h ; End vertical blanking + DW 0 +TBL_Height200 LABEL WORD ; CRTC + DW 0BF06h ; Vertical total + DW 01F07h ; Overflow + DW 09C10h ; Start vertical sync + DW 08E11h ; End vertical sync + DW 08F12h ; Vertical displayed + DW 09615h ; Start vertical blanking + DW 0B916h ; End vertical blanking + DW 0 +TBL_Height240 LABEL WORD ; CRTC + DW 00D06h ; Vertical total + DW 03E07h ; Overflow + DW 0EA10h ; Start vertical sync + DW 08C11h ; End vertical sync + DW 0DF12h ; Vertical displayed + DW 0E715h ; Start vertical blanking + DW 00616h ; End vertical blanking + DW 0 +TBL_Tweak400x600: + DW 07400h + DW 06301h + DW 06402h + DW 09703h + DW 06804h + DW 09505h + DW 08606h + DW 0F007h + DW 06009h + DW 0310Fh + DW 05B10h + DW 08D11h + DW 05712h + DW 03213h + DW 00014h + DW 06015h + DW 08016h + DW 0E317h + DW 0 + +TBL_320x200: + DB 63h ; 400 scan lines, 25 MHz clock + DW 6, 5 ; Aspect: 6/5 = 1.2:1 + DW 320, 200 ; Size + DW TBL_Width320, TBL_Height200, TBL_DoubleLine, 0 + DW 819 ; Max height +TBL_320x240: + DB 0E3h ; 400 scan lines, 25 MHz clock + DW 1, 1 ; Aspect: 1/1 = 1:1 + DW 320, 240 ; Size + DW TBL_Width320, TBL_Height240, TBL_DoubleLine, 0 + DW 819 ; Max height +TBL_320x400: + DB 63h ; 480 scan lines, 25 MHz clock + DW 6, 10 ; Aspect: 6/10 = 0.6:1 + DW 320, 400 ; Size + DW TBL_Width320, TBL_Height200, TBL_SingleLine, 0 + DW 819 ; Max height +TBL_320x480: + DB 0E3h ; 480 scan lines, 25 MHz clock + DW 1, 2 ; Aspect: 1/2 = 0.5:1 + DW 320, 480 ; Size + DW TBL_Width320, TBL_Height240, TBL_SingleLine, 0 + DW 819 ; Max height +TBL_360x200: + DB 067h ; 400 scan lines, 28 MHz clock + DW 27, 20 ; Aspect: 27/20 = 1.35:1 + DW 360, 200 ; Size + DW TBL_Width360, TBL_Height200, TBL_DoubleLine, 0 + DW 728 ; Max height +TBL_360x240: + DB 0E7h ; 480 scan lines, 28 MHz clock + DW 9, 8 ; Aspect: 9/8 = 1.125:1 + DW 360, 240 ; Size + DW TBL_Width360, TBL_Height240, TBL_DoubleLine, 0 + DW 728 ; Max height +TBL_360x400: + DB 067h ; 400 scan lines, 28 MHz clock + DW 27, 40 ; Aspect: 27/40 = 0.675:1 + DW 360, 400 ; Size + DW TBL_Width360, TBL_Height200, TBL_SingleLine, 0 + DW 728 ; Max height +TBL_360x480: + DB 0E7h ; 480 scan lines, 28 MHz clock + DW 9, 16 ; Aspect: 9/16 = 0.5625:1 + DW 360, 480 ; Size + DW TBL_Width360, TBL_Height240, TBL_SingleLine, 0 + DW 728 ; Max height +TBL_320x175: + DB 0A3h + DW 0, 0 ; Aspect: + DW 320, 175 + DW TBL_Width320, TBL_Height175, TBL_DoubleLine, 0 + DW 819 +TBL_320x350: + DB 0A3h + DW 0, 0 ; Aspect: + DW 320, 175 + DW TBL_Width320, TBL_Height175, TBL_SingleLine, 0 + DW 819 +TBL_360x175: + DB 0A7h + DW 0, 0 ; Aspect: + DW 360, 480 ; Size + DW TBL_Width360, TBL_Height175, TBL_DoubleLine, 0 + DW 728 ; Max height +TBL_360x350: + DB 0A7h + DW 0, 0 ; Aspect: + DW 360, 480 ; Size + DW TBL_Width360, TBL_Height175, TBL_SingleLine, 0 + DW 728 ; Max height +TBL_400x600: + DB 0E7h ; 28 MHz clock + DW 1, 2 ; Aspect: 1/2 = 0.5:1 + DW 400, 600 ; Size + DW TBL_Tweak400x600, 0 + DW 655 ; Max height + +TBL_Mode LABEL WORD + DW TBL_320x175 + DW TBL_320x200 + DW TBL_320x240 + DW TBL_320x350 + DW TBL_320x400 + DW TBL_320x480 + DW TBL_360x175 + DW TBL_360x200 + DW TBL_360x240 + DW TBL_360x350 + DW TBL_360x400 + DW TBL_360x480 + DW TBL_400x600 + +MAXVMODE EQU ($-OFFSET TBL_Mode) / 2 + +;----------------------------------------------------------- +; +; Enables 80x25 color text mode +; +subText PROC NEAR + ASSUME ds:MX_TEXT + mov ax, 0003h + int 10h ; Call BIOS set mode + + mov [mx_ScreenHeight], 0 + mov [mx_BytesPerLine], 0 + ret +subText ENDP + +;----------------------------------------------------------- +; +; Enables the selected graphics mode. +; +; Input: +; Mode = mode to select (MX_???x???) +; Output: +; none +; +mxSetMode PROC FAR + ARG Mode:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si, es, di + +; Set DS to code segment alias + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov si, [Mode] + cmp si, MAXVMODE ; Is it a valid mode? + ja @@Exit ; No, exit + test si, si ; Text mode? + jnz @@Set ; No, handle it + + call subText ; Back to text mode + jmp @@Exit ; Exit now + +; Set video mode +@@Set: + dec si ; Skip text mode + shl si, 1 + mov si, TBL_Mode[si] + cld + +; Use BIOS to set 320x200x256 linear mode + push si ; Save SI + mov ax, 0013h + int 10h ; Use BIOS to set 320x200 linear mode + pop si ; Restore SI + + mov dx, TS + mov ax, 0604h + out dx, ax ; Disable chain-4 mode + mov ax, 0100h + out dx, ax ; Reset + mov dx, MISC + lodsb + out dx, al ; New timing/size + mov dx, TS + mov ax, 0300h + out dx, ax ; Restart sequencer + +; Unlock CRTC registers 0-7 + mov dx, CRTC + mov al, 11h + out dx, al ; Vertical sync end register + inc dx + in al, dx + and al, 7Fh ; Clear write protect bit + out dx, al + + lodsw ; Get X aspect + mov [mx_AspectX], ax + lodsw ; Get Y aspect + mov [mx_AspectY], ax + lodsw ; Get screen width + mov [mx_ScreenWidth], ax + shr ax, 1 + shr ax, 1 ; Divide by four to get bytes per line + mov [mx_BytesPerLine], ax + lodsw ; Get screen height + mov [mx_ScreenHeight], ax + +; Set CRTC registers + mov bx, si + mov dx, CRTC +@@TableLoop: + mov si, ds:[bx] ; DS:SI -> table of CRTC registers + inc bx + inc bx ; DS:BX -> offset of next table + test si, si ; Last table? + jz @@EndLoop ; Yes, exit loop +@@Loop: + lodsw ; Get CRTC register index and value + test ax, ax ; End of table? + jz @@TableLoop ; Yes, go to next table + out dx, ax ; Set register AL to value AH + jmp @@Loop ; Get next register/value +@@EndLoop: + +; Set virtual screen and system clip region + push [mx_ScreenWidth] + push WORD PTR ds:[bx] + call mxSetSysClipRegion + +; Clear video memory + mov dx, TS + mov ax, 0F02h + out dx, ax ; Enable all planes + mov es, [mx_VideoSegment] + xor di, di + mov cx, 8000h + xor ax, ax + rep stosw + +@@Done: +; Lock CRTC registers 0-7 (some cards need this) + mov dx, CRTC + mov al, 11h + out dx, al ; Vertical sync end register + inc dx + in al, dx + or al, 80h ; Set write protect bit + out dx, al + +@@Exit: + xor ax, ax + mov ax, [mx_ScreenWidth] + .pop ds, si, es, di + .leave ARG_SIZE +mxSetMode ENDP + +;----------------------------------------------------------- +; +; Changes from the current mode the selected graphics mode. +; +; Input: +; Mode = mode to select (MX_???x???) +; Output: +; none +; Notes: +; this function assumes that mxSetMode and mxSetVirtualScreen +; have been called first. View size is rearranged to match the +; specified mode, but video memory is not cleared. +; Differences from mxSetMode: +; - video BIOS is not called to initialize graphics; +; - row address register is not modified; +; - video memory is not cleared; +; - mx_BytesPerLine is not modified; +; - system clip region is not modified. +; +mxChangeMode PROC FAR + ARG Mode:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si, es, di + +; Set DS to code segment alias + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov si, [Mode] + cmp si, MAXVMODE ; Is it a valid mode? + ja @@Exit ; No, exit + test si, si ; Text mode? + jz @@Exit ; Yes, exit + + dec si ; Skip text mode + shl si, 1 + mov si, TBL_Mode[si] + cld + + mov dx, TS + mov ax, 0604h + out dx, ax ; Disable chain-4 mode + mov ax, 0100h + out dx, ax ; Reset + mov dx, MISC + lodsb + out dx, al ; New timing/size + mov dx, TS + mov ax, 0300h + out dx, ax ; Restart sequencer + +; Unlock CRTC registers 0-7 + mov dx, CRTC + mov al, 11h + out dx, al ; Vertical sync end register + inc dx + in al, dx + and al, 7Fh ; Clear write protect bit + out dx, al + + lodsw ; Get X aspect + mov [mx_AspectX], ax + lodsw ; Get Y aspect + mov [mx_AspectY], ax + lodsw ; Get screen width + mov [mx_ScreenWidth], ax + lodsw ; Get screen height + mov [mx_ScreenHeight], ax + +; Set CRTC registers + mov bx, si + mov dx, CRTC +@@TableLoop: + mov si, ds:[bx] ; DS:SI -> table of CRTC registers + inc bx + inc bx ; DS:BX -> offset of next table + test si, si ; Last table? + jz @@EndLoop ; Yes, exit loop +@@Loop: + lodsw ; Get CRTC register index and value + test ax, ax ; End of table? + jz @@TableLoop ; Yes, go to next table + cmp al, 13h ; Row address register? + je @@Loop ; Yes, ignore it + out dx, ax ; Set register AL to value AH + jmp @@Loop ; Get next register/value +@@EndLoop: + +; Lock CRTC registers 0-7 (some cards need this) + mov dx, CRTC + mov al, 11h + out dx, al ; Vertical sync end register + inc dx + in al, dx + or al, 80h ; Set write protect bit + out dx, al + +@@Exit: + xor ax, ax + mov ax, [mx_ScreenWidth] + .pop ds, si, es, di + .leave ARG_SIZE +mxChangeMode ENDP + +;----------------------------------------------------------- +; +; Returns the aspect ratio for the current mode. +; +; Input: +; AspectX = pointer to aspect X +; AspectY = pointer to aspect Y +; +; A rectangle of width AspectX and height AspectY looks like a square. +; +mxGetAspect PROC FAR + ARG AspectY:DWORD, \ + AspectX:DWORD = ARG_SIZE + .enter 0 + .push ds, si + ASSUME ds:NOTHING + + lds si, [AspectX] + mov ax, [mx_AspectX] + mov ds:[si], ax + lds si, [AspectY] + mov ax, [mx_AspectY] + mov ds:[si], ax + + .pop ds, si + .leave ARG_SIZE +mxGetAspect ENDP + +;----------------------------------------------------------- +; +; Returns the current screen size. +; +; Input: +; Width = pointer to screen width +; Height = pointer to screen height +; +mxGetScreenSize PROC FAR + ARG SizeY:DWORD, \ + SizeX:DWORD = ARG_SIZE + .enter 0 + .push ds, si + ASSUME ds:NOTHING + + lds si, [SizeX] + mov ax, [mx_ScreenWidth] + mov ds:[si], ax + lds si, [SizeY] + mov ax, [mx_ScreenHeight] + mov ds:[si], ax + + .pop ds, si + .leave ARG_SIZE +mxGetScreenSize ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxsp.asm b/16/xw/mxsp.asm new file mode 100755 index 00000000..1d08e711 --- /dev/null +++ b/16/xw/mxsp.asm @@ -0,0 +1,57 @@ +;----------------------------------------------------------- +; +; MXSP.ASM - Set palette function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxSetPalette + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Updates the VGA palette. +; +; Input: +; Buffer = pointer to palette data (R,G,B) +; Start = index of first color to set +; Count = number of color to set +; Output: +; none +; +mxSetPalette PROC FAR + ARG Count:WORD, \ + Start:WORD, \ + Buffer:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si + + lds si, [Buffer] + mov cx, [Count] + mov ax, [Start] + mov dx, 3C8h ; PEL write address register + out dx, al + inc dx + cld + cli ; Disable interrupts +@@Loop: + lodsb + out dx, al ; Red + lodsb + out dx, al ; Green + lodsb + out dx, al ; Blue + loop @@Loop ; Loop until done + sti ; Enable interrupts + + .pop ds, si + .leave ARG_SIZE +mxSetPalette ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxss.asm b/16/xw/mxss.asm new file mode 100755 index 00000000..97df7366 --- /dev/null +++ b/16/xw/mxss.asm @@ -0,0 +1,72 @@ +;----------------------------------------------------------- +; +; MXSS.ASM - Split screen function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxSplitScreen + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Splits the screen. +; +; Input: +; Line = scan line at which screen has to be splitted +; Output: +; none +; +mxSplitScreen PROC FAR + ARG Line:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + +; Modify the line compare value: bits 0-7 are in the Line Compare +; register (CRTC #18), bit 8 is in the Overflow Low register (CRTC #7) +; and bit 9 is in the Maximum Row Address register (CRTC #9) + mov ax, [Line] + shl ax, 1 ; Adjust line for mode "X" + mov bh, ah + mov bl, ah + and bx, 0201h + mov cl, 4 + shl bx, cl + shl bh, 1 + mov dx, CRTC +; Write bits 0-7 to line compare register + mov ah, al + mov al, 18h + out dx, ax +; Write bit 8 to overflow register + mov al, 07h + out dx, al + inc dx + in al, dx + dec dx + mov ah, al + and ah, 11101111b + or ah, bl + mov al, 07h + out dx, ax +; Write bit 9 to maximum row address register + mov al, 09h + out dx, al + inc dx + in al, dx + dec dx + mov ah, al + and ah, 10111111b + or ah, bh + mov al, 09h + out dx, ax + + .leave ARG_SIZE +mxSplitScreen ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxtl.asm b/16/xw/mxtl.asm new file mode 100755 index 00000000..69900c88 --- /dev/null +++ b/16/xw/mxtl.asm @@ -0,0 +1,169 @@ +;----------------------------------------------------------- +; +; MXTL.ASM - Put tile +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxPutTile +PUBLIC mxTransPutTile + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_VideoSegment : WORD +EXTRN mx_BytesPerLine : WORD + +;----------------------------------------------------------- +; +; Copies a "mode-x" tile from memory to screen. +; +; Input: +; Image = pointer to tile +; X, Y = coordinates of destination +; Width = width of image in pixels (Width and 3 = 0) +; Height = height of image in pixels +; Output: +; none +; Note: +; no clipping is performed on tiles! +; +mxPutTile PROC FAR + ARG Height:WORD, \ + Width:WORD, \ + Y:WORD, \ + X:WORD, \ + Image:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si, es, di + + mov ax, [Y] ; Get pixel address + mul [mx_BytesPerLine] + mov di, [X] + .shr di, 2 + add di, ax + mov es, [mx_VideoSegment] + + lds si, [Image] ; Get tile address + .shr [Width], 2 ; Number of bytes per plane + mov cl, BYTE PTR [X] + and cl, 3 + mov ah, 11h ; AH = plane mask + shl ah, cl ; Align mask to first plane + + mov [Y], 4 ; Number of planes + mov bx, [mx_BytesPerLine] + sub bx, [Width] ; Extra bytes per line +@@Loop: + mov al, 02h + mov dx, TS + out dx, ax ; Set write plane + mov [X], di ; Save video offset + mov dx, [Height] +@@Loop2: + mov cx, [Width] ; Number of bytes to move + + shr cx, 1 ; Move line + rep movsw + rcl cx, 1 + rep movsb + + add di, bx ; Move video offset to next line + dec dx ; Done all lines? + jnz @@Loop2 ; No, continue + mov di, [X] ; Restore video offset + rol ah, 1 ; Next plane + adc di, 0 ; Bump video offset if needed + dec [Y] ; Any plane left? + jnz @@Loop ; Yes, keep looping + + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxPutTile ENDP + +;----------------------------------------------------------- +; +; Copies a "mode-x" tile from memory to screen. +; Skips over color 0. +; +; Input: +; Image = pointer to tile +; X, Y = coordinates of destination +; Width = width of image in pixels (Width and 3 = 0) +; Height = height of image in pixels +; Output: +; none +; Note: +; no clipping is performed on tiles! +; +mxTransPutTile PROC FAR + ARG Height:WORD, \ + Width:WORD, \ + Y:WORD, \ + X:WORD, \ + Image:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si, es, di + + mov ax, [Y] ; Get pixel address + mul [mx_BytesPerLine] + mov di, [X] + .shr di, 2 + add di, ax + mov es, [mx_VideoSegment] + + lds si, [Image] ; Get tile address + .shr [Width], 2 ; Number of bytes per plane + mov cl, BYTE PTR [X] + and cl, 3 + mov ah, 11h ; AH = plane mask + shl ah, cl ; Align mask to first plane + + mov [Y], 4 ; Number of planes + mov bx, [mx_BytesPerLine] + sub bx, [Width] ; Extra bytes per line +@@Loop: + mov al, 02h + mov dx, TS + out dx, ax ; Set write plane + mov [X], di ; Save video offset + mov dx, [Height] +@@Loop2: + mov cx, [Width] ; Number of bytes to move + +; Move one line + jcxz @@MoveLineDone +@@MoveLineLoop: + mov al, ds:[si] + test al, al + jz @@MoveLineNext + mov es:[di], al +@@MoveLineNext: + inc si + inc di + dec cx + jnz @@MoveLineLoop +@@MoveLineDone: + + add di, bx ; Move video offset to next line + dec dx ; Done all lines? + jnz @@Loop2 ; No, continue + mov di, [X] ; Restore video offset + rol ah, 1 ; Next plane + adc di, 0 ; Bump video offset if needed + dec [Y] ; Any plane left? + jnz @@Loop ; Yes, keep looping + + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxTransPutTile ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxvs.asm b/16/xw/mxvs.asm new file mode 100755 index 00000000..992eabab --- /dev/null +++ b/16/xw/mxvs.asm @@ -0,0 +1,110 @@ +;----------------------------------------------------------- +; +; MXVS.ASM - Set/get virtual screen +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +NOWARN RES +INCLUDE MODEX.DEF + +PUBLIC mxSetVirtualScreen +PUBLIC mxGetVirtualScreen + +EXTRN mxRowAddress : FAR +EXTRN mxSetSysClipRegion : FAR + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_BytesPerLine : WORD +EXTRN mx_CodeSegment : WORD + +mx_VirtualWidth DW ? ; Virtual screen size +mx_VirtualHeight DW ? + +;----------------------------------------------------------- +; +; Sets the virtual screen. +; +; Input: +; Width = virtual screen width +; Height = virtual screen height +; Output: +; 0 on success, else invalid parameters +; +mxSetVirtualScreen PROC FAR + ARG Height:WORD, \ + Width:WORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds + +; Set DS to code segment + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, 1 ; Assume an error + cmp [Width], 320 ; Check width + jb @@Exit + push ax ; Save return code + mov dx, 0004h + xor ax, ax ; DX:AX = 256K + div [Width] ; Max height in AX + cmp [Height], ax + pop ax ; Restore return code + ja @@Exit ; Exit if bad heigth + + mov ax, [Width] + and ax, 0FFF8h ; Align to byte + mov [mx_VirtualWidth], ax + shr ax, 1 + shr ax, 1 + mov [mx_BytesPerLine], ax + shr ax, 1 + push ax + call mxRowAddress ; Set row address + mov ax, [Height] + mov [mx_VirtualHeight], ax + + push [Width] + push [Height] + call mxSetSysClipRegion + xor ax, ax + +@@Exit: + .pop ds + .leave ARG_SIZE +mxSetVirtualScreen ENDP + +;----------------------------------------------------------- +; +; Returns the current virtual screen size. +; +; Input: +; Width = pointer to virtual screen width +; Height = pointer to virtual screen height +; Output: +; none +; +mxGetVirtualScreen PROC FAR + ARG Height:DWORD, \ + Width:DWORD = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + .push ds, si + + mov ax, [mx_VirtualWidth] + lds si, [Width] + mov ds:[si], ax + mov ax, [mx_VirtualHeight] + lds si, [Height] + mov ds:[si], ax + + xor ax, ax + .pop ds, si + .leave ARG_SIZE +mxGetVirtualScreen ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxwd.asm b/16/xw/mxwd.asm new file mode 100755 index 00000000..de55208f --- /dev/null +++ b/16/xw/mxwd.asm @@ -0,0 +1,28 @@ +;----------------------------------------------------------- +; +; MXWD.ASM - Wait display function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxWaitDisplay + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Waits for display start. +; +mxWaitDisplay PROC FAR + mov dx, STATUS +@@1: in al, dx + test al, 08h + jnz @@1 + ret +mxWaitDisplay ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxwm.asm b/16/xw/mxwm.asm new file mode 100755 index 00000000..06158859 --- /dev/null +++ b/16/xw/mxwm.asm @@ -0,0 +1,39 @@ +;----------------------------------------------------------- +; +; MXWM.ASM - Set write mode function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxWriteMode + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Sets the write mode. +; +; Input: +; Mode = write mode (0,1,2,3) +; Output: +; none +; +mxWriteMode PROC FAR + ARG Mode:BYTE:2 = ARG_SIZE + .enter 0 + + mov dx, GDC + mov ah, [Mode] + and ah, 00000011b + or ah, 01000000b + mov al, 05h + out dx, ax + + .leave ARG_SIZE +mxWriteMode ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxwp.asm b/16/xw/mxwp.asm new file mode 100755 index 00000000..19ca99d0 --- /dev/null +++ b/16/xw/mxwp.asm @@ -0,0 +1,62 @@ +;----------------------------------------------------------- +; +; MXWP.ASM - Set write/read plane functions +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxWritePlane +PUBLIC mxReadPlane + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Sets the write plane(s). +; +; Input: +; Plane = write plane(s) to set (bit 0 enables plane 0, +; bit 1 enables plane 1 and so on, different planes +; may be selected at the same time) +; Output: +; none +; +mxWritePlane PROC FAR + ARG Plane:BYTE:2 = ARG_SIZE + .enter 0 + + mov ah, [Plane] + and ah, 00001111b ; Mask off unused bits + mov al, 02h + mov dx, TS + out dx, ax + + .leave ARG_SIZE +mxWritePlane ENDP + +;----------------------------------------------------------- +; +; Sets the read plane. +; +; Input: +; Plane = read plane to set (0,1,2,3) +; Output: +; none +; +mxReadPlane PROC FAR + ARG Plane:BYTE:2 = ARG_SIZE + ASSUME ds:NOTHING + .enter 0 + mov al, 04h + mov ah, [Plane] + and ah, 0000011b ; Mask off unused bits + mov dx, GDC + out dx, ax + .leave ARG_SIZE +mxReadPlane ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/mxwr.asm b/16/xw/mxwr.asm new file mode 100755 index 00000000..bd29fe59 --- /dev/null +++ b/16/xw/mxwr.asm @@ -0,0 +1,28 @@ +;----------------------------------------------------------- +; +; MXWR.ASM - Wait vertical retrace function +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxWaitRetrace + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +;----------------------------------------------------------- +; +; Waits for vertical retrace start. +; +mxWaitRetrace PROC FAR + mov dx, STATUS +@@1: in al,dx + test al, 08h + jz @@1 + ret +mxWaitRetrace ENDP + +MX_TEXT ENDS +END diff --git a/16/xw/readme.txt b/16/xw/readme.txt new file mode 100755 index 00000000..306e8b9a --- /dev/null +++ b/16/xw/readme.txt @@ -0,0 +1,8 @@ +ModeX - A graphical library for DOS programs +Copyright (c) 1993-1994 Alessandro Scotti +http://www.ascotti.org/ + +Please look at the above site in the "Art of..." and +then in the "Old programs" section for more information. + + diff --git a/16/xw_/default.fnt b/16/xw_/default.fnt new file mode 100755 index 00000000..12eb22cb --- /dev/null +++ b/16/xw_/default.fnt @@ -0,0 +1,260 @@ +; +; MODEX library default font +; Copyright (c) 1993-1994 by Alessandro Scotti +; + DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; #0 + DB 07Eh, 081h, 0A5h, 081h, 0A5h, 099h, 081h, 07Eh ; #1 + DB 07Eh, 0FFh, 0DBh, 0FFh, 0DBh, 0E7h, 0FFh, 07Eh ; #2 + DB 06Ch, 0FEh, 0FEh, 0FEh, 07Ch, 038h, 010h, 000h ; #3 + DB 010h, 038h, 07Ch, 0FEh, 07Ch, 038h, 010h, 000h ; #4 + DB 010h, 038h, 010h, 054h, 0FEh, 054h, 010h, 0FEh ; #5 + DB 010h, 038h, 07Ch, 0FEh, 0FEh, 07Ch, 010h, 0FEh ; #6 + DB 000h, 018h, 03Ch, 07Eh, 07Eh, 03Ch, 018h, 000h ; #7 + DB 0FFh, 0E7h, 0C3h, 081h, 081h, 0C3h, 0E7h, 0FFh ; #8 + DB 000h, 03Ch, 066h, 042h, 042h, 066h, 03Ch, 000h ; #9 + DB 0FFh, 0C3h, 099h, 0BDh, 0BDh, 099h, 0C3h, 0FFh ; #10 + DB 007h, 003h, 005h, 078h, 084h, 084h, 084h, 078h ; #11 + DB 07Ch, 082h, 082h, 082h, 07Ch, 010h, 038h, 010h ; #12 + DB 01Ch, 010h, 01Ch, 010h, 010h, 010h, 030h, 030h ; #13 + DB 03Eh, 022h, 03Eh, 022h, 022h, 026h, 066h, 060h ; #14 + DB 099h, 05Ah, 03Ch, 0E7h, 0E7h, 03Ch, 05Ah, 099h ; #15 + DB 000h, 010h, 030h, 070h, 0F0h, 070h, 030h, 010h ; #16 + DB 000h, 080h, 0C0h, 0E0h, 0F0h, 0E0h, 0C0h, 080h ; #17 + DB 010h, 038h, 054h, 010h, 010h, 054h, 038h, 010h ; #18 + DB 048h, 048h, 048h, 048h, 048h, 000h, 048h, 000h ; #19 + DB 07Eh, 092h, 092h, 072h, 012h, 012h, 012h, 000h ; #20 + DB 03Ch, 022h, 018h, 024h, 024h, 018h, 044h, 03Ch ; #21 + DB 000h, 000h, 000h, 000h, 000h, 03Eh, 03Eh, 000h ; #22 + DB 038h, 054h, 010h, 010h, 010h, 054h, 038h, 0FEh ; #23 + DB 000h, 010h, 038h, 054h, 010h, 010h, 010h, 000h ; #24 + DB 000h, 010h, 010h, 010h, 054h, 038h, 010h, 000h ; #25 + DB 000h, 008h, 004h, 0FEh, 004h, 008h, 000h, 000h ; #26 + DB 000h, 020h, 040h, 0FEh, 040h, 020h, 000h, 000h ; #27 + DB 000h, 000h, 080h, 080h, 080h, 0FCh, 000h, 000h ; #28 + DB 000h, 024h, 042h, 0FFh, 042h, 024h, 000h, 000h ; #29 + DB 000h, 000h, 010h, 038h, 07Ch, 0FEh, 000h, 000h ; #30 + DB 000h, 000h, 0FEh, 07Ch, 038h, 010h, 000h, 000h ; #31 + DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; + DB 010h, 010h, 010h, 010h, 010h, 000h, 010h, 000h ; ! + DB 000h, 024h, 024h, 000h, 000h, 000h, 000h, 000h ; " + DB 024h, 024h, 07Eh, 024h, 07Eh, 024h, 024h, 000h ; # + DB 038h, 054h, 050h, 038h, 014h, 054h, 038h, 010h ; $ + DB 000h, 002h, 044h, 008h, 010h, 020h, 042h, 000h ; % + DB 038h, 044h, 038h, 060h, 094h, 088h, 074h, 000h ; & + DB 020h, 020h, 040h, 000h, 000h, 000h, 000h, 000h ; ' + DB 010h, 020h, 040h, 040h, 040h, 020h, 010h, 000h ; ( + DB 040h, 020h, 010h, 010h, 010h, 020h, 040h, 000h ; ) + DB 000h, 024h, 018h, 07Eh, 018h, 024h, 000h, 000h ; * + DB 000h, 010h, 010h, 07Ch, 010h, 010h, 000h, 000h ; + + DB 000h, 000h, 000h, 000h, 000h, 010h, 010h, 020h ; , + DB 000h, 000h, 000h, 0FCh, 000h, 000h, 000h, 000h ; - + DB 000h, 000h, 000h, 000h, 000h, 000h, 010h, 000h ; . + DB 000h, 004h, 008h, 010h, 020h, 040h, 080h, 000h ; / + DB 07Ch, 0C6h, 08Ah, 092h, 0A2h, 0C6h, 07Ch, 000h ; 0 + DB 010h, 030h, 010h, 010h, 010h, 010h, 038h, 000h ; 1 + DB 078h, 084h, 004h, 018h, 060h, 080h, 0FCh, 000h ; 2 + DB 078h, 084h, 004h, 038h, 004h, 084h, 078h, 000h ; 3 + DB 01Ch, 024h, 044h, 084h, 0FEh, 004h, 00Eh, 000h ; 4 + DB 0FCh, 080h, 0F8h, 004h, 004h, 084h, 078h, 000h ; 5 + DB 078h, 084h, 080h, 0F8h, 084h, 084h, 078h, 000h ; 6 + DB 0FCh, 004h, 004h, 008h, 010h, 020h, 020h, 000h ; 7 + DB 078h, 084h, 084h, 078h, 084h, 084h, 078h, 000h ; 8 + DB 078h, 084h, 084h, 07Ch, 004h, 084h, 078h, 000h ; 9 + DB 000h, 000h, 010h, 000h, 000h, 000h, 010h, 000h ; : + DB 000h, 000h, 010h, 000h, 000h, 010h, 010h, 020h ; ; + DB 008h, 010h, 020h, 040h, 020h, 010h, 008h, 000h ; < + DB 000h, 000h, 0FCh, 000h, 000h, 0FCh, 000h, 000h ; = + DB 040h, 020h, 010h, 008h, 010h, 020h, 040h, 000h ; > + DB 078h, 084h, 004h, 008h, 010h, 000h, 010h, 000h ; ? + DB 07Ch, 082h, 0BAh, 0A6h, 0BEh, 080h, 07Ch, 000h ; @ + DB 078h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h ; A + DB 0F8h, 084h, 084h, 0F8h, 084h, 084h, 0F8h, 000h ; B + DB 078h, 084h, 080h, 080h, 080h, 084h, 078h, 000h ; C + DB 0F0h, 088h, 084h, 084h, 084h, 088h, 0F0h, 000h ; D + DB 0FCh, 080h, 080h, 0F0h, 080h, 080h, 0FCh, 000h ; E + DB 0FCh, 080h, 080h, 0F0h, 080h, 080h, 080h, 000h ; F + DB 078h, 084h, 080h, 09Ch, 084h, 084h, 078h, 000h ; G + DB 084h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h ; H + DB 038h, 010h, 010h, 010h, 010h, 010h, 038h, 000h ; I + DB 01Ch, 008h, 008h, 008h, 088h, 088h, 070h, 000h ; J + DB 084h, 088h, 090h, 0E0h, 090h, 088h, 084h, 000h ; K + DB 080h, 080h, 080h, 080h, 080h, 080h, 0FCh, 000h ; L + DB 0C6h, 0AAh, 092h, 082h, 082h, 082h, 082h, 000h ; M + DB 082h, 0C2h, 0A2h, 092h, 08Ah, 086h, 082h, 000h ; N + DB 078h, 084h, 084h, 084h, 084h, 084h, 078h, 000h ; O + DB 0F8h, 084h, 084h, 0F8h, 080h, 080h, 080h, 000h ; P + DB 078h, 084h, 084h, 084h, 094h, 088h, 076h, 000h ; Q + DB 0F8h, 084h, 084h, 0F8h, 090h, 088h, 084h, 000h ; R + DB 078h, 084h, 080h, 078h, 004h, 084h, 078h, 000h ; S + DB 0FEh, 010h, 010h, 010h, 010h, 010h, 010h, 000h ; T + DB 084h, 084h, 084h, 084h, 084h, 084h, 078h, 000h ; U + DB 084h, 084h, 084h, 084h, 084h, 048h, 030h, 000h ; V + DB 082h, 082h, 082h, 082h, 092h, 0AAh, 0C6h, 000h ; W + DB 082h, 044h, 028h, 010h, 028h, 044h, 082h, 000h ; X + DB 044h, 044h, 044h, 038h, 010h, 010h, 010h, 000h ; Y + DB 0FEh, 004h, 008h, 010h, 020h, 040h, 0FEh, 000h ; Z + DB 078h, 040h, 040h, 040h, 040h, 040h, 078h, 000h ; [ + DB 000h, 080h, 040h, 020h, 010h, 008h, 004h, 000h ; \ + DB 078h, 008h, 008h, 008h, 008h, 008h, 078h, 000h ; ] + DB 010h, 028h, 044h, 082h, 000h, 000h, 000h, 000h ; ^ + DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0FFh ; _ + DB 020h, 020h, 010h, 000h, 000h, 000h, 000h, 000h ; ` + DB 000h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; a + DB 000h, 040h, 040h, 078h, 044h, 044h, 078h, 000h ; b + DB 000h, 000h, 03Ch, 040h, 040h, 040h, 03Ch, 000h ; c + DB 000h, 004h, 004h, 03Ch, 044h, 044h, 03Ch, 000h ; d + DB 000h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; e + DB 000h, 00Ch, 010h, 03Ch, 010h, 010h, 010h, 000h ; f + DB 000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 038h ; g + DB 000h, 040h, 040h, 078h, 044h, 044h, 044h, 000h ; h + DB 000h, 010h, 000h, 010h, 010h, 010h, 010h, 000h ; i + DB 000h, 004h, 000h, 004h, 004h, 004h, 044h, 038h ; j + DB 000h, 040h, 040h, 050h, 060h, 050h, 048h, 000h ; k + DB 000h, 030h, 010h, 010h, 010h, 010h, 010h, 000h ; l + DB 000h, 000h, 068h, 054h, 054h, 044h, 044h, 000h ; m + DB 000h, 000h, 078h, 044h, 044h, 044h, 044h, 000h ; n + DB 000h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; o + DB 000h, 000h, 078h, 044h, 044h, 078h, 040h, 040h ; p + DB 000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 004h ; q + DB 000h, 000h, 05Ch, 060h, 040h, 040h, 040h, 000h ; r + DB 000h, 000h, 038h, 040h, 07Ch, 004h, 07Ch, 000h ; s + DB 000h, 010h, 038h, 010h, 010h, 010h, 018h, 000h ; t + DB 000h, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; u + DB 000h, 000h, 044h, 044h, 044h, 028h, 010h, 000h ; v + DB 000h, 000h, 044h, 044h, 054h, 054h, 06Ch, 000h ; w + DB 000h, 000h, 044h, 028h, 010h, 028h, 044h, 000h ; x + DB 000h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch ; y + DB 000h, 000h, 07Ch, 004h, 038h, 040h, 07Ch, 000h ; z + DB 000h, 008h, 010h, 010h, 030h, 010h, 010h, 008h ; { + DB 000h, 010h, 010h, 010h, 000h, 010h, 010h, 010h ; | + DB 000h, 020h, 010h, 010h, 018h, 010h, 010h, 020h ; } + DB 064h, 098h, 000h, 000h, 000h, 000h, 000h, 000h ; ~ + DB 000h, 010h, 028h, 044h, 082h, 082h, 0FEh, 000h ;  + DB 07Ch, 080h, 080h, 080h, 080h, 07Ch, 004h, 07Ch ; #128 + DB 000h, 028h, 000h, 044h, 044h, 044h, 038h, 000h ; #129 + DB 03Ch, 000h, 07Ch, 044h, 07Ch, 040h, 07Ch, 000h ; #130 + DB 07Eh, 081h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #131 + DB 024h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #132 + DB 078h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #133 + DB 018h, 018h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #134 + DB 000h, 000h, 078h, 080h, 080h, 078h, 008h, 038h ; #135 + DB 07Ch, 082h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #136 + DB 048h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #137 + DB 078h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #138 + DB 000h, 028h, 000h, 010h, 010h, 010h, 010h, 000h ; #139 + DB 010h, 028h, 000h, 010h, 010h, 010h, 010h, 000h ; #140 + DB 000h, 030h, 000h, 010h, 010h, 010h, 010h, 000h ; #141 + DB 048h, 000h, 078h, 084h, 0FCh, 084h, 084h, 000h ; #142 + DB 030h, 030h, 078h, 084h, 0FCh, 084h, 084h, 000h ; #143 + DB 038h, 000h, 0FCh, 080h, 0F0h, 080h, 0FCh, 000h ; #144 + DB 000h, 000h, 07Eh, 008h, 07Eh, 048h, 07Eh, 000h ; #145 + DB 07Eh, 090h, 090h, 0FCh, 090h, 090h, 09Eh, 000h ; #146 + DB 07Ch, 082h, 038h, 044h, 044h, 044h, 038h, 000h ; #147 + DB 028h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #148 + DB 070h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #149 + DB 038h, 044h, 000h, 044h, 044h, 044h, 038h, 000h ; #150 + DB 070h, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; #151 + DB 028h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch ; #152 + DB 048h, 000h, 078h, 084h, 084h, 084h, 078h, 000h ; #153 + DB 048h, 000h, 084h, 084h, 084h, 084h, 078h, 000h ; #154 + DB 000h, 010h, 038h, 040h, 040h, 040h, 038h, 010h ; #155 + DB 038h, 044h, 040h, 0E0h, 040h, 040h, 082h, 0FCh ; #156 + DB 044h, 07Ch, 010h, 07Ch, 010h, 07Ch, 010h, 000h ; #157 + DB 0F0h, 088h, 08Ah, 0F7h, 082h, 082h, 082h, 000h ; #158 + DB 00Ch, 012h, 010h, 018h, 030h, 010h, 090h, 060h ; #159 + DB 03Ch, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #160 + DB 000h, 018h, 000h, 010h, 010h, 010h, 010h, 000h ; #161 + DB 01Ch, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #162 + DB 01Ch, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; #163 + DB 07Ch, 000h, 078h, 044h, 044h, 044h, 044h, 000h ; #164 + DB 07Ch, 000h, 044h, 064h, 054h, 04Ch, 044h, 000h ; #165 + DB 018h, 024h, 024h, 01Eh, 000h, 03Eh, 000h, 000h ; #166 + DB 01Ch, 022h, 022h, 01Ch, 000h, 03Eh, 000h, 000h ; #167 + DB 010h, 000h, 010h, 020h, 040h, 042h, 03Ch, 000h ; #168 + DB 000h, 000h, 000h, 0FCh, 080h, 080h, 000h, 000h ; #169 + DB 000h, 000h, 000h, 0FCh, 004h, 004h, 000h, 000h ; #170 + DB 040h, 044h, 048h, 057h, 021h, 047h, 004h, 007h ; #171 + DB 040h, 044h, 048h, 052h, 026h, 04Ah, 01Fh, 002h ; #172 + DB 010h, 000h, 010h, 010h, 010h, 010h, 010h, 000h ; #173 + DB 000h, 024h, 048h, 090h, 048h, 024h, 000h, 000h ; #174 + DB 000h, 048h, 024h, 012h, 024h, 048h, 000h, 000h ; #175 + DB 022h, 088h, 022h, 088h, 022h, 088h, 022h, 088h ; #176 + DB 055h, 0AAh, 055h, 0AAh, 055h, 0AAh, 055h, 0AAh ; #177 + DB 0DBh, 077h, 0DBh, 0EEh, 0DBh, 077h, 0DBh, 0EEh ; #178 + DB 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h ; #179 + DB 018h, 018h, 018h, 018h, 0F8h, 018h, 018h, 018h ; #180 + DB 018h, 018h, 0F8h, 018h, 0F8h, 018h, 018h, 018h ; #181 + DB 036h, 036h, 036h, 036h, 0F6h, 036h, 036h, 036h ; #182 + DB 000h, 000h, 000h, 000h, 0FEh, 036h, 036h, 036h ; #183 + DB 000h, 000h, 0F8h, 018h, 0F8h, 018h, 018h, 018h ; #184 + DB 036h, 036h, 0F6h, 006h, 0F6h, 036h, 036h, 036h ; #185 + DB 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h ; #186 + DB 000h, 000h, 0FEh, 006h, 0F6h, 036h, 036h, 036h ; #187 + DB 036h, 036h, 0F6h, 006h, 0FEh, 000h, 000h, 000h ; #188 + DB 036h, 036h, 036h, 036h, 0FEh, 000h, 000h, 000h ; #189 + DB 018h, 018h, 0F8h, 018h, 0F8h, 000h, 000h, 000h ; #190 + DB 000h, 000h, 000h, 000h, 0F8h, 018h, 018h, 018h ; #191 + DB 018h, 018h, 018h, 018h, 01Fh, 000h, 000h, 000h ; #192 + DB 018h, 018h, 018h, 018h, 0FFh, 000h, 000h, 000h ; #193 + DB 000h, 000h, 000h, 000h, 0FFh, 018h, 018h, 018h ; #194 + DB 018h, 018h, 018h, 018h, 01Fh, 018h, 018h, 018h ; #195 + DB 000h, 000h, 000h, 000h, 0FFh, 000h, 000h, 000h ; #196 + DB 018h, 018h, 018h, 018h, 0FFh, 018h, 018h, 018h ; #197 + DB 018h, 018h, 01Fh, 018h, 01Fh, 018h, 018h, 018h ; #198 + DB 036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h ; #199 + DB 036h, 036h, 037h, 030h, 03Fh, 000h, 000h, 000h ; #200 + DB 000h, 000h, 03Fh, 030h, 037h, 036h, 036h, 036h ; #201 + DB 036h, 036h, 0F7h, 000h, 0FFh, 000h, 000h, 000h ; #202 + DB 000h, 000h, 0FFh, 000h, 0F7h, 036h, 036h, 036h ; #203 + DB 036h, 036h, 037h, 030h, 037h, 036h, 036h, 036h ; #204 + DB 000h, 000h, 0FFh, 000h, 0FFh, 000h, 000h, 000h ; #205 + DB 036h, 036h, 0F7h, 000h, 0F7h, 036h, 036h, 036h ; #206 + DB 018h, 018h, 0FFh, 000h, 0FFh, 000h, 000h, 000h ; #207 + DB 036h, 036h, 036h, 036h, 0FFh, 000h, 000h, 000h ; #208 + DB 000h, 000h, 0FFh, 000h, 0FFh, 018h, 018h, 018h ; #209 + DB 000h, 000h, 000h, 000h, 0FFh, 036h, 036h, 036h ; #210 + DB 036h, 036h, 036h, 036h, 03Fh, 000h, 000h, 000h ; #211 + DB 018h, 018h, 01Fh, 018h, 01Fh, 000h, 000h, 000h ; #212 + DB 000h, 000h, 01Fh, 018h, 01Fh, 018h, 018h, 018h ; #213 + DB 000h, 000h, 000h, 000h, 03Fh, 036h, 036h, 036h ; #214 + DB 036h, 036h, 036h, 036h, 0FFh, 036h, 036h, 036h ; #215 + DB 018h, 018h, 0FFh, 018h, 0FFh, 018h, 018h, 018h ; #216 + DB 018h, 018h, 018h, 018h, 0F8h, 000h, 000h, 000h ; #217 + DB 000h, 000h, 000h, 000h, 01Fh, 018h, 018h, 018h ; #218 + DB 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh ; #219 + DB 000h, 000h, 000h, 000h, 0FFh, 0FFh, 0FFh, 0FFh ; #220 + DB 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h ; #221 + DB 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh ; #222 + DB 0FFh, 0FFh, 0FFh, 0FFh, 000h, 000h, 000h, 000h ; #223 + DB 000h, 000h, 062h, 094h, 088h, 094h, 062h, 000h ; #224 + DB 000h, 0F0h, 088h, 0F0h, 088h, 088h, 0F0h, 080h ; #225 + DB 000h, 0F8h, 088h, 080h, 080h, 080h, 080h, 000h ; #226 + DB 000h, 0FCh, 048h, 048h, 048h, 048h, 048h, 000h ; #227 + DB 0FCh, 084h, 040h, 020h, 040h, 084h, 0FCh, 000h ; #228 + DB 03Ch, 040h, 038h, 044h, 044h, 044h, 038h, 000h ; #229 + DB 000h, 000h, 044h, 044h, 044h, 078h, 040h, 040h ; #230 + DB 000h, 036h, 048h, 008h, 008h, 008h, 008h, 000h ; #231 + DB 038h, 010h, 038h, 044h, 044h, 038h, 010h, 038h ; #232 + DB 078h, 084h, 084h, 0FCh, 084h, 084h, 078h, 000h ; #233 + DB 078h, 084h, 084h, 084h, 048h, 048h, 0CCh, 000h ; #234 + DB 078h, 004h, 038h, 044h, 044h, 044h, 038h, 000h ; #235 + DB 000h, 000h, 06Ch, 092h, 092h, 06Ch, 000h, 000h ; #236 + DB 000h, 000h, 03Ah, 044h, 05Ah, 022h, 05Ch, 000h ; #237 + DB 018h, 020h, 040h, 078h, 040h, 020h, 018h, 000h ; #238 + DB 078h, 084h, 084h, 084h, 084h, 084h, 084h, 000h ; #239 + DB 000h, 0FCh, 000h, 0FCh, 000h, 0FCh, 000h, 000h ; #240 + DB 020h, 020h, 0F8h, 020h, 020h, 000h, 0F8h, 000h ; #241 + DB 020h, 010h, 008h, 010h, 020h, 000h, 07Ch, 000h ; #242 + DB 008h, 010h, 020h, 010h, 008h, 000h, 07Ch, 000h ; #243 + DB 00Ch, 012h, 010h, 010h, 010h, 010h, 010h, 010h ; #244 + DB 010h, 010h, 010h, 010h, 010h, 010h, 090h, 060h ; #245 + DB 000h, 010h, 000h, 07Ch, 000h, 010h, 000h, 000h ; #246 + DB 000h, 032h, 04Ch, 000h, 032h, 04Ch, 000h, 000h ; #247 + DB 038h, 044h, 044h, 038h, 000h, 000h, 000h, 000h ; #248 + DB 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h ; #249 + DB 000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h ; #250 + DB 00Eh, 008h, 008h, 008h, 048h, 028h, 018h, 008h ; #251 + DB 038h, 024h, 024h, 024h, 024h, 000h, 000h, 000h ; #252 + DB 03Ch, 004h, 03Ch, 020h, 03Ch, 000h, 000h, 000h ; #253 + DB 000h, 000h, 03Ch, 03Ch, 03Ch, 03Ch, 000h, 000h ; #254 + DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; #255 diff --git a/16/xw_/makefile b/16/xw_/makefile new file mode 100755 index 00000000..cfe15232 --- /dev/null +++ b/16/xw_/makefile @@ -0,0 +1,132 @@ +# +# MODEX library makefile (for Borland MAKE) +# Copyright (c) 1993,1994 by Alessandro Scotti +# +!ifdef __LINUX__ +REMOVECOMMAND=rm -f +COPYCOMMAND=cp -f +DIRSEP=/ +OBJ=o +!else +REMOVECOMMAND=del +COPYCOMMAND=copy /y +DIRSEP=\ +OBJ=obj +!endif +LIBINCS = modex.def + +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) +#mxfp.$(OBJ) +# +# ASM compiler +# +ASMC =wasm +ASMO =-mh -0 + +# +# PAS compiler +# +#PASC = tpc +#PASO = /m -$D- -$L- -$S- + +# +# LIB maker, uses response file +# +LIBC = wlib + +# .asm.obj: +# $(ASMC) $(ASMO) $< + +mxbb.$(OBJ): mxbb.asm + $(ASMC) $(ASMO) mxbb.asm +mxcc.$(OBJ): mxcc.asm + $(ASMC) $(ASMO) mxcc.asm +mxcg.$(OBJ): mxcg.asm + $(ASMC) $(ASMO) mxcg.asm +mxcl.$(OBJ): mxcl.asm + $(ASMC) $(ASMO) mxcl.asm +mxcr.$(OBJ): mxcr.asm + $(ASMC) $(ASMO) mxcr.asm +mxfb.$(OBJ): mxfb.asm + $(ASMC) $(ASMO) mxfb.asm +mxfp.$(OBJ): mxfp.asm + $(ASMC) $(ASMO) mxfp.asm +mxgc.$(OBJ): mxgc.asm + $(ASMC) $(ASMO) mxgc.asm +mxgi.$(OBJ): mxgi.asm + $(ASMC) $(ASMO) mxgi.asm +mxgm.$(OBJ): mxgm.asm + $(ASMC) $(ASMO) mxgm.asm +mxgp.$(OBJ): mxgp.asm + $(ASMC) $(ASMO) mxgp.asm +mxgv.$(OBJ): mxgv.asm + $(ASMC) $(ASMO) mxgv.asm +mxhl.$(OBJ): mxhl.asm + $(ASMC) $(ASMO) mxhl.asm +mxit.$(OBJ): mxit.asm + $(ASMC) $(ASMO) mxit.asm +mxll.$(OBJ): mxll.asm + $(ASMC) $(ASMO) mxll.asm +mxln.$(OBJ): mxln.asm + $(ASMC) $(ASMO) mxln.asm +mxot.$(OBJ): mxot.asm + $(ASMC) $(ASMO) mxot.asm +mxpb.$(OBJ): mxpb.asm + $(ASMC) $(ASMO) mxpb.asm +mxpf.$(OBJ): mxpf.asm + $(ASMC) $(ASMO) mxpf.asm +mxpg.$(OBJ): mxpg.asm + $(ASMC) $(ASMO) mxpg.asm +mxpi.$(OBJ): mxpi.asm + $(ASMC) $(ASMO) mxpi.asm +mxpn.$(OBJ): mxpn.asm + $(ASMC) $(ASMO) mxpn.asm +mxpp.$(OBJ): mxpp.asm + $(ASMC) $(ASMO) mxpp.asm +mxra.$(OBJ): mxra.asm + $(ASMC) $(ASMO) mxra.asm +mxrp.$(OBJ): mxrp.asm + $(ASMC) $(ASMO) mxrp.asm +mxsa.$(OBJ): mxsa.asm + $(ASMC) $(ASMO) mxsa.asm +mxsc.$(OBJ): mxsc.asm + $(ASMC) $(ASMO) mxsc.asm +mxsi.$(OBJ): mxsi.asm + $(ASMC) $(ASMO) mxsi.asm +mxsl.$(OBJ): mxsl.asm + $(ASMC) $(ASMO) mxsl.asm +mxsm.$(OBJ): mxsm.asm + $(ASMC) $(ASMO) mxsm.asm +mxsp.$(OBJ): mxsp.asm + $(ASMC) $(ASMO) mxsp.asm +mxss.$(OBJ): mxss.asm + $(ASMC) $(ASMO) mxss.asm +mxtl.$(OBJ): mxtl.asm + $(ASMC) $(ASMO) mxtl.asm +mxvs.$(OBJ): mxvs.asm + $(ASMC) $(ASMO) mxvs.asm +mxwd.$(OBJ): mxwd.asm + $(ASMC) $(ASMO) mxwd.asm +mxwm.$(OBJ): mxwm.asm + $(ASMC) $(ASMO) mxwm.asm +mxwp.$(OBJ): mxwp.asm + $(ASMC) $(ASMO) mxwp.asm +mxwr.$(OBJ): mxwr.asm + $(ASMC) $(ASMO) mxwr.asm + +all: $(LIBOBJS) modex.lib +# modex.tpu modex.tpp + +#modex.tpu: $(LIBOBJS) modex.pas +# $(PASC) $(PASO) modex +# copy modex.tpu .. +# copy modex.pas .. + +#modex.tpp: $(LIBOBJS) modex.pas +# $(PASC) /cp $(PASO) modex +# copy modex.tpp .. + +modex.lib: modex.lbr $(LIBOBJS) + $(LIBC) modex.lib @modex.lbr + +$(LIBOBJS): modex.def diff --git a/16/xw_/makefile.bcc b/16/xw_/makefile.bcc new file mode 100755 index 00000000..d3ad8b71 --- /dev/null +++ b/16/xw_/makefile.bcc @@ -0,0 +1,81 @@ +# +# MODEX library makefile (for Borland MAKE) +# Copyright (c) 1993,1994 by Alessandro Scotti +# +LIBINCS = MODEX.DEF + +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 + +# +# ASM compiler +# +ASMC = tasm +ASMO = /m5 /p + +# +# PAS compiler +# +PASC = tpc +PASO = /m -$D- -$L- -$S- + +# +# LIB maker, uses response file +# +LIBC = tlib + +.asm.obj: + $(ASMC) $(ASMO) $< + +target: modex.lib +# modex.tpu modex.tpp + +#modex.tpu: $(LIBOBJS) modex.pas +# $(PASC) $(PASO) modex +# copy modex.tpu .. +# copy modex.pas .. + +#modex.tpp: $(LIBOBJS) modex.pas +# $(PASC) /cp $(PASO) modex +# copy modex.tpp .. + +modex.lib: modex.lbr $(LIBOBJS) + $(LIBC) modex.lib @modex.lbr + +$(LIBOBJS): modex.def diff --git a/16/xw_/modex.bak b/16/xw_/modex.bak new file mode 100755 index 0000000000000000000000000000000000000000..560a1c68304c56844f41325820f296a21192ac4e GIT binary patch literal 25600 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 literal 0 HcmV?d00001 diff --git a/16/xw_/modex.def b/16/xw_/modex.def new file mode 100755 index 00000000..7977a4a0 --- /dev/null +++ b/16/xw_/modex.def @@ -0,0 +1,163 @@ +;------------------------------------------------------------ +; +; MODEX.DEF - Include file +; Copyright (c) 1993-1994 by Alessandro Scotti +; +;JUMPS +;LOCALS + +TRUE EQU 1 ; Boolean constants +FALSE EQU 0 + +USE286 = FALSE ; TRUE enables 80286 instructions +USE386 = FALSE ; TRUE enables 80386 (and 80286) instructions + +IF USE286 EQ TRUE + P286 +ENDIF + +IF USE386 EQ TRUE + P386 + USE286 = TRUE +ENDIF + +MXVERSION EQU 0128h ; Library version (1.40) + +;------------------------------------------------------------ +; +; VGA definitions +; +MISC EQU 3C2h ; Miscellaneous output +TS EQU 3C4h ; Timing Sequencer index register +GDC EQU 3CEh ; Graphics Data Controller index register +CRTC EQU 3D4h ; CRTC index register +STATUS EQU 3DAh ; Input Status register one + +;------------------------------------------------------------ +; +; Raster operators +; +OP_SET EQU 0 +OP_MOVE EQU 0 ; Same as OP_SET +OP_AND EQU 1 +OP_OR EQU 2 +OP_XOR EQU 3 +OP_TRANS EQU 4 +OP_ADD EQU 5 ; Must be last op + +;------------------------------------------------------------ +; +; Polygon fill functions +; +POLYSCANBUFSIZE EQU 4*1024 + +;------------------------------------------------------------ +; Macro to push registers, variables or flags onto the stack +; Usage: .push "loc16"[,"loc16"...] +; where "loc16" is a 16-bit register, a word-sized variable or the +; keyword "FLAGS". +; Exmpl: .push ax, flags, var1 +; .pop ax, flags, var1 +; +.push MACRO r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10 + IFNB + .ERROR <.PUSH has more than 10 arguments> + ENDIF + IRP $reg, + IFB <$reg> ;; Is argument blank? + EXITM ;; Yes, exit + ELSEIFIDNI <$reg>, ;; Is argument the keyword "FLAGS"? + pushf ;; Yes, push flags + ELSE + push $reg ;; Push argument + ENDIF + ENDM +ENDM + +;------------------------------------------------------------ +; Macro to pop registers, variables or flags from the stack +; Usage: .pop "loc16"[,"loc16"...] +; where "loc16" is a 16-bit register, a word-sized variable or the +; keyword "FLAGS". +; Exmpl: .push ax, flags, var1 +; .pop ax, flags, var1 +; +.pop MACRO r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10 + IFNB + .ERROR <.POP has more than 10 arguments> + ENDIF + IRP $reg, + IFNB <$reg> ;; Is argument non-blank? + IFIDNI <$reg>, ;; Yes, is it the keyword "FLAGS"? + popf ;; Yes, pop flags + ELSE + pop $reg ;; Pop argument + ENDIF + ENDIF + ENDM +ENDM + +;------------------------------------------------------------ +; +.enter MACRO localsize + IF USE286 EQ TRUE + enter localsize, 0 + ELSE + push bp + mov bp, sp + sub sp, localsize + ENDIF +ENDM + +;------------------------------------------------------------ +; +;.leave MACRO argsize +; IF USE286 EQ TRUE +; leave +; ELSE +; mov sp, bp +; pop bp +; ENDIF +; IFNB +; ret argsize +; ELSE +; ret +; ENDIF +;ENDM + +;------------------------------------------------------------ +; +;.shr MACRO arg, count +; IF USE286 EQ TRUE +; shr arg, count +; ELSE +; $temp = count +; WHILE $temp GT 0 +; shr arg, 1 +; $temp = $temp-1 +; ENDM +; ENDIF +;ENDM + +;------------------------------------------------------------ +; +;.shl MACRO arg, count +; IF USE286 EQ TRUE +; shl arg, count +; ELSE +; $temp = count +; WHILE $temp GT 0 +; shl arg, 1 +; $temp = $temp-1 +; ENDM +; ENDIF +;ENDM + +;------------------------------------------------------------ +; +;.chk386 MACRO name, jump +; IF USE386 EQ FALSE +; .OUT "Warning: ", , " needs a 386 or better to run!" +; jmp @@jump +; ENDIF +;ENDM diff --git a/16/xw_/modex.h b/16/xw_/modex.h new file mode 100755 index 00000000..2c1f1ebe --- /dev/null +++ b/16/xw_/modex.h @@ -0,0 +1,153 @@ +/* + MODEX.H - C/C++ include file for the MODEX library + Copyright (c) 1994 Alessandro Scotti +*/ + +#ifndef _MODEX_H_ // Avoid nested inclusions +#define _MODEX_H_ + +// +// Video modes +// +#define MX_TEXT 0 // 80x25 text +#define MX_320x175 1 // 320x175x256 +#define MX_320x200 2 // 320x200x256, 4 pages, aspect 6:5 +#define MX_320x240 3 // 320x240x256, 3 pages, aspect 1:1 +#define MX_320x350 4 // 320x350x256 +#define MX_320x400 5 // 320x400x256, 2 pages +#define MX_320x480 6 // 320x480x256, 1 page +#define MX_360x175 7 // 360x175x256 +#define MX_360x200 8 // 360x200x256, 3 pages +#define MX_360x240 9 // 360x240x256, 2 pages +#define MX_360x350 10 // 360x350x256 +#define MX_360x400 11 // 360x400x256, 1 page +#define MX_360x480 12 // 360x480x256, 1 page +#define MX_400x600 13 // 400x600x256, 1 page + +// +// Fade effects +// +#define MX_FADEIN 0 +#define MX_FADEOUT 1 + +// +// Raster ops +// +#define OP_SET 0 // No operator +#define OP_AND 1 // And +#define OP_OR 2 // Or +#define OP_XOR 3 // Xor +#define OP_TRANS 4 // Transparent +#define OP_ADD 5 // Additive +#define OP_MOVE 0 // Alias for OP_SET + +// +// Temporary definitions +// +#define MXBYTE unsigned char +#define MXBOOL short int +#define MXSINT short int +#define MXUINT unsigned short int +#define MXAPI far pascal +#define MXPTR void far * + +// Functions + +#ifdef __cplusplus // Avoid C++ name mangling +extern "C" { +#endif + +// +// Initialization +// +MXSINT MXAPI mxInit( void ); // Returns 0 if successful +void MXAPI mxTerm( void ); +MXUINT MXAPI mxGetVersion( void ); +// +// Mode setting +// +void MXAPI mxChangeMode( MXUINT mode ); +void MXAPI mxSetMode( MXUINT mode ); +void MXAPI mxGetAspect( MXUINT far *aspectx, MXUINT far *aspecty ); +void MXAPI mxGetScreenSize( MXUINT far *width, MXUINT far *height ); +// +// Hardware support +// +void MXAPI mxWriteMode( MXBYTE wm ); +void MXAPI mxSplitScreen( MXUINT line ); +void MXAPI mxStartAddress( MXUINT sa ); +void MXAPI mxStartLine( MXUINT sl ); +void MXAPI mxWaitDisplay( void ); +void MXAPI mxWaitRetrace( void ); +void MXAPI mxWritePlane( MXBYTE wp ); +void MXAPI mxReadPlane( MXBYTE rp ); +void MXAPI mxRowAddress( MXBYTE ra ); +// +// Virtual screen +// +void MXAPI mxGetVirtualScreen( MXUINT far *width, MXUINT far *height ); +void MXAPI mxSetVirtualScreen( MXUINT width, MXUINT height ); +void MXAPI mxPan( MXUINT x, MXUINT y ); +// +// Clipping +// +MXBOOL MXAPI mxGetClip( void ); +MXBOOL MXAPI mxGetClipRegion( MXSINT far *x, MXSINT far *y, MXSINT far *w, MXSINT far *h ); +MXBOOL MXAPI mxSetClip( MXBOOL ); +void MXAPI mxSetClipRegion( MXUINT x, MXUINT y, MXUINT width, MXUINT height ); +// +// Graphics +// +void MXAPI mxBitBlt( MXSINT sx, MXSINT sy, MXUINT width, MXUINT height, MXSINT dx, MXSINT dy ); +void MXAPI mxFillBox( MXSINT x, MXSINT y, MXUINT width, MXUINT height, MXUINT color, MXUINT op ); +MXBYTE MXAPI mxGetPixel( MXSINT x, MXSINT y ); +void MXAPI mxPutPixel( MXSINT x, MXSINT y, MXBYTE color ); +void MXAPI mxLine( MXSINT x1, MXSINT y1, MXSINT x2, MXSINT y2, MXUINT color, MXUINT op ); +void MXAPI mxGetImage( MXPTR img, MXSINT x, MXSINT y, MXUINT width, MXUINT height ); +void MXAPI mxPutImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT op ); +void MXAPI mxPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT width, MXUINT height ); +void MXAPI mxTransPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT w, MXUINT h ); +void MXAPI mxCircle( MXSINT x, MXSINT y, MXUINT radius, MXBYTE color ); +void MXAPI mxStretchImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT neww, MXUINT newh, MXUINT op ); +// +// Palette +// +void MXAPI mxColorToGray( MXPTR source, MXPTR dest, MXUINT count ); +void MXAPI mxGammaCorrect( MXPTR source, MXPTR dest, MXUINT count ); +void MXAPI mxGetColor( MXUINT index, MXSINT far *r, MXSINT far *g, MXSINT far *b ); +void MXAPI mxSetColor( MXUINT index, MXSINT red, MXSINT green, MXSINT blue ); +void MXAPI mxGetPalette( MXPTR palette, MXUINT index, MXUINT count ); +void MXAPI mxSetPalette( MXPTR palette, MXUINT index, MXUINT count ); +void MXAPI mxFadePalette( MXPTR, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT ); +void MXAPI mxRotatePalette( MXPTR palette, MXUINT count, MXSINT step ); +// +// Text +// +MXSINT MXAPI mxSetFont( MXPTR font, MXUINT charwidth, MXUINT charheight ); +void MXAPI mxSetTextColor( MXUINT color, MXUINT op ); +void MXAPI mxGetTextStep( MXSINT far *deltax, MXSINT far *deltay ); +void MXAPI mxSetTextStep( MXSINT deltax, MXSINT deltay ); +void MXAPI mxOutChar( MXSINT x, MXSINT y, char c ); +void MXAPI mxOutText( MXSINT x, MXSINT y, char far *sz ); +// +// Convex polygons +// +void MXAPI mxFillPoly( MXUINT, MXPTR, MXPTR, MXUINT, MXUINT ); +void MXAPI mxGouraudPoly( MXUINT, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT ); +void MXAPI mxTexturePoly( MXUINT, MXPTR, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT ); + +#ifdef __cplusplus +} +#endif + +// +// Remove temporary defines +// +#undef MXBYTE +#undef MXBOOL +#undef MXSINT +#undef MXUINT +#undef MXPTR +#undef MXAPI + +#endif // _MODEX_H_ diff --git a/16/xw_/modex.lbr b/16/xw_/modex.lbr new file mode 100755 index 00000000..93fc7801 --- /dev/null +++ b/16/xw_/modex.lbr @@ -0,0 +1,39 @@ ++-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 & ++-MXPT.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 diff --git a/16/xw_/modex.pas b/16/xw_/modex.pas new file mode 100755 index 00000000..7d9d26ed --- /dev/null +++ b/16/xw_/modex.pas @@ -0,0 +1,194 @@ +(* + Turbo Pascal interface to the MODEX library + Copyright (c) 1993,1994 by Alessandro Scotti +*) +unit ModeX; +interface + +const + (* Video modes *) + MX_TEXT = 0; + MX_320x175 = 1; + MX_320x200 = 2; + MX_320x240 = 3; + MX_320x350 = 4; + MX_320x400 = 5; + MX_320x480 = 6; + MX_360x175 = 7; + MX_360x200 = 8; + MX_360x240 = 9; + MX_360x350 = 10; + MX_360x400 = 11; + MX_360x480 = 12; + MX_400x600 = 13; + + (* Fade effects *) + MX_FADEIN = 0; + MX_FADEOUT = 1; + + (* Raster ops *) + OP_SET = 0; + OP_AND = 1; + OP_OR = 2; + OP_XOR = 3; + OP_TRANS = 4; + OP_ADD = 5; + OP_MOVE = 0; (* Alias for OP_SET *) + +procedure mxBitBlt( SX, SY: integer; Width, Height: word; DX, DY: integer ); +procedure mxCircle( CX, CY: integer; Radius: word; Color: byte ); +procedure mxChangeMode( Mode: word ); +procedure mxColorToGray( ColorPalette, GrayPalette: pointer; Count: word ); +procedure mxFadePalette( Palette: pointer; Cmd, Start, Count, R, G, B: word ); +procedure mxFillBox( X, Y: integer; Width, Height: word; Color: byte; Op: word ); +procedure mxGammaCorrect( ColorPalette, GammaPalette: pointer; Count: word ); +procedure mxGetAspect( var AspectX, AspectY: word ); +function mxGetClipRegion( var X1, Y1, Width, Height: word ): boolean; +function mxGetClip: boolean; +procedure mxGetImage( Image: pointer; X, Y: integer; Width, Height: word ); +procedure mxGetPalette( Palette: pointer; Start, Count: word ); +function mxGetPixel( X, Y: word ): byte; +procedure mxGetScreenSize( var Width, Height: word ); +procedure mxGetTextStep( var DeltaX, DeltaY: integer ); +function mxGetVersion: word; +procedure mxGetVirtualScreen( var Width, Height: word ); +procedure mxInit; +procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word ); +procedure mxOutChar( X, Y: integer; C: char ); +procedure mxOutText( X, Y: integer; S: pointer ); +procedure mxPan( X, Y: word ); +procedure mxPutImage( Image: pointer; X, Y: integer; Width, Height, Op: word ); +procedure mxPutPixel( X, Y: word; C: byte ); +procedure mxPutTile( Tile: pointer; X, Y: integer; Width, Height: word ); +procedure mxReadPlane( Plane: byte ); +procedure mxRotatePalette( Palette: pointer; Count: word; Step: integer ); +procedure mxRowAddress( RowAddress: byte ); +function mxSetClip( Clip: boolean ): boolean; +procedure mxSetClipRegion( X1, Y1, Width, Height: word ); +procedure mxSetColor( Index, R, G, B: word ); +procedure mxSetFont( Font: pointer; Width, Height: word ); +procedure mxSetMode( Mode: word ); +procedure mxSetPalette( Palette: pointer; Start, Count: word ); +procedure mxSetTextColor( Color, Op: word ); +procedure mxSetTextStep( DeltaX, DeltaY: integer ); +procedure mxSetVirtualScreen( Width, Height: word ); +procedure mxStretchImage( Image: pointer; X, Y: integer; Width, Height, NewWidth, NewHeight, Op: word ); +procedure mxSplitScreen( Line: word ); +procedure mxStartAddress( StartAddress: word ); +procedure mxStartLine( Line: word ); +procedure mxTerm; +procedure mxTransPutTile( Tile: pointer; X, Y: integer; Width, Height: word ); +procedure mxWaitDisplay; +procedure mxWaitRetrace; +procedure mxWriteMode( Mode: byte ); +procedure mxWritePlane( Plane: byte ); + +procedure mxFillPoly( Count: word; var Map, Points; Color: word ); +procedure mxGouraudPoly( Count: word; var Map, Points, Colors; BaseColor: word ); +procedure mxTexturePoly( Count: word; var Map, Points, ImgPoints, Texture; Width: word ); + +procedure mxOutStr( X, Y: integer; S: string ); + +implementation + +procedure mxBitBlt; external; +procedure mxChangeMode( Mode: word ); external; +procedure mxCircle; external; +procedure mxColorToGray; external; +procedure mxFadePalette; external; +procedure mxFillBox; external; +procedure mxGammaCorrect; external; +procedure mxGetAspect( var AspectX, AspectY: word ); external; +function mxGetClipRegion; external; +function mxGetClip: boolean; external; +procedure mxGetImage; external; +procedure mxGetPalette( Palette: pointer; Start, Count: word ); external; +function mxGetPixel( X, Y: word ): byte; external; +procedure mxGetScreenSize( var Width, Height: word ); external; +procedure mxGetTextStep( var DeltaX, DeltaY: integer ); external; +function mxGetVersion: word; external; +procedure mxGetVirtualScreen( var Width, Height: word ); external; +procedure mxInit; external; +procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word ); external; +procedure mxOutChar( X, Y: integer; C: char ); external; +procedure mxOutText( X, Y: integer; S: pointer ); external; +procedure mxPan( X, Y: word ); external; +procedure mxPutImage; external; +procedure mxPutPixel( X, Y: word; C: byte ); external; +procedure mxPutTile; external; +procedure mxReadPlane( Plane: byte ); external; +procedure mxRotatePalette; external; +procedure mxRowAddress( RowAddress: byte ); external; +function mxSetClip( Clip: boolean ): boolean; external; +procedure mxSetClipRegion( X1, Y1, Width, Height: word ); external; +procedure mxSetColor( Index, R, G, B: word ); external; +procedure mxSetFont( Font: pointer; Width, Height: word ); external; +procedure mxSetMode( Mode: word ); external; +procedure mxSetPalette( Palette: pointer; Start, Count: word ); external; +procedure mxSetTextColor( Color, Op: word ); external; +procedure mxSetTextStep( DeltaX, DeltaY: integer ); external; +procedure mxSetVirtualScreen( Width, Height: word ); external; +procedure mxSplitScreen( Line: word ); external; +procedure mxStartAddress( StartAddress: word ); external; +procedure mxStartLine; external; +procedure mxStretchImage; external; +procedure mxTerm; external; +procedure mxTransPutTile; external; +procedure mxWaitDisplay; external; +procedure mxWaitRetrace; external; +procedure mxWriteMode( Mode: byte ); external; +procedure mxWritePlane( Plane: byte ); external; + +procedure mxFillPoly; external; +procedure mxGouraudPoly; external; +procedure mxTexturePoly; external; +{$L MXPB} +{$L MXPF} +{$L MXPG} +{$L MXPT} + +{$L MXBB} +{$L MXCC} +{$L MXCG} +{$L MXCL} +{$L MXCR} +{$L MXFB} +{$L MXFP} +{$L MXGI} +{$L MXGM} +{$L MXGP} +{$L MXGV} +{$L MXHL} +{$L MXIT} +{$L MXLN} +{$L MXOT} +{$L MXPI} +{$L MXPN} +{$L MXPP} +{$L MXRA} +{$L MXRP} +{$L MXSA} +{$L MXSC} +{$L MXSI} +{$L MXSL} +{$L MXSM} +{$L MXSP} +{$L MXSS} +{$L MXTL} +{$L MXVS} +{$L MXWD} +{$L MXWM} +{$L MXWP} +{$L MXWR} + +(* + Prints a Turbo Pascal string. + Note: BP 7.0 supports ASCIIZ strings (PChar type). +*) +procedure mxOutStr; +begin + S := S + #0; + mxOutText( X, Y, @S[1] ); +end; + +end. diff --git a/16/xw_/modex/DEMO01.EXE b/16/xw_/modex/DEMO01.EXE new file mode 100755 index 0000000000000000000000000000000000000000..28caff88c58a0b8ce5a4d23c6544c00cda8482fc GIT binary patch literal 10208 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 320 ) then begin + S.X := 320; + S.DX := -S.DX; + end; + if( S.X < -16 ) then begin + S.X := -16; + S.DX := -S.DX; + end; + if( S.Y > 240 ) then begin + S.Y := 240; + S.DY := -S.DY; + end; + if( S.Y < -16 ) then begin + S.Y := -16; + S.DY := -S.DY; + end; + (* Draw the sprite, note the Page offset added to the *) + (* Y coordinate of the image *) + mxPutImage( @S.Image, S.X, Page+S.Y, S.W, S.H, OP_TRANS ); +end; + +begin + (* Initialize library *) + mxInit; + + (* Enter graphics mode *) + mxSetMode( MX_320x240 ); + + (* Print initialization message *) + mxSetTextColor( 15, OP_TRANS ); + mxOutStr( 4, 4, 'Initializing...' ); + + (* Initialize sprites *) + for I:=1 to MAX_SPRITE do sxInit( S[I] ); + + (* Draw background *) + for I:=1 to 192 do begin + mxCircle( 160, 480+120, I, I+63 ); + mxCircle( 161, 480+120, I, I+63 ); + end; + + (* Compute and set palette *) + for I:=1 to 192 do with Palette[I+63] do begin + R := 0; + G := 0; + B := 0; + if( I < 64 ) then + R := I shr 1+31 + else if( I < 128 ) then + G := (I-64) shr 1+31 + else + B := (I-128) shr 1+31; + end; + mxSetPalette( @Palette[64], 64, 192 ); + + (* Main loop *) + Page := 240; + while( not KeyPressed ) do begin + (* Set clip region to current page *) + mxSetClipRegion( 0, Page, 320, 240 ); + mxSetClip( TRUE ); + (* Restore background *) + mxBitBlt( 0, 480, 320, 240, 0, Page ); + (* Draw sprites *) + for I:=1 to MAX_SPRITE do sxMove( S[I] ); + (* Print message *) + mxOutStr( 4, Page+4, 'Some sprites moving...' ); + (* Flip page *) + mxStartLine( Page ); + Page := 240-Page; + (* Animate palette *) + mxSetPalette( @Palette[64], 64, 192 ); + mxRotatePalette( @Palette[64], 192, 3 ); + end; + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw_/modex/DEMO02.EXE b/16/xw_/modex/DEMO02.EXE new file mode 100755 index 0000000000000000000000000000000000000000..14e7dc72b16e421ae94767feaa07cb3988f49db1 GIT binary patch literal 24688 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 L6~S)>H$VReFZ-F@ literal 0 HcmV?d00001 diff --git a/16/xw_/modex/DEMO02.PAS b/16/xw_/modex/DEMO02.PAS new file mode 100755 index 00000000..6b4fb6f9 --- /dev/null +++ b/16/xw_/modex/DEMO02.PAS @@ -0,0 +1,125 @@ +(* + DEMO02 - Texture mapping and palette rotation + (c) 1994 by Alessandro Scotti +*) +uses Crt, Modex, Plasma, Threed; + +const + LSIZE = 85; + Trans : TPoint = ( X:0; Y:0; Z:0 ); +type + T2DPoint = record + X, Y: integer; + end; + TTexture = record + Desc : array[ 0..3 ] of T2DPoint; + Width : word; + Data : array[ 1..64*64 ] of byte; + end; + TQuad = record + VtxCnt : word; + Vtx : array[ 0..3 ] of word; + Texture: word; + end; +var + Vtx : array[ 0..7 ] of TPoint; + XVtx : array[ 0..7 ] of TPoint; + VVtx : array[ 0..7 ] of T2DPoint; + Face : array[ 0..5 ] of TQuad; + Txts : array[ 0..5 ] of TTexture; + Nrm : array[ 0..5 ] of TPoint; + XNrm : array[ 0..5 ] of TPoint; + Page : word; + Palette: array[ byte ] of record R, G, B: byte; end; + +(* Make a 64x64 plasma to be used as texture *) +procedure MakeTexture( Idx: word ); +var + I: word; +begin + mxFillBox( 0, 0, 64, 64, 0, OP_SET ); + MakePlasma( 0, 0, 64, 64, 96, Random(192)+1, Random(192)+1, Random(192)+1 ); + mxGetImage( @Txts[Idx].Data, 0, 0, 64, 64 ); + (* Texture vertexes are 8:8 fixed, add $80 (0.5) for best results *) + with Txts[Idx] do begin + Desc[0].X := $80; Desc[0].Y := $80; + Desc[1].X := $80; Desc[1].Y := $3F80; + Desc[2].X := $3F80; Desc[2].Y := $3F80; + Desc[3].X := $3F80; Desc[3].Y := $80; + Width := 64; + end; +end; + +procedure Init; +var + I: integer; +begin + (* Build vertexes for a cube *) + with Vtx[0] do begin X:=-LSIZE; Y:=-LSIZE; Z:=-LSIZE; end; + with Vtx[1] do begin X:=+LSIZE; Y:=-LSIZE; Z:=-LSIZE; end; + with Vtx[2] do begin X:=-LSIZE; Y:=+LSIZE; Z:=-LSIZE; end; + with Vtx[3] do begin X:=+LSIZE; Y:=+LSIZE; Z:=-LSIZE; end; + with Vtx[4] do begin X:=-LSIZE; Y:=-LSIZE; Z:=+LSIZE; end; + with Vtx[5] do begin X:=+LSIZE; Y:=-LSIZE; Z:=+LSIZE; end; + with Vtx[6] do begin X:=-LSIZE; Y:=+LSIZE; Z:=+LSIZE; end; + with Vtx[7] do begin X:=+LSIZE; Y:=+LSIZE; Z:=+LSIZE; end; + for I:=0 to 7 do begin (* Make points 16:16 fixed *) + Vtx[I].X := Vtx[I].X*$10000; + Vtx[I].Y := Vtx[I].Y*$10000; + Vtx[I].Z := Vtx[I].Z*$10000; + end; + (* Build faces *) + with Face[0] do begin Vtx[0]:=0; Vtx[1]:=2; Vtx[2]:=3; Vtx[3]:=1; end; + with Face[1] do begin Vtx[0]:=4; Vtx[1]:=5; Vtx[2]:=7; Vtx[3]:=6; end; + with Face[2] do begin Vtx[0]:=0; Vtx[1]:=1; Vtx[2]:=5; Vtx[3]:=4; end; + with Face[3] do begin Vtx[0]:=1; Vtx[1]:=3; Vtx[2]:=7; Vtx[3]:=5; end; + with Face[4] do begin Vtx[0]:=2; Vtx[1]:=0; Vtx[2]:=4; Vtx[3]:=6; end; + with Face[5] do begin Vtx[0]:=7; Vtx[1]:=3; Vtx[2]:=2; Vtx[3]:=6; end; + for I:=0 to 5 do Face[I].Texture := I; + (* Build textures and palette *) + Randomize; + FillChar( Palette, SizeOf(Palette), 0 ); + MakePlasmaPalette( Palette, PAL_RGB ); + mxSetPalette( @Palette, 0, 193 ); + for I:=0 to 5 do MakeTexture( I ); +end; + +var + AX, AY, AZ: byte; + I: word; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; (* Start with hidden page *) + + AX := 0; + AY := 0; + AZ := 0; + (* Init 3D transforms, perspective is intentionally exaggerated *) + tdSetTranslation( Trans ); + tdSetPerspective( 400*$10000, $10000, $10000 ); + (* Main loop, all magic here! *) + while( not KeyPressed ) do begin + tdSetRotation( AX, AY, AZ ); (* Set new angles *) + tdTransform( Vtx, XVtx, 8 ); (* 3D transform points *) + tdTransformToImage( XVtx, VVtx, 8, 160, 120+Page ); + Inc( AX, 1 ); (* Bump angles *) + Inc( AY, 1 ); + Inc( AZ, 2 ); + mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *) + mxSetClip( TRUE ); + mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *) + mxRotatePalette( @Palette[1], 192, 3 ); (* Rotate palette *) + (* Draw cube: backface culling is straighforward in this case, so *) + (* it can be handled by the polygon filling procedure *) + for I:=0 to 5 do + mxTexturePoly( 4, Face[I].Vtx, VVtx, Txts[I].Desc, Txts[I].Data, Txts[I].Width ); + mxStartLine( Page ); (* Flip pages *) + mxSetPalette( @Palette[1], 1, 192 ); (* Set new palette *) + Page := 240-Page; + end; + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw_/modex/DEMO03.EXE b/16/xw_/modex/DEMO03.EXE new file mode 100755 index 0000000000000000000000000000000000000000..c646c4b0283db932174d915432747c2176034195 GIT binary patch literal 14256 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 RADIUS*RADIUS ) then goto Retry; + Z := Toggle( Round( Sqrt( Abs( RADIUS*RADIUS-X*X-Y*Y ) ) ) ); + case Random(3) of + 0: Swap( X, Z ); + 1: Swap( Y, Z ); + end; + X := X * $10000; Y := Y * $10000; Z := Z * $10000; + end; + end; + (* Initialize morphing *) + Move( CubeVtx^, Vtx^, SizeOf(Vtx^) ); + Status := 0; + Count := WAITCOUNT; +end; + +procedure Morph; +var + I: integer; +begin + (* Fully unoptimized, slowest loop I could think of! *) + for I:=0 to MAXVTX-1 do begin + Vtx^[I].X := ((CubeVtx^[I].X * Morph1)+(SphereVtx^[I].X * Morph2)) div MS; + Vtx^[I].Y := ((CubeVtx^[I].Y * Morph1)+(SphereVtx^[I].Y * Morph2)) div MS; + Vtx^[I].Z := ((CubeVtx^[I].Z * Morph1)+(SphereVtx^[I].Z * Morph2)) div MS; + end; +end; + +var + AX, AY, AZ: byte; + I: word; + C: char; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; (* Start with hidden page *) + + AX := 0; + AY := 0; + AZ := 0; + (* Init 3D transforms, perspective is intentionally exaggerated *) + tdSetTranslation( Trans ); + tdSetPerspective( 400*$10000, $10000, $10000 ); + C := #0; + repeat + tdSetRotation( AX, AY, AZ ); (* Set new angles *) + tdTransform( Vtx^, XVtx^, MAXVTX ); (* 3D transform points *) + tdTransformToImage( XVtx^, VVtx, MAXVTX, 160, 120+Page ); + Inc( AX, 1 ); (* Bump angles *) + Inc( AY, 1 ); + Inc( AZ, 2 ); + mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *) + mxSetClip( TRUE ); + mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *) + (* Draw points *) + for I:=0 to MAXVTX-1 do + mxPutPixel( VVtx[I].X, VVtx[I].Y, 128 + XVtx^[I].Z shr 18 ); + mxStartLine( Page ); (* Flip pages *) + Page := 240-Page; + (* Morph *) + if( Odd(Status) ) then begin + Morph; + Inc( Morph1, Delta1 ); + Inc( Morph2, Delta2 ); + if( Morph1 < 0 )or( Morph2 < 0 ) then Inc( Status ); + if( Status = 4 ) then Status := 0; + end + else begin + Dec( Count ); + if( Count < 0 ) then begin + Inc( Status ); + Count := WAITCOUNT; + Morph1 := InitMorph1[Status]; + Morph2 := InitMorph2[Status]; + Delta1 := InitDelta1[Status]; + Delta2 := InitDelta2[Status]; + end; + end; + until( KeyPressed ); + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw_/modex/DEMO04.DAT b/16/xw_/modex/DEMO04.DAT new file mode 100755 index 0000000000000000000000000000000000000000..72aaad08ac55e4d161e7868374296a4e42554684 GIT binary patch literal 37662 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%0D)*4A2IO9KMZYD#oU43C^WOCfTg8_%RD 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�-ncKj8QX2BIutynAlnfJ{;J0ue86t5F zBjm=|;P0?%@yd7OQ+dFR2PjBAijBxEkSVe|?8Mg`9bSn;0N$gC2!TOY+!Y(CGYIfJ zLl{!MwjfSv@Yn<)6iedBDwo&xm>BZTP_LoO?r4B)pf z@(#EL^wxV26ZBM>A@H@;CKMzBuwQPx9H>JQB5){kn4Lsf3IoM~CNpr(HcqO3&~HpVtQmsBT~d zxVH$Y0;Sm?4|fWkKuWhmh-O4%TaO0lZamnfmB#0>Zx_-Bh%5AyG6O zdf27Mg&5kc(Keic#||#$*c3`(95EhB6xi+ zr;jHFqB^jRfCJqT{=kaD?F7ua9-zYGYb=%+fCNwYB%Z=6k$H6SGb`B^QclPoWFe#| z4n|El2cfEn_)$9{4kY1M%NhUAFi9k&iiacuWK=t|@PIPX`9!E78uX5biQ#`edWO>8*UCA!0r$bsPHHI2=A3k0ZA&IgFiy&iHmJ00dxtgE9;15 z6Ts7BD|ybV-|ex)L}O+-h=?l}lu>LZb1he}&-emQw9TnUE4!jOhiETJJ$#^xvj>eS zGUm@_5QFutmmLVhOyopm|EWI}kR`!tZn2;05|@ zauX7Jc1TzuTx_fgA%#K%^w2J-#M_}0^S}a_Jtao~&Ds?yS&NfnP;4Ut0D&9=u*88W zfUk%zEbsuk1A5A}mk>b6fM5hjXaxrdy{h0KW|_DKXDwntI+?OzUMF!YmJ=?UEF@`A z7$Jufq|F)Obs|U>Zsu_K6n7}>kQ|cP;!p_oaL8fue7+!S@$_M|pLd}cPM-Hk?qA3W zF_$gp_)J<7T$oKjAxDPO^5IE6UOgR-@qh9F3hKyUqU-W#Kv0z2=0KPb1rri;A2tGg zC@S(5Rv`xCg|1=|`7FahG~`l|MCJ%3F9{;!}B z1tHeC7dz_?m=l0F_jX!&T(hjN`M-|~fwm=DZ&H>Cu;X&f4xdIEt7K-iU5jY>}4sN%{1_m(x$M^$NL*gd{ z&*jPSZo3CnMR6d2gTejq0WJc2U@nZ=f$4x7aaY_hH9!JeoVg=9+GcZM$RNNFm1)iZ z{9}SuIa2h|?Igr<%Wd#xn5Sci4-i`>;K;B=rXYYfl*Xe}vMsm|6pElx7F1*bscI&Zuvki%@6AO{J=nJa^)43&@tVBa{vaJ(1pLxK(UQ5>pRM4W+jLJ@L_oU9vB zb=mRwcoR{;{d9iu{un`OG&3<^CHmx2M36*uq_i#zu~-(dm_keDoXPA(Q`Bx({iUCGwCV5wO6Q+hY{P z>eePRD*7uyR1Pb423r&k*?k-VS^|X`9KB2==mkv6#6PikhjMIT<1TMAGTF4i$(=rCIrJ!Ct5o=z#$aJSwpjZrLgM##fl2Mpaq(N(RAX`Zf%u^}smO-}pf*UE zf$yQ9i*zuO%&o)PCWoY=7zNcJUY%!Xqol^Z$s)iYRceuctuN4kJ5W&?j~MUra}s~M zl)%*F3d{0WlA(+b0w6C40}1Mh!4Q8G3CzR+6Xyh2Nl%N+#?A+MP`bc{*B3w)5mHzH zYzddEAb~~I5yr>+RL;S0z2(pn}>jieIrj{juu|xaS6Am%R9(Tvg71*#QK1(j9y47vJra< zD7qCSfvLciKAQHt01dm-qlk?tU2zK}3w9FCn=B^LwtTDX1Ce^gzR2z{DJTsVoQK`Q z0YwK1ekO zroN7j1+dzu&KedMghTjrrYgpp#0jUtkzfqjA^ooW zwgaR-;>y0YF|vb6AulOdp0+Im1jeU4=QEK%(Fd|98mTrJOvDmwMD?MBFqQyneRiAj zSPHd+N^=4+F+R>xVKl-B z+5#E~lOfzjk_}2!e4+*rXS9AB1xKx1g^Ddu!&&Qm5D>VMgqVm0B;3WPNEC!uSHF_U zQz#wou~?l>Pzs%1?3cU^*%o+U&H(}uRKA4_qsC|eC&6(MmHXX9P0G({vI2RP_s7>5 z@TyQxmIs@lQ&0}n?onF_fRxutuOR>-K#>5-WD;bGW!wq#DCG!B>Q_{7a#~mv@L85i z7ecO#0=+sm8^M%p9NUJSET(2MK_-#Ip)27IRXj!dXHFCNw( zqjG^PouI739^*>X1R~!dmxrh+4@%OXlp_uU6*r(BmZOCvQfU5B4OK85so=NP;J9$} zk}1GF>zjxip~Mpb4wX{DKp&N+>7SU*jv|)`* zq6l-K4h;`72oy9ux26(`dPT#k0677KNDIn*$wNSZz^W_;Kng9FqALSH8Nt9!q(*%{ zFc_Z-e37}qjdC8UErD41EgM)`>(iJUIRorDV>9Ho%1b3uZ9dN|}J)aSSD1l7aD>2njvg8+)G zR6*b+U{p5-RK@$F5iBlr7y;*0kbASf@*W(B{GbF5C6hbG9FSf_?Pci<;Fj!RblIw~ zC#K(+IFgJ69%}s+))sq!`}~3xg5rAwaJJ|zd4Xt?qr>PzfFv6b$u>}RcmXp=NAn#V zkUJ+TqMiff6ySzHnJ^e>2tWdXw=hBRkB5{H*>Law!KW`h@cISuLo76X*ng5L(qo$f^tafb_8e zLL~@2kkkQoB*}%%Czt@$%0IhxZ&84mhXcqc_tg;_cmx;&P2kGCv=Lg>x~@VSt0JM| zn1~kFkOC8bm?%x97q>Dk7;*@ZbgBo8pnwJ$+KD(bRW8&z<)-OO%VUYqG`SJBr<0Ho zLmZX$hXYiT&}?foNIpXNO%-ac%6=DD{W>YHpTjsEbX*Kn|MpRWf?C1Q{(@*7J+wTJj{{d_TT_D zj1Z1Q_kaM_$5E&ep3D#?7Xr8g%4Twy&S-Xq5D4$^$Ai^J&+r$LY&G?&S4kx%4hs2E z0*%$h*~s|6ys{vTF+}_qhJ#dr%NjI28`=aMkS^mW5n{|uBwkhQm!a&hgWIDU%7VfG zle>qlgiSg(i7tsj=_=Nk^V8Y0F|1BSMZl-=e}qbCQubCB&qN7o?g4S?htg1tkTi*Q z<;cq+*YG!6C_w?Q`k#d|VE}rH&5^?b#-U*pnn|D{{XjH~wZvLSBl-At{2w7eF@&~ahFO3d8JUm$7%) zAejWd7v_^WAmBB!uKEyB>cE~aWD3;l>#SvsxOn?ldYz^Lk z4I|>}&UCB1CLxIU0d~hgkj*McCrBn!CRt{ifC7ScWWxx7b}BTl!!#N#6XjA=uTp~q zoy8&}BwNVx@SP5`k|Y3fV=~;hb19eGs`mgq5Ota$xjS;`w94EP6az}(iwuY|xDFDi zazT8O2C%6tiHS19yh}ANCm}8V-e`^>sJcY9?DLWgm#;_r@IevX67eQw<5h)IZz6c) zQau({$3TGS(#}~5^&z?9w>VXb!|3SWDiLPFSre2KppxyRAySfq@EiRz0;unlYLNB| zbV)#=kMFTOz+IBX=9fE?YXiRM2vaAHM?wGta(-FGPlrti;e% z!6TD3{OTO=30A;hFCzsq$e{!Yi&;}sH3);02gL$@+O4ugN|C^9g)V|LKD&$T3LyyM zq>!IOVLHu0z#*t?HVzqboiG_jDmKvBK{z=X1Q=Beq3DE&Rz-lJqly&selT6JlAfnixupqK5I|GA_3sK|-Zc?XaBpOjH ziMKK1{~`cWqH#zrs8V8_?W%>*62oub!=sSMR?MlYo|7IJeib362r)x46s^WsX(Yf0 zDd^5LXcT2enni%*O5@aUfOZzE0b>FVl2-+(jQ@iz(J~H9#|6rk2@%+r1X!$oc@%&T z)vgeWUe?&jRAYw?p zL~>Q&(r;b^Wf_}qPJlp#JODNr4u}WF3o52D zW`xcrE za$7L>yW{^fngbjdks*F@dg+FwD-KgE8ALk}OqMZGjdEN7SBZ-lu5+ zSc((OvxSLt3M7VG0x5#g{PCG&9j69rtL4bGPj&KR%9-f+vj zM73u1uS6gOh*8^RIjoTgz)MRug?5Pk8F41Wtz`Tk?rQu$hD@#_1`Kd-{2z})YCxPe z?Tg&q1|$Xyax5lZS7E)9d8Q11WE}E&{{NyoRDk;Mw}lZ(~KvJ069vcDLM*hK_N5u zxAA|2hM`!Ni}VtWW-%^&DdCS?aYV`)YCypGYchE9;u>I(bVWQYuaYB!`>+7fVZAKi z;=NdsBS0uj_UPXDKRL|*Vf>%tBhf48L_x_;>JBk9!T}3}B^B!%NQ0SID%N8YKo^BZ zMu3@GU%p5}2-=d*1)JO(|Cfmgd85H73akHl{9kxkpbF$g08V}pNQ8OjRx+y`KEssA z8eUgw&sxf2xdi4VKd6auh!B7;Mx;5ptcU~s=kb4j_xIn&{{x(}4ge#<9u+iEch@=j zyjF7c0RS<2p#OvWM!z!Iu}~lugI`wdj`5(1g2i;yn;s?EUX|{kF;YMWl>GDfzmqvH zga`{@ay^Cs3TFFQ2VTnaEB8PHl%9?NJJElnOrKOILM(9YoQ00TZ^r)>oWUhSA<1v$ zS~x0U9=zVY@qfW+BaqH-$NxF&fDvYSd_+rZln0?y0qc-e;xd^!6#=qDhK?5$r;sNL zqIfj~m@aYUUPS;d(}XX;Yn3OB@4{$MKnCte*Nu1n*YSU7Q_w0Y6Cvyq3TSAjy_+nz z1Pb*s`YmrLx#VKYO0-AD{}t*h@hUa;lR7{w&{pmuWJYH^t?9ydsY}OAN?*Kq!qoKi z8F5cMv260xxXBZyEn7TeTx@LYm;Sz9)6?Q6rO%i$b;gpkaTBL6n-Uv4E^gwK zrKw9|<6C-2rr>3W+rA>^TwsdCPxPKeJbkgLhGvZ=nr=)Y;cLJuT zPM^GV>D1T><0p(uo%mqfxXIJfr;ndF3I31c{|QK) zk)A$zLh91E@zc{%wQ}5)8Pk?7TQ)N_ec8m=*tq+C1WVGMShg&E>GYYCXU<4XUy_Nf+XH|0;ViUTbB03^chR1O`J3{eetC9rEwD{Pne#bHZv`K0;+i5 z35c6EGktn$?1Uu~VyC91O`i0`;_)0Rz}K7H}{xb*Q8@Ci?( zj*p!(WATLPlPBDF4lGU`KW@_a*tm(Ylg5o3hY-ZY%|HpqO-)}qIW~5}{U>1Bgt&1N zB=r-QOq)1<+_Kbh<0q#tLlV-b#&QDp-x5xai=F)7%o&TPPg^E)wB(7IOViV4Oo*Mf zICdf&x&H*<{L<6YQqv#A2*8OcGne5JXFNDz0(JpW9CzPkU~1|Usf(ASFPl1k>dc9; zadFF@NKaclbt0#aK5*T40ze_@QCihlNT>uJaNi|iIZk5T{1Ox z67kxSwEM4yi>EF@_6SKQFPhoB2fQ6U)+<-FFTUfGmau_?-#kW2a4@ XG;Ye`)EVP3#M6mPm!(a=?*#mR$DZhs literal 0 HcmV?d00001 diff --git a/16/xw_/modex/DEMO04.EXE b/16/xw_/modex/DEMO04.EXE new file mode 100755 index 0000000000000000000000000000000000000000..1fec5e8aa383353d986ca1e4420838b09e61eef4 GIT binary patch literal 24384 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 Im202>1y)VB#{d8T literal 0 HcmV?d00001 diff --git a/16/xw_/modex/DEMO04.PAS b/16/xw_/modex/DEMO04.PAS new file mode 100755 index 00000000..1a946315 --- /dev/null +++ b/16/xw_/modex/DEMO04.PAS @@ -0,0 +1,198 @@ +(* + DEMO04 - Multiple textures and triple buffering (3 pages) + (c) 1994 by Alessandro Scotti +*) +uses Crt, Modex, Threed; + +const + MAXVTX = 256; + MAXCUB = 2; + MAXTXT = 2; + Trans : TPoint = ( X:0; Y:0; Z:0 ); + TxtSunDial: array[ 0..7 ] of word = ( + $7F80,$0080, $0080,$0080, $0080,$7E80, $7F80,$7E80 ); + TxtSapphire : array[ 0..7 ] of word = ( + $0080,$0080, $0080,$1F80, $1F80,$1F80, $1F80,$0080 ); + TxtMarble: array[ 0..7 ] of word = ( + $0080,$8080, $0080,$FD80, $7F80,$FD80, $7F80,$8080 ); +type + T2DPoint = record + X, Y: integer; + end; + TTexture = record + Desc : array[ 0..3 ] of record X, Y: word end; + Width : word; + Data : pointer; + end; + TQuad = record + Vtx : array[ 0..3 ] of word; + Texture: word; + end; + TCube = record + Face : array[ 0..5 ] of TQuad; + Base : integer; + end; +var + Vtx, XVtx: array[ 0..MAXVTX ] of TPoint; + VVtx : array[ 0..MAXVTX ] of T2DPoint; + Cube : array[ 0..MAXCUB ] of TCube; + ZList : array[ 0..MAXCUB ] of integer; + VtxCnt : word; + Txts : array[ 0..MAXTXT ] of TTexture; + Page : word; + Palette : array[ byte ] of record R, G, B: byte; end; + TxtDat1, TxtDat2: pointer; + +(* Add a new entry to the vertex array *) +procedure AddVtx( PX, PY, PZ: longint ); +begin + with Vtx[VtxCnt] do begin X:=PX*$10000; Y:=PY*$10000; Z:=PZ*$10000; end; + Inc( VtxCnt ); +end; + +procedure MakeCube( var C: TCube; X1,Y1,Z1, X2,Y2,Z2, TX,TY,TZ, Texture: integer ); +const + FaceIdx: array[ 0..23 ] of integer = ( + 0,1,2,3, 0,4,5,1, 1,5,6,2, 2,6,7,3, 3,7,4,0, 6,5,4,7 ); +var + I, VC: integer; +begin + VC := VtxCnt; + C.Base := VC; + AddVtx( X1+TX, Y1+TY, Z1+TZ ); + AddVtx( X2+TX, Y1+TY, Z1+TZ ); + AddVtx( X2+TX, Y2+TY, Z1+TZ ); + AddVtx( X1+TX, Y2+TY, Z1+TZ ); + AddVtx( X1+TX, Y1+TY, Z2+TZ ); + AddVtx( X2+TX, Y1+TY, Z2+TZ ); + AddVtx( X2+TX, Y2+TY, Z2+TZ ); + AddVtx( X1+TX, Y2+TY, Z2+TZ ); + for I:=0 to 23 do C.Face[I shr 2].Vtx[I and 3] := VC+FaceIdx[I]; + for I:=0 to 5 do C.Face[I].Texture := Texture; +end; + +procedure MakeTexture( Idx: integer; var VtxData ); +var + P: ^word; + I: integer; +begin + P := @VtxData; + with Txts[Idx] do begin + for I:=0 to 3 do begin + Desc[I].X := P^; Inc( P ); + Desc[I].Y := P^; Inc( P ); + end; + Width := 129; + Data := TxtDat1; + end; +end; + +procedure Init; +var + I: integer; + V: integer; + F: file; + P: array[ 1..768 ] of byte; +begin + (* Initialize objects *) + VtxCnt := 0; + MakeCube( Cube[0], -64,-64,8, 64,64,-8, 0,0,0, 1 ); (* Sundial *) + Cube[0].Face[0].Texture := 0; + V := VtxCnt; + MakeCube( Cube[1], -16,-16,16, 16,16,-16, 0,0,0, 2 ); (* Sapphire *) + tdSetTranslation( Trans ); + tdSetRotation( 32, 32, 00 ); + tdRotate( Vtx[V], XVtx[V], 8 ); (* Got to rotate this cube *) + for I:=V to V+7 do begin + Vtx[I].X := XVtx[I].X; + Vtx[I].Y := XVtx[I].Y; + Vtx[I].Z := XVtx[I].Z + 100*$10000; + end; + MakeCube( Cube[2], -64,-4,48, 64,4,-48, 0,68,56, 1 ); (* Marble *) + (* Load texture and palette *) + Assign( F, 'DEMO04.DAT' ); + Reset( F, 1 ); + BlockRead( F, P, SizeOf(P) ); + mxSetPalette( @P, 0, 256 ); + GetMem( TxtDat1, 63*1024 ); + BlockRead( F, TxtDat1^, 129*286 ); + Close( F ); + TxtDat2 := Ptr( Seg(TxtDat1^), Ofs(TxtDat1^)+129*254 ); + (* Init textures *) + MakeTexture( 0, TxtSundial ); + MakeTexture( 1, TxtMarble ); + MakeTexture( 2, TxtSapphire ); + Txts[2].Data := TxtDat2; +end; + +(* Sort procedure, not worth optimizing with only a few objects *) +procedure SortObjects; +var + I, J, K: integer; + ZMax: array[ 0..MAXCUB ] of longint; + ZI: integer; + L: longint; +begin + for I:=0 to MAXCUB do begin + L := XVtx[Cube[I].Base].Z; + for J:=1 to 7 do + if( L > XVtx[Cube[I].Base+J].Z ) then L := XVtx[Cube[I].Base+J].Z; + ZMax[I] := L; + ZList[I] := I; + end; + for I:=0 to MAXCUB-1 do begin + ZI := I; + for J:=I+1 to MAXCUB do + if( ZMax[ZList[J]] > ZMax[ZList[ZI]] ) then ZI := J; + if( ZI <> I ) then begin + K := ZList[I]; + ZList[I] := ZList[ZI]; + ZList[ZI] := K; + end; + end; +end; + +var + AX, AY, AZ: byte; + I, J, K: word; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; (* Start with hidden page *) + + (* Init 3D transforms, perspective is intentionally exaggerated *) + AX := 0; AY := 0; AZ := 0; + tdSetTranslation( Trans ); + tdSetPerspective( 600*$10000, $10000, $10000 ); + (* Main loop, all magic here! *) + while( not KeyPressed ) do begin + tdSetRotation( AX, AY, AZ ); (* Set new angles *) + tdTransform( Vtx, XVtx, VtxCnt ); (* 3D transform points *) + tdTransformToImage( XVtx, VVtx, VtxCnt, 160, 120+Page ); + Inc( AX, 1 ); (* Bump angles *) + Inc( AY, 2 ); + Inc( AZ, 1 ); + mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *) + mxSetClip( TRUE ); + mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *) + (* Draw objects *) + SortObjects; + for I:=0 to MAXCUB do with Cube[ZList[I]] do begin + for J:=0 to 5 do begin + K := Face[J].Texture; + mxTexturePoly( 4, Face[J].Vtx, VVtx, Txts[K].Desc, Txts[K].Data^, Txts[K].Width ); + end; + end; + (* Flip page: at 320x240 the Start Address Register Low is always zero *) + case Page of + 0 : begin PortW[$3D4] := $000C; Page := 240; end; + 240: begin PortW[$3D4] := $4B0C; Page := 480; end; + 480: begin PortW[$3D4] := $960C; Page := 0; end; + end; + mxWaitRetrace; (* If the frame rate seems low, try to remove this line *) + end; + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw_/modex/DEMO05.EXE b/16/xw_/modex/DEMO05.EXE new file mode 100755 index 0000000000000000000000000000000000000000..21a7c207f7134ed187a08530637509b96b37b19e GIT binary patch literal 22528 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 CoI~RP literal 0 HcmV?d00001 diff --git a/16/xw_/modex/DEMO05.PAS b/16/xw_/modex/DEMO05.PAS new file mode 100755 index 00000000..819c5cf3 --- /dev/null +++ b/16/xw_/modex/DEMO05.PAS @@ -0,0 +1,131 @@ +(* + DEMO05 - A Gouraud-shaded rotating torus + (c) 1994 Alessandro Scotti +*) +uses Crt, Modex, Threed; + +(* Define ALTPAL for alternate palette *) +{$define ALTPAL} + +const + MAXVTX1 = 15; RADIUS1 = 70; (* MAXVTX1+1 must be multiple of 4 *) + MAXVTX2 = 15; RADIUS2 = 30; + MAXVTX = (MAXVTX1+1)*(MAXVTX2+1)-1; + MAXFACE = MAXVTX; + Trans : TPoint = ( X:0; Y:0; Z:0 ); (* Object translation *) + Light : TPoint = ( X:0; Y:0; Z:-63*$10000 ); (* Light direction *) +type + TQuad = record + QVtx : array[ 0..3 ] of integer; + end; +var + Vtx, XVtx : array[ 0..MAXVTX ] of TPoint; (* Points *) + VVtx : array[ 0..MAXVTX ] of record X, Y: integer end; + Face : array[ 0..MAXFACE ] of TQuad; (* Polys *) + Culled : array[ 0..MAXFACE ] of integer; + GNrm,XGNrm: array[ 0..MAXVTX ] of TVector; (* Gouraud normals *) + VtxLight : array[ 0..MAXVTX ] of integer; (* Points brightness *) + Page : word; + +function GetVtx( I1, I2: integer ): integer; +begin + GetVtx := (I1 mod (MAXVTX1+1))*(MAXVTX2+1) + I2 mod (MAXVTX2+1); +end; + +procedure Init; +var + R, N, X, Y, Z: real; + I, J, K, V: integer; +begin + (* Build vertexes *) + for I:=0 to MAXVTX1 do begin + K := (I + (MAXVTX1+1) shr 2) mod (MAXVTX1+1); + R := RADIUS1 + RADIUS2*Cos( 2*K*Pi / (MAXVTX1+1) ); + for J:=0 to MAXVTX2 do begin + V := I*(MAXVTX2+1)+J; (* Index of current vertex *) + (* Compute coordinates of current vertex *) + X := R*Cos(2*J*Pi / (MAXVTX2+1)); (* Get coordinates *) + Y := R*Sin(2*J*Pi / (MAXVTX2+1)); + Z := RADIUS2*Sin(2*K*Pi / (MAXVTX1+1)); + Vtx[V].X := Round( X )*$10000; (* Save coordinates *) + Vtx[V].Y := Round( Y )*$10000; + Vtx[V].Z := Round( Z )*$10000; + (* Compute direction of Gouraud normal thru current vertex *) + X := X - RADIUS1*Cos(2*J*Pi / (MAXVTX2+1)); + Y := Y - RADIUS1*Sin(2*J*Pi / (MAXVTX2+1)); + N := Sqrt( X*X + Y*Y + Z*Z ); (* Get vector length *) + GNrm[V].X := Trunc( X*$10000/N ); (* Save normal vector *) + GNrm[V].Y := Trunc( Y*$10000/N ); + GNrm[V].Z := Trunc( Z*$10000/N ); + end; + end; + (* Generate faces so that depth-sorting is not needed: there are still *) + (* some *very* little errors, but this is the best I could devise *) + J := 0; + K := 0; + for I:=0 to MAXFACE do with Face[I] do begin + QVtx[0] := GetVtx( J, K ); + QVtx[1] := GetVtx( J, K+1 ); + QVtx[2] := GetVtx( J+1, K+1 ); + QVtx[3] := GetVtx( J+1, K ); + Inc( K ); + if( K > MAXVTX2 ) then begin + K := 0; + Inc( J ); + end; + end; +{$ifndef ALTPAL} + for I:=0 to 63 do mxSetColor( I+64, 0, 0, I ); (* Blue palette *) +{$else} + for I:=0 to 31 do mxSetColor(I+64, 0, I shl 1, 0); (* Green neon palette *) + for I:=32 to 63 do mxSetColor ( I+64, (I-32) shl 1, 63, (I-32) shl 1 ); +{$endif} +end; + +var + AX, AY, AZ: byte; + I: word; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; (* Start with hidden page *) + + AX := 0; + AY := 0; + AZ := 0; + (* Init 3D transforms, perspective is intentionally exaggerated *) + tdSetTranslation( Trans ); + tdSetLight( Light ); + tdSetPerspective( 400*$10000, $10000, $10000 ); + (* Main loop, all magic here! *) + while( not KeyPressed ) do begin + tdSetRotation( AX, AY, AZ ); (* Set new angles *) + tdTransform( Vtx, XVtx, MAXVTX+1 ); (* 3D transform points *) + tdTransformToImage( XVtx, VVtx, MAXVTX+1, 160, 120+Page ); + tdRotate( GNrm, XGNrm, MAXVTX+1 ); (* Rotate Gouraud normals *) + tdTransformLight( XGNrm, VtxLight, MAXVTX+1 ); + (* Backplane culling is not really needed here! *) + FillChar( Culled, SizeOf(Culled), 0 ); + tdBackPlaneCull( Face, XVtx, Culled, MAXFACE+1, SizeOf(TQuad) ); + Inc( AX, 1 ); (* Bump angles *) + Inc( AY, 2 ); + Inc( AZ, 3 ); + mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *) + mxSetClip( TRUE ); + mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *) + (* Draw polygons *) + for I:=0 to MAXFACE do with Face[I] do + if( Culled[I] >= 0 ) then mxGouraudPoly( 4, QVtx, VVtx, VtxLight, 64 ); + (* Flip page: at 320x240 the Start Address Register Low is always zero *) + case Page of + 0 : begin PortW[$3D4] := $000C; Page := 240; end; + 240: begin PortW[$3D4] := $4B0C; Page := 480; end; + 480: begin PortW[$3D4] := $960C; Page := 0; end; + end; + mxWaitRetrace; (* Uncomment this instruction if screen flickers *) + end; + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw_/modex/DEMO06.DAT b/16/xw_/modex/DEMO06.DAT new file mode 100755 index 0000000000000000000000000000000000000000..1ac2c2bb8f8c79a7cf1f3c968f75e8e5ac8cd705 GIT binary patch literal 77568 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 P3zel81wBCVexm$;I2yv& literal 0 HcmV?d00001 diff --git a/16/xw_/modex/DEMO06.EXE b/16/xw_/modex/DEMO06.EXE new file mode 100755 index 0000000000000000000000000000000000000000..f1308e8a536aa9d3d4574566fd018d698d5ef784 GIT binary patch literal 10864 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 G@BaZ%)XT^K literal 0 HcmV?d00001 diff --git a/16/xw_/modex/DEMO06.PAS b/16/xw_/modex/DEMO06.PAS new file mode 100755 index 00000000..f26af067 --- /dev/null +++ b/16/xw_/modex/DEMO06.PAS @@ -0,0 +1,135 @@ +(* + DEMO06 - Magnifying glass + (c) 1994 Alessandro Scotti +*) +uses Crt, Modex; + +const + R = 40; (* Lens radius *) + K : real = 1.8; (* Magnifying factor, less makes a stronger lens *) +type + TLine = array[ 0..319 ] of byte; + PLine = ^TLine; + TScreen = array[ 0..239 ] of PLine; +var + VScreen: TScreen; (* Virtual screen *) + BallX : array[ 0..R, 0..R ] of integer; + BallY : array[ 0..R, 0..R ] of integer; + Sprite : array[ -R..R, -R..R ] of byte; + Page : word; + +(* Returns "lens-view" coordinates of X,Y *) +procedure GetCoords( var X, Y: integer ); +var + LR, Z, SinA, SinB, TgB, Q: real; +begin + LR := Sqrt( X*X + Y*Y ); + if( LR = 0 ) then Exit; + if( LR < R ) then begin + Z := Sqrt( R*R - LR*LR ); + SinA := LR / R; + SinB := SinA / K; + TgB := SinB / Sqrt( 1-SinB*SinB ); + Q := LR - TgB*Z; + X := Round( X * ( Q/LR ) ); + Y := Round( Y * ( Q/LR ) ); + end; +end; + +procedure Init; +var + F : file; + Palette: array[ 0..767 ] of record R, G, B: byte; end; + X, Y, + X2, Y2 : integer; +begin + (* Load background image *) + Assign( F, 'demo06.dat' ); + Reset( F, 1 ); + BlockRead( F, Palette, 768 ); + mxSetPalette( @Palette, 0, 256 ); + for Y:=0 to 239 do begin + New( VScreen[Y] ); + BlockRead( F, VScreen[Y]^, 320 ); + mxPutImage( VScreen[Y], 0, 480+Y, 320, 1, OP_MOVE ); + end; + Close( F ); + (* Build lens *) + for X:=0 to R do begin + for Y:=0 to R do begin + X2 := X; + Y2 := Y; + GetCoords( X2, Y2 ); + BallX[X, Y] := X2; + BallY[X, Y] := Y2; + end; + end; +end; + +procedure PutLens( OX, OY: integer ); +var + X, Y: integer; +begin + for X:=0 to R do begin + for Y:=0 to R do begin + Sprite[Y][X] := VScreen[ OY+BallY[X,Y] ]^[ OX+BallX[X,Y] ]; + Sprite[Y][-X] := VScreen[ OY+BallY[X,Y] ]^[ OX-BallX[X,Y] ]; + Sprite[-Y][X] := VScreen[ OY-BallY[X,Y] ]^[ OX+BallX[X,Y] ]; + Sprite[-Y][-X] := VScreen[ OY-BallY[X,Y] ]^[ OX-BallX[X,Y] ]; + end; + end; + (* Draw the sprite *) + mxPutImage( @Sprite, OX-R, OY-R+Page, 2*R+1, 2*R+1, OP_MOVE ); +end; + +function Delta: integer; +begin + Delta := Random(3)+2; +end; + +procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer ); +begin + if( Cond ) then begin + Coord := NewCoord; + DeltaC := Sign*Delta; + end; +end; + +var + X, Y, DX, DY: integer; + C: char; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; + X := R; + Y := R; + Randomize; + DX := Delta; + DY := Delta; + + (* Main loop *) + repeat + (* Update video *) + mxBitBlt( 0, 480, 320, 240, 0, Page ); + PutLens( X, Y ); + mxCircle( X, Page+Y, R, 0 ); + (* Update lens coordinates *) + Inc( X, DX ); + Check( X+R >= 319, X, DX, 319-R, -1 ); + Check( X <= R, X, DX, R, +1 ); + Inc( Y, DY ); + Check( Y+R >= 239, Y, DY, 239-R, -1 ); + Check( Y <= R, Y, DY, R, +1 ); + (* Flip pages: double buffering, avoid wait for display *) + case Page of + 0 : begin PortW[$3D4] := $000C; Page := 240; end; + 240: begin PortW[$3D4] := $4B0C; Page := 0; end; + end; + mxWaitRetrace; (* Wait for hidden page to show *) + until( KeyPressed ); + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw_/modex/DEMO07.EXE b/16/xw_/modex/DEMO07.EXE new file mode 100755 index 0000000000000000000000000000000000000000..8a401169bba312a0d668452c9df6086505c394a8 GIT binary patch literal 7440 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 639, X, DX, 319, -1 ); + Check( X < 0, X, DX, 0, +1 ); + Inc( Y, DY ); + Check( Y+200 >= 399, Y, DY, 199, -1 ); + Check( Y < 0, Y, DY, 0, +1 ); + mxPan( X, Y ); + mxWaitRetrace; + end; + + (* Shutdown *) + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw_/modex/MATH.INC b/16/xw_/modex/MATH.INC new file mode 100755 index 00000000..742af410 --- /dev/null +++ b/16/xw_/modex/MATH.INC @@ -0,0 +1,34 @@ +; +; MATH.INC - Include file for THREED.ASM +; + +; 3-dimensional point, coordinates in fixed format (16:16) +; +TPOINT STRUC + X DD ? + Y DD ? + Z DD ? +TPOINT ENDS + +; 2-dimensional point, coordinates in integer format +; +TIMAGEPOINT STRUC + IX DW ? + IY DW ? +TIMAGEPOINT ENDS + +; Fixed-point divide: EAX = EAX / arg +; +.xdiv MACRO arg + xor edx, edx + shld edx, eax, 16 + shl eax, 16 + idiv arg +ENDM + +; Fixed-point multiply: EAX = EAX * arg +; +.xmul MACRO arg + imul arg + shrd eax, edx, 16 +ENDM diff --git a/16/xw_/modex/PLASMA.PAS b/16/xw_/modex/PLASMA.PAS new file mode 100755 index 00000000..237e292a --- /dev/null +++ b/16/xw_/modex/PLASMA.PAS @@ -0,0 +1,103 @@ +unit Plasma; +interface + +const + PAL_RGB = 0; + PAL_CLOUDS = 1; + PAL_LANDSCAPE = 2; + +procedure MakePlasma( X, Y: integer; W, H: word; C1, C2, C3, C4: byte ); +procedure MakePlasmaPalette( var Palette; What: word ); + +implementation uses Modex; + +procedure NewColor( XA, YA, X, Y, XB, YB: integer ); +var + Color: longint; +begin + Color := Abs( XA-XB )+Abs( YA-YB ); + Color := Random( Color shl 1 )-Color; + Color := (Color+mxGetPixel( XA, YA )+mxGetPixel( XB, YB )+1) shr 1; + if( Color < 1 ) then Color := 1; + if( Color > 192 ) then Color := 192; + if( mxGetPixel( X, Y ) = 0 ) then + mxPutPixel( X, Y, Lo(Color) ); +end; + +procedure Divide( X1, Y1, X2, Y2: integer ); +var + X, Y, Color: integer; +begin + if not( (X2-X1<2)and(Y2-Y1<2) ) then begin + X := (X1+X2) shr 1; + Y := (Y1+Y2) shr 1; + NewColor( X1, Y1, X, Y1, X2, Y1 ); + NewColor( X2, Y1, X2, Y, X2, Y2 ); + NewColor( X1, Y2, X, Y2, X2, Y2 ); + NewColor( X1, Y1, X1, Y, X1, Y2 ); + Color := (mxGetPixel( X1, Y1 )+mxGetPixel( X2, Y1 )+ + mxGetPixel( X2, Y2 )+mxGetPixel( X1, Y2 )) shr 2; + mxPutPixel( X, Y, Color ); + Divide( X1, Y1, X, Y ); + Divide( X, Y1, X2, Y ); + Divide( X, Y, X2, Y2 ); + Divide( X1, Y, X, Y2 ); + end; +end; + +procedure MakePlasma; +begin + Dec( W ); + Dec( H ); + mxPutPixel( X, Y, C1 ); + mxPutPixel( X, Y+H, C2 ); + mxPutPixel( X+W, Y+H, C3 ); + mxPutPixel( X+W, Y, C4 ); + Divide( X, Y, X+W, Y+H ); +end; + +procedure MakePlasmaPalette; +type + TPal = array[ byte ] of record R, G, B: byte end; +var + I: word; +begin + FillChar( TPal(Palette)[1], 192*3, 0 ); + case What of + PAL_CLOUDS: + for I:=1 to 192 do begin + TPal(Palette)[I].R := Abs( I-96 )*63 div 96; + TPal(Palette)[I].G := Abs( I-96 )*63 div 96; + TPal(Palette)[I].B := 63; + end; + PAL_LANDSCAPE: + begin + for I:=0 to 31 do begin + TPal(Palette)[I+1].R := I; + TPal(Palette)[I+1].G := I; + TPal(Palette)[I+1].B := I + I shr 1+15; + end; + for I:=32 to 63 do begin + TPal(Palette)[I+1].R := 0; + TPal(Palette)[I+1].G := I; + TPal(Palette)[I+1].B := 0; + end; + for I:=64 to 191 do begin + TPal(Palette)[I+1].R := (I-64) div 3 + 15; + TPal(Palette)[I+1].G := (I-64) div 3 + 15; + TPal(Palette)[I+1].B := (I-64) div 3 + 15; + end; + end; + else + for I:=1 to 64 do begin + TPal(Palette)[I].G := I-1; + TPal(Palette)[I].B := 64-I; + TPal(Palette)[I+64].R := I-1; + TPal(Palette)[I+64].G := 64-I; + TPal(Palette)[I+128].B := I-1; + TPal(Palette)[I+128].R := 64-I; + end; + end; +end; + +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 index 0000000000000000000000000000000000000000..a10d7db5a0a62654c70c632d8ce6b078a520613c GIT binary patch literal 10336 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 DJ^3nG literal 0 HcmV?d00001 diff --git a/16/xw_/modex/QIX2.PAS b/16/xw_/modex/QIX2.PAS new file mode 100755 index 00000000..d1b59791 --- /dev/null +++ b/16/xw_/modex/QIX2.PAS @@ -0,0 +1,210 @@ +{$E-,N+} +uses Crt, Modex; + +const + DEFVERT = 12; (* Vertex count *) + DEFREPL = 3; (* Repetition count *) + DEFQIXS = 2; (* Qixs *) + FADESPEED = 48; +type + TPoint = record + X, Y : integer; + end; + TRGB = record + R, G, B: byte; + end; + TQix = record + Color: integer; + Vert : array[ 0..DEFVERT-1, 0..DEFREPL-1 ] of TPoint; + Delta: array[ 0..DEFVERT-1 ] of TPoint; + end; +var + Page : integer; + MaxX, + MaxY : word; + Qix : array[ 0..DEFQIXS-1 ] of TQix; + Pal : array[ byte ] of TRGB; + +type + TReal = double; + TRPoint = record + X, Y: TReal; + end; + TMatrix = array[ 0..3, 0..3 ] of TReal; +var + M: TMatrix; + G: array[ 0..DEFVERT-1 ] of TRPoint; + C: array[ 0..DEFVERT-1 ] of TRPoint; + +procedure BumpPal( Idx, DR, DG, DB, Steps: integer ); +var + I: integer; +begin + for I:=1 to Steps do begin + Pal[Idx+1].R := Pal[Idx].R + DR; + Pal[Idx+1].G := Pal[Idx].G + DG; + Pal[Idx+1].B := Pal[Idx].B + DB; + Inc( Idx ); + end; +end; + +procedure InitPalette; +begin + with Pal[0] do begin R:=0; G:=0; B:=0; end; + with Pal[1] do begin R:=0; G:=0; B:=62; end; + BumpPal( 1, 0, 2, -2, 31 ); + BumpPal( 32, 2, -2, 0, 31 ); + BumpPal( 63, -2, 2, 2, 31 ); + BumpPal( 94, 2, 0, -2, 31 ); + BumpPal( 125, -2, -2, 2, 31 ); +end; + +procedure Init( var Qix: TQix; Color: integer ); +var + I: integer; +begin + FillChar( Qix.Vert, SizeOf(Qix.Vert), 0 ); + for I:=0 to DEFVERT-1 do begin + Qix.Vert[I, DEFREPL-1].X := Random( MaxX ); + Qix.Vert[I, DEFREPL-1].Y := Random( MaxY ); + Qix.Delta[I].X := Random(5)+1; + Qix.Delta[I].Y := Random(5)+1; + end; + Qix.Color := Color; + + (* Initialize matrix (Catmull-Rom) *) + M[0,0] := -1/2; M[0,1] := 3/2; M[0,2] := -3/2; M[0,3] := 1/2; + M[1,0] := 1; M[1,1] := -5/2; M[1,2] := 2; M[1,3] := -1/2; + M[2,0] := -1/2; M[2,1] := 0; M[2,2] := 1/2; M[2,3] := 0; + M[3,0] := 0; M[3,1] := 1; M[3,2] := 0; M[3,3] := 0; +end; + +procedure mxBezier( var Qix: TQix; I0, Idx, N: integer ); +var + I, J: integer; + T, T2, T3: TReal; + X0, Y0, X, Y: TReal; + Delta: TReal; +begin + (* Compute coefficients *) + for I:=0 to 3 do begin + C[I].X := 0; + for J:=0 to 3 do C[I].X := C[I].X + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].X; + C[I].Y := 0; + for J:=0 to 3 do C[I].Y := C[I].Y + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].Y; + end; + X0 := C[3].X; + Y0 := C[3].Y; + Delta := 1 / N; + T := 0; + for I:=1 to N do begin + T := T + Delta; + T2 := T*T; + T3 := T*T2; + X := C[0].X*T3 + C[1].X*T2 + C[2].X*T + C[3].X; + Y := C[0].Y*T3 + C[1].Y*T2 + C[2].Y*T + C[3].Y; + mxLine( Round(X0), Page+Round(Y0), Round(X), Page+Round(Y), Qix.Color, OP_SET ); + X0 := X; + Y0 := Y; + end; +end; + +procedure Plot( var Qix: TQix; Idx: integer ); +var + I, J: integer; +begin + for I:=0 to DEFVERT-1 do begin + mxBezier( Qix, I, Idx, 12 ); + end; +end; + +procedure Update( var Qix: TQix; Idx: integer ); +var + I: integer; +begin + for I:=0 to DEFVERT-1 do with Qix do begin + Inc( Vert[I,Idx].X, Delta[I].X ); + if( Vert[I,Idx].X < 0 ) then begin + Vert[I,Idx].X := 0; + Delta[I].X := Random( 5 )+1; + end; + if( Vert[I,Idx].X > MaxX ) then begin + Vert[I,Idx].X := MaxX; + Delta[I].X := -Random( 5 )-1; + end; + Inc( Vert[I,Idx].Y, Delta[I].Y ); + if( Vert[I,Idx].Y < 0 ) then begin + Vert[I,Idx].Y := 0; + Delta[I].Y := Random( 5 )+1; + end; + if( Vert[I,Idx].Y > MaxY ) then begin + Vert[I,Idx].Y := MaxY; + Delta[I].Y := -Random( 5 )-1; + end; + end; +end; + +procedure Copy( var Qix: TQix; Dest, Src: integer ); +var + I: integer; +begin + for I:=0 to DEFVERT-1 do with Qix do begin + Vert[I,Dest].X := Vert[I,Src].X; + Vert[I,Dest].Y := Vert[I,Src].Y; + end; +end; + +procedure AnimateQix; +var + Q, Idx, I, J, P, Count: integer; +begin + Count := 0; + P := DEFREPL-1; + I := 0; + J := 1; + repeat + mxSetClipRegion( 0, Page, MaxX+1, MaxY+1 ); + mxSetClip( TRUE ); + mxFillBox( 0, Page, MaxX+1, MaxY+1, 0, OP_SET ); + for Q:=0 to DEFQIXS-1 do begin + Copy( Qix[Q], I, P ); + Update( Qix[Q], I ); + for Idx:=0 to DEFREPL-1 do begin + Plot( Qix[Q], Idx ); + end; + end; + I := (I+1) mod DEFREPL; + J := (J+1) mod DEFREPL; + P := (P+1) mod DEFREPL; + Inc( Count ); + mxStartLine( Page ); + if( Count >= FADESPEED ) then begin + for Q:=0 to DEFQIXS-1 do begin + Inc( Qix[Q].Color ); + if( Qix[Q].Color > 156 ) then + Qix[Q].Color := 1; + end; + Count := 0; + end; + Page := 240-Page; + until( KeyPressed ); +end; + +var + I: integer; +begin + Randomize; + mxInit; + mxSetMode( MX_320x240 ); + mxGetScreenSize( MaxX, MaxY ); + for I:=0 to DEFQIXS-1 do + Init( Qix[I], (I*(155 div DEFQIXS)) mod 155 + 1 ); + InitPalette; + mxSetPalette( @Pal, 0, 157 ); + Page := 240; + Dec( MaxX ); + Dec( MaxY ); + AnimateQix; + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw_/modex/README.TXT b/16/xw_/modex/README.TXT new file mode 100755 index 00000000..306e8b9a --- /dev/null +++ b/16/xw_/modex/README.TXT @@ -0,0 +1,8 @@ +ModeX - A graphical library for DOS programs +Copyright (c) 1993-1994 Alessandro Scotti +http://www.ascotti.org/ + +Please look at the above site in the "Art of..." and +then in the "Old programs" section for more information. + + diff --git a/16/xw_/modex/SINCOS.INC b/16/xw_/modex/SINCOS.INC new file mode 100755 index 00000000..6986eeeb --- /dev/null +++ b/16/xw_/modex/SINCOS.INC @@ -0,0 +1,518 @@ +; +; SINCOS.INC - Sin/cos tables for THREED.ASM +; + +tblSin LABEL DWORD + DD 0 + DD 411733 + DD 823219 + DD 1234209 + DD 1644455 + DD 2053710 + DD 2461729 + DD 2868265 + DD 3273072 + DD 3675909 + DD 4076531 + DD 4474698 + DD 4870169 + DD 5262706 + DD 5652074 + DD 6038037 + DD 6420363 + DD 6798821 + DD 7173184 + DD 7543226 + DD 7908725 + DD 8269459 + DD 8625213 + DD 8975771 + DD 9320922 + DD 9660458 + DD 9994176 + DD 10321873 + DD 10643353 + DD 10958422 + DD 11266890 + DD 11568571 + DD 11863283 + DD 12150850 + DD 12431097 + DD 12703856 + DD 12968963 + DD 13226258 + DD 13475586 + DD 13716797 + DD 13949745 + DD 14174291 + DD 14390298 + DD 14597637 + DD 14796184 + DD 14985817 + DD 15166424 + DD 15337895 + DD 15500126 + DD 15653022 + DD 15796488 + DD 15930439 + DD 16054795 + DD 16169479 + DD 16274424 + DD 16369565 + DD 16454846 + DD 16530216 + DD 16595628 + DD 16651044 + DD 16696429 + DD 16731757 + DD 16757007 + DD 16772163 + DD 16777216 + DD 16772163 + DD 16757007 + DD 16731757 + DD 16696429 + DD 16651044 + DD 16595628 + DD 16530216 + DD 16454846 + DD 16369565 + DD 16274424 + DD 16169479 + DD 16054795 + DD 15930439 + DD 15796488 + DD 15653022 + DD 15500126 + DD 15337895 + DD 15166424 + DD 14985817 + DD 14796184 + DD 14597637 + DD 14390298 + DD 14174291 + DD 13949745 + DD 13716797 + DD 13475586 + DD 13226258 + DD 12968963 + DD 12703856 + DD 12431097 + DD 12150850 + DD 11863283 + DD 11568571 + DD 11266890 + DD 10958422 + DD 10643353 + DD 10321873 + DD 9994176 + DD 9660458 + DD 9320922 + DD 8975771 + DD 8625213 + DD 8269459 + DD 7908725 + DD 7543226 + DD 7173184 + DD 6798821 + DD 6420363 + DD 6038037 + DD 5652074 + DD 5262706 + DD 4870169 + DD 4474698 + DD 4076531 + DD 3675909 + DD 3273072 + DD 2868265 + DD 2461729 + DD 2053710 + DD 1644455 + DD 1234209 + DD 823219 + DD 411733 + DD 0 + DD -411733 + DD -823219 + DD -1234209 + DD -1644455 + DD -2053710 + DD -2461729 + DD -2868265 + DD -3273072 + DD -3675909 + DD -4076531 + DD -4474698 + DD -4870169 + DD -5262706 + DD -5652074 + DD -6038037 + DD -6420363 + DD -6798821 + DD -7173184 + DD -7543226 + DD -7908725 + DD -8269459 + DD -8625213 + DD -8975771 + DD -9320922 + DD -9660458 + DD -9994176 + DD -10321873 + DD -10643353 + DD -10958422 + DD -11266890 + DD -11568571 + DD -11863283 + DD -12150850 + DD -12431097 + DD -12703856 + DD -12968963 + DD -13226258 + DD -13475586 + DD -13716797 + DD -13949745 + DD -14174291 + DD -14390298 + DD -14597637 + DD -14796184 + DD -14985817 + DD -15166424 + DD -15337895 + DD -15500126 + DD -15653022 + DD -15796488 + DD -15930439 + DD -16054795 + DD -16169479 + DD -16274424 + DD -16369565 + DD -16454846 + DD -16530216 + DD -16595628 + DD -16651044 + DD -16696429 + DD -16731757 + DD -16757007 + DD -16772163 + DD -16777216 + DD -16772163 + DD -16757007 + DD -16731757 + DD -16696429 + DD -16651044 + DD -16595628 + DD -16530216 + DD -16454846 + DD -16369565 + DD -16274424 + DD -16169479 + DD -16054795 + DD -15930439 + DD -15796488 + DD -15653022 + DD -15500126 + DD -15337895 + DD -15166424 + DD -14985817 + DD -14796184 + DD -14597637 + DD -14390298 + DD -14174291 + DD -13949745 + DD -13716797 + DD -13475586 + DD -13226258 + DD -12968963 + DD -12703856 + DD -12431097 + DD -12150850 + DD -11863283 + DD -11568571 + DD -11266890 + DD -10958422 + DD -10643353 + DD -10321873 + DD -9994176 + DD -9660458 + DD -9320922 + DD -8975771 + DD -8625213 + DD -8269459 + DD -7908725 + DD -7543226 + DD -7173184 + DD -6798821 + DD -6420363 + DD -6038037 + DD -5652074 + DD -5262706 + DD -4870169 + DD -4474698 + DD -4076531 + DD -3675909 + DD -3273072 + DD -2868265 + DD -2461729 + DD -2053710 + DD -1644455 + DD -1234209 + DD -823219 + DD -411733 +tblCos LABEL DWORD + DD 16777216 + DD 16772163 + DD 16757007 + DD 16731757 + DD 16696429 + DD 16651044 + DD 16595628 + DD 16530216 + DD 16454846 + DD 16369565 + DD 16274424 + DD 16169479 + DD 16054795 + DD 15930439 + DD 15796488 + DD 15653022 + DD 15500126 + DD 15337895 + DD 15166424 + DD 14985817 + DD 14796184 + DD 14597637 + DD 14390298 + DD 14174291 + DD 13949745 + DD 13716797 + DD 13475586 + DD 13226258 + DD 12968963 + DD 12703856 + DD 12431097 + DD 12150850 + DD 11863283 + DD 11568571 + DD 11266890 + DD 10958422 + DD 10643353 + DD 10321873 + DD 9994176 + DD 9660458 + DD 9320922 + DD 8975771 + DD 8625213 + DD 8269459 + DD 7908725 + DD 7543226 + DD 7173184 + DD 6798821 + DD 6420363 + DD 6038037 + DD 5652074 + DD 5262706 + DD 4870169 + DD 4474698 + DD 4076531 + DD 3675909 + DD 3273072 + DD 2868265 + DD 2461729 + DD 2053710 + DD 1644455 + DD 1234209 + DD 823219 + DD 411733 + DD 0 + DD -411733 + DD -823219 + DD -1234209 + DD -1644455 + DD -2053710 + DD -2461729 + DD -2868265 + DD -3273072 + DD -3675909 + DD -4076531 + DD -4474698 + DD -4870169 + DD -5262706 + DD -5652074 + DD -6038037 + DD -6420363 + DD -6798821 + DD -7173184 + DD -7543226 + DD -7908725 + DD -8269459 + DD -8625213 + DD -8975771 + DD -9320922 + DD -9660458 + DD -9994176 + DD -10321873 + DD -10643353 + DD -10958422 + DD -11266890 + DD -11568571 + DD -11863283 + DD -12150850 + DD -12431097 + DD -12703856 + DD -12968963 + DD -13226258 + DD -13475586 + DD -13716797 + DD -13949745 + DD -14174291 + DD -14390298 + DD -14597637 + DD -14796184 + DD -14985817 + DD -15166424 + DD -15337895 + DD -15500126 + DD -15653022 + DD -15796488 + DD -15930439 + DD -16054795 + DD -16169479 + DD -16274424 + DD -16369565 + DD -16454846 + DD -16530216 + DD -16595628 + DD -16651044 + DD -16696429 + DD -16731757 + DD -16757007 + DD -16772163 + DD -16777216 + DD -16772163 + DD -16757007 + DD -16731757 + DD -16696429 + DD -16651044 + DD -16595628 + DD -16530216 + DD -16454846 + DD -16369565 + DD -16274424 + DD -16169479 + DD -16054795 + DD -15930439 + DD -15796488 + DD -15653022 + DD -15500126 + DD -15337895 + DD -15166424 + DD -14985817 + DD -14796184 + DD -14597637 + DD -14390298 + DD -14174291 + DD -13949745 + DD -13716797 + DD -13475586 + DD -13226258 + DD -12968963 + DD -12703856 + DD -12431097 + DD -12150850 + DD -11863283 + DD -11568571 + DD -11266890 + DD -10958422 + DD -10643353 + DD -10321873 + DD -9994176 + DD -9660458 + DD -9320922 + DD -8975771 + DD -8625213 + DD -8269459 + DD -7908725 + DD -7543226 + DD -7173184 + DD -6798821 + DD -6420363 + DD -6038037 + DD -5652074 + DD -5262706 + DD -4870169 + DD -4474698 + DD -4076531 + DD -3675909 + DD -3273072 + DD -2868265 + DD -2461729 + DD -2053710 + DD -1644455 + DD -1234209 + DD -823219 + DD -411733 + DD 0 + DD 411733 + DD 823219 + DD 1234209 + DD 1644455 + DD 2053710 + DD 2461729 + DD 2868265 + DD 3273072 + DD 3675909 + DD 4076531 + DD 4474698 + DD 4870169 + DD 5262706 + DD 5652074 + DD 6038037 + DD 6420363 + DD 6798821 + DD 7173184 + DD 7543226 + DD 7908725 + DD 8269459 + DD 8625213 + DD 8975771 + DD 9320922 + DD 9660458 + DD 9994176 + DD 10321873 + DD 10643353 + DD 10958422 + DD 11266890 + DD 11568571 + DD 11863283 + DD 12150850 + DD 12431097 + DD 12703856 + DD 12968963 + DD 13226258 + DD 13475586 + DD 13716797 + DD 13949745 + DD 14174291 + DD 14390298 + DD 14597637 + DD 14796184 + DD 14985817 + DD 15166424 + DD 15337895 + DD 15500126 + DD 15653022 + DD 15796488 + DD 15930439 + DD 16054795 + DD 16169479 + DD 16274424 + DD 16369565 + DD 16454846 + DD 16530216 + DD 16595628 + DD 16651044 + DD 16696429 + DD 16731757 + DD 16757007 + DD 16772163 diff --git a/16/xw_/modex/THREED.ASM b/16/xw_/modex/THREED.ASM new file mode 100755 index 00000000..5ecd3ba3 --- /dev/null +++ b/16/xw_/modex/THREED.ASM @@ -0,0 +1,872 @@ +COMMENT / + Fixed-point math functions and 3D transforms + Copyright (c) 1993,94 by Alessandro Scotti +/ +WARN PRO +P386 +JUMPS +LOCALS + +INCLUDE MATH.INC + +PUBLIC tdFixedMul +PUBLIC tdGetNormal +PUBLIC tdRotate +PUBLIC tdGetSurfaceLight +PUBLIC tdSetLight +PUBLIC tdSetRotation +PUBLIC tdSetTranslation +PUBLIC tdTransform +PUBLIC tdTransformToImage +PUBLIC tdTransformLight +PUBLIC tdBackPlaneCull +PUBLIC tdSetPerspective + +;----------------------------------------------------------- +; +; Data segment +; +MATH_DATA SEGMENT USE16 PARA PUBLIC 'DATA' + ASSUME ds:MATH_DATA + +INCLUDE SINCOS.INC ; Fixed 8:24 sin/cos table + +XRotation TPOINT <> ; 3x3 rotation matrix +YRotation TPOINT <> +ZRotation TPOINT <> + +Translation TPOINT <> ; Translation vector + +Light TPOINT <> ; Light vector +AmbientLight DW 00 ; Ambient light + +XScale DD 10000h ; Scaling factor for X coordinate +YScale DD 10000h ; Scaling factor for Y coordinate +PerspectiveDistance DD 20000000h + +MATH_DATA ENDS + +;----------------------------------------------------------- +; +; Code segment +; +MATH_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MATH_TEXT, es:NOTHING, fs:NOTHING + +tdSetPerspective PROC PASCAL FAR + ARG Perspective:DWORD, \ + ScaleX:DWORD, \ + ScaleY:DWORD + USES ds + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + mov eax, [Perspective] + mov [PerspectiveDistance], eax + mov eax, [ScaleX] + mov [XScale], eax + mov eax, [ScaleY] + mov [YScale], eax + + ret +tdSetPerspective ENDP + + +;----------------------------------------------------------- +; +; Sets the rotation matrix. +; +; Input: +; RX = X-axis rotation angle +; RY = X-axis rotation angle +; RZ = X-axis rotation angle +; Output: +; none +; +tdSetRotation PROC PASCAL FAR + ARG RX:WORD, \ + RY:WORD, \ + RZ:WORD + USES ds, si, di + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + mov bx, [RZ] + mov si, [RY] + mov di, [RX] + shl bx, 2 + shl si, 2 + shl di, 2 + + push ebp ; We use EBP as a scratch register + +; Set X rotation + mov eax, tblCos[bx] + imul tblCos[si] + mov [XRotation.X], edx + + mov eax, tblSin[bx] + imul tblCos[si] + mov [XRotation.Y], edx + + mov eax, tblSin[si] + sar eax, 8 ; Convert fixed 8:24 to fixed 16:16 + mov [XRotation.Z], eax + +; Set Y rotation + mov eax, tblCos[bx] + imul tblSin[si] ; EDX:EAX = fixed 16:48 + shrd eax, edx, 24 ; EAX = fixed 8:24 + imul tblSin[di] ; EDX:EAX = fixed 16:48 + mov ebp, eax + mov ecx, edx + mov eax, tblSin[bx] + imul tblCos[di] + add eax, ebp + adc edx, ecx ; EDX:EAX = fixed 16:48 + neg edx + mov [YRotation.X], edx + + mov eax, tblSin[bx] + imul tblSin[si] + shrd eax, edx, 24 + imul tblSin[di] + mov ebp, eax + mov ecx, edx + mov eax, tblCos[bx] + imul tblCos[di] + sub eax, ebp + sbb edx, ecx + mov [YRotation.Y], edx + + mov eax, tblCos[si] + imul tblSin[di] + mov [YRotation.Z], edx + +; Set Z rotation + mov eax, tblCos[bx] + imul tblSin[si] + shrd eax, edx, 24 + imul tblCos[di] + mov ebp, eax + mov ecx, edx + mov eax, tblSin[bx] + imul tblSin[di] + sub eax, ebp + sbb edx, ecx + mov [ZRotation.X], edx + + mov eax, tblSin[bx] + imul tblSin[si] + shrd eax, edx, 24 + imul tblCos[di] + mov ebp, eax + mov ecx, edx + mov eax, tblCos[bx] + imul tblSin[di] + add eax, ebp + add edx, ecx + neg edx + mov [ZRotation.Y], edx + + mov eax, tblCos[si] + imul tblCos[di] + mov [ZRotation.Z], edx + + pop ebp ; Restore EBP + + ret +tdSetRotation ENDP + +;----------------------------------------------------------- +; +; Sets the translation vector. +; +; Input: +; TV = pointer to translation vector +; Output: +; none +; +tdSetTranslation PROC PASCAL FAR + ARG TV:DWORD + USES ds, es, di + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + les di, [TV] + mov eax, es:[di].X + mov [Translation.X], eax + mov eax, es:[di].Y + mov [Translation.Y], eax + mov eax, es:[di].Z + mov [Translation.Z], eax + + ret +tdSetTranslation ENDP + +;----------------------------------------------------------- +; +; Transforms an array of TPOINT. +; +; Input: +; Source = pointer to source array of TPOINT +; Dest = pointer to destination array of TPOINT +; Count = number of entries to transform +; Output: +; none +; +tdTransform PROC PASCAL FAR + ARG Source:DWORD, \ + Dest:DWORD, \ + Count:WORD + LOCAL Adjust:DWORD + USES ds, si, es, di, fs + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + lfs si, [Source] + les di, [Dest] + + ALIGN DWORD +@@Loop: +; Transform Z coordinate + mov eax, fs:[si].X + imul [ZRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [ZRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [ZRotation.Z] + add eax, ecx + adc edx, ebx + mov ebx, eax + shrd eax, edx, 16 + add eax, [Translation.Z] ; EAX = new Z coord (fixed 16:16) + mov es:[di].Z, eax +; Get perspective factor + mov ebx, [PerspectiveDistance] + sub eax, ebx + neg eax ; EAX = PD - Z + xor edx, edx + shld edx, eax, 16 + shl eax, 16 + idiv ebx ; EAX = fixed 16:16 result + mov [Adjust], eax + +; Transform X coordinate + mov eax, fs:[si].X + imul [XRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [XRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [XRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + add eax, [Translation.X] + imul [Adjust] + shrd eax, edx, 16 + mov es:[di].X, eax + +; Transform Y coordinate + mov eax, fs:[si].X + imul [YRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [YRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [YRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + add eax, [Translation.Y] + imul [Adjust] + shrd eax, edx, 16 + mov es:[di].Y, eax + + add si, SIZE TPOINT + add di, SIZE TPOINT + dec [Count] + jnz @@Loop + + ret +tdTransform ENDP + +;----------------------------------------------------------- +; +; Transforms an array of TPOINT into an array of TIMAGEPOINT. +; +; Input: +; Source = pointer to source array of TPOINT +; Dest = pointer to destination array of TIMAGEPOINT +; Count = number of entries to transform +; DeltaX = translation distance for the X coordinate +; DeltaY = translation distance for the Y coordinate +; Output: +; the maximum Z value +; +tdTransformToImage PROC PASCAL FAR + ARG Source:DWORD, \ + Dest:DWORD, \ + Count:WORD, \ + DeltaX:WORD, \ + DeltaY:WORD + LOCAL Adjust:DWORD, \ + Max:DWORD + USES ds, si, es, di, fs + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + lfs si, [Source] + les di, [Dest] + mov [Max], 80000000h + +@@Loop: +; Check max Z + mov eax, fs:[si].Z + cmp eax, [Max] + jle @@1 + mov [Max], eax +@@1: + +; Transform X coordinate + mov ax, WORD PTR fs:[si].X[2] + add ax, [DeltaX] + mov es:[di].IX, ax + +; Transform Y coordinate + mov ax, WORD PTR fs:[si].Y[2] + add ax, [DeltaY] + mov es:[di].IY, ax + + add si, SIZE TPOINT + add di, SIZE TIMAGEPOINT + dec [Count] + jnz @@Loop + + mov eax, [Max] + shld edx, eax, 16 + ret +tdTransformToImage ENDP + +;----------------------------------------------------------- +; +; Sets the light source. +; +; Input: +; Light = pointer to light vector +; Output: +; none +; +tdSetLight PROC PASCAL FAR + ARG L:DWORD + USES ds, es, di + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + les di, [L] + mov eax, es:[di].X + mov [Light.X], eax + mov eax, es:[di].Y + mov [Light.Y], eax + mov eax, es:[di].Z + mov [Light.Z], eax + + ret +tdSetLight ENDP + +;----------------------------------------------------------- +; +; Computes light intensity for an array of surfaces. +; +; Input: +; Normals = pointer to an array of surface normals +; Lights = pointer to an array of integer to be filled with +; light intensity +; Count = number of elements to transform +; Output: +; none +; +tdTransformLight PROC PASCAL FAR + ARG Normals:DWORD, \ + Lights:DWORD, \ + Count:WORD + USES ds, si, es, di, fs + + mov ax, SEG MATH_DATA + mov fs, ax + ASSUME fs:MATH_DATA + + lds si, [Normals] + les di, [Lights] + ASSUME ds:NOTHING + +; Intensity is given by the dot product between the Light vector and +; the surface normal +@@Loop: + mov eax, ds:[si].Z + imul [Light.Z] + mov ebx, eax + mov ecx, edx + mov eax, ds:[si].Y + imul [Light.Y] + add ebx, eax + adc ecx, edx + mov eax, ds:[si].X + imul [Light.X] + add eax, ebx + adc edx, ecx ; EDX:EAX = fixed 32:32 intensity + add dx, [AmbientLight] + test dx, dx + jg @@1 + xor dx, dx ; Return 0 for no light +@@1: + mov es:[di], dx + inc di + inc di + add si, SIZE TPOINT + dec [Count] + jnz @@Loop + + ASSUME fs:NOTHING + ret +tdTransformLight ENDP + +;----------------------------------------------------------- +; +; Returns the light value given the normal to a surface. +; +; Input: +; Normal = pointer to TPOINT surface normal vector +; Output: +; AX = light intensity (>=0) +; Notes: +; the normal is rotated according to the current setting. +; +tdGetSurfaceLight PROC PASCAL FAR + ARG Normal:DWORD + USES ds, esi, es, di + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + les di, [Normal] + +; Transform Z coordinate + mov eax, es:[di].X + imul [ZRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, es:[di].Y + imul [ZRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, es:[di].Z + imul [ZRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + imul [Light.Z] + shrd eax, edx, 16 + mov esi, eax + +; Transform X coordinate + mov eax, es:[di].X + imul [XRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, es:[di].Y + imul [XRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, es:[di].Z + imul [XRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + imul [Light.X] + shrd eax, edx, 16 + add esi, eax + +; Transform Y coordinate + mov eax, es:[di].X + imul [YRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, es:[di].Y + imul [YRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, es:[di].Z + imul [YRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + imul [Light.X] + shrd eax, edx, 16 + add eax, esi + shr eax, 16 + +; Add ambient light + add ax, [AmbientLight] + test ax, ax + jge @@Exit + xor ax, ax + +@@Exit: + ret +tdGetSurfaceLight ENDP + +;----------------------------------------------------------- +; +; Rotates an array of TPOINT. +; +; Input: +; Source = pointer to source array of TPOINT +; Dest = pointer to destination array of TPOINT +; Count = number of entries to transform +; Output: +; none +; +tdRotate PROC PASCAL FAR + ARG Source:DWORD, \ + Dest:DWORD, \ + Count:WORD + USES ds, si, es, di, fs + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + lfs si, [Source] + les di, [Dest] + +@@Loop: +; Transform Z coordinate + mov eax, fs:[si].X + imul [ZRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [ZRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [ZRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + mov es:[di].Z, eax + +; Transform X coordinate + mov eax, fs:[si].X + imul [XRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [XRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [XRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + mov es:[di].X, eax + +; Transform Y coordinate + mov eax, fs:[si].X + imul [YRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [YRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [YRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + mov es:[di].Y, eax + + add si, SIZE TPOINT + add di, SIZE TPOINT + dec [Count] + jnz @@Loop + + ret +tdRotate ENDP + +tdFixedMul PROC PASCAL FAR + ARG F1:DWORD, \ + F2:DWORD + + mov eax, [F1] + imul [F2] + shr eax, 16 + + ret +tdFixedMul ENDP + +;----------------------------------------------------------- +; +; Returns in EAX the square root of EDX:EAX. +; +subSqrt PROC NEAR + push esi + push edi + + add eax, eax + adc edx, 0 + mov eax, edx ; Just discard the low bits + + mov esi, eax + xor edi, edi + shld edi, esi, 16 + shl esi, 16 +@@Loop: + mov ebx, eax + mul eax + add eax, esi + adc edx, edi + shrd eax, edx, 1 + shr edx, 1 + div ebx + cmp eax, ebx + jne @@Loop + +; Adjust EAX + shl eax, 8 + + pop edi + pop esi + ret +subSqrt ENDP + +;----------------------------------------------------------- +; +; Finds the unitary normal to a given surface. +; +; Input: +; Dest = pointer to TPOINT (vector) result +; P1, P2, P3 = pointer to TPOINT points on surface +; Output: +; none +; Notes: +; the normal is given by the cross-product between (P3-P1) and +; (P2-P1), so its orientation depends on the parameters order. +; +tdGetNormal PROC PASCAL FAR + ARG Dest:DWORD, \ + P1:DWORD, \ + P2:DWORD, \ + P3:DWORD + LOCAL V1:TPOINT, \ + V2:TPOINT, \ + N:TPOINT + USES ds, si, es, di + +; Get vector V1 + lds si, [P1] + les di, [P3] + mov eax, es:[di].X + sub eax, ds:[si].X + mov [V1.X], eax + mov eax, es:[di].Y + sub eax, ds:[si].Y + mov [V1.Y], eax + mov eax, es:[di].Z + sub eax, ds:[si].Z + mov [V1.Z], eax + +; Get vector V2 + les di, [P2] + mov eax, es:[di].X + sub eax, ds:[si].X + mov [V2.X], eax + mov eax, es:[di].Y + sub eax, ds:[si].Y + mov [V2.Y], eax + mov eax, es:[di].Z + sub eax, ds:[si].Z + mov [V2.Z], eax + +; Get normal vector (V1 x V2) + mov eax, [V1.Z] + imul [V2.Y] + mov ebx, eax + mov ecx, edx + mov eax, [V1.Y] + imul [V2.Z] + sub eax, ebx + sbb edx, ecx + shrd eax, edx, 16 + mov [N.X], eax + + mov eax, [V1.X] + imul [V2.Z] + mov ebx, eax + mov ecx, edx + mov eax, [V1.Z] + imul [V2.X] + sub eax, ebx + sbb edx, ecx + shrd eax, edx, 16 + mov [N.Y], eax + + mov eax, [V1.Y] + imul [V2.X] + mov ebx, eax + mov ecx, edx + mov eax, [V1.X] + imul [V2.Y] + sub eax, ebx + sbb edx, ecx + shrd eax, edx, 16 + mov [N.Z], eax + +; Get normal length + mov eax, [N.X] + imul eax + mov ebx, eax + mov ecx, edx + mov eax, [N.Y] + imul eax + add ebx, eax + adc ecx, edx + mov eax, [N.Z] + imul eax + add eax, ebx + adc edx, ecx ; EDX:EAX = N.X*N.X + N.Y*N.Y + N.Z*N.Z + call subSqrt ; EAX = normal length + mov ebx, eax + +; Adjust vector and save it + les di, [Dest] + mov eax, [N.X] + cdq + shld edx, eax, 16 + shl eax, 16 + idiv ebx + mov es:[di].X, eax + mov eax, [N.Y] + cdq + shld edx, eax, 16 + shl eax, 16 + idiv ebx + mov es:[di].Y, eax + mov eax, [N.Z] + cdq + shld edx, eax, 16 + shl eax, 16 + idiv ebx + mov es:[di].Z, eax + + ret +tdGetNormal ENDP + +TPOLY STRUC + Vtx DW 4 DUP(?) +TPOLY ENDS + +;----------------------------------------------------------- +; +; Performs surface removal on an array of polygons. +; +; Input: +; Poly = pointer to an array of TPOLY +; Vertex = pointer to an array of TPOINT +; Dest = pointer to an array of integer +; Count = number of polygons to check +; Step = size of TPOLY structure +; Output: +; if the n-th polygon is invisible the n-th entry of the +; Dest array is set to -1, other entries are not modified +; (so it's possible to use the Light array for Dest, because +; the light intensity is always >= 0) +; +tdBackPlaneCull PROC PASCAL FAR + ARG Step:WORD, \ + Poly:DWORD, \ + Vertex:DWORD, \ + Dest:DWORD, \ + Count:WORD + USES ds, si, es, di, fs + ASSUME ds:NOTHING + + mov ds, WORD PTR Vertex[2] + les di, [Poly] + mov fs, WORD PTR Dest[2] + +@@Loop: + mov ax, es:[di].Vtx[2] ; Index of 2nd vertex + shl ax, 2 + mov bx, ax + shl ax, 1 + add bx, ax ; BX = index*SIZE TPOINT + add bx, WORD PTR [Vertex] ; BX = offset of 2nd vertex + mov ax, es:[di].Vtx[4] ; Index of 3rd vertex + shl ax, 2 + mov si, ax + shl ax, 1 + add si, ax + add si, WORD PTR [Vertex] ; SI = offset of 3rd vertex + mov ecx, ds:[si].X + sub ecx, ds:[bx].X ; ECX = V3.X-V2.X + mov edx, ds:[si].Y + sub edx, ds:[bx].Y ; EDX = V3.Y-V2.Y + mov ax, es:[di].Vtx[0] ; Index of 1st vertex + shl ax, 2 + mov si, ax + shl ax, 1 + add si, ax + add si, WORD PTR [Vertex] ; SI = offset of 1st vertex + mov eax, ds:[si].X + sub eax, ds:[bx].X ; EAX = V1.X-V2.X + mov esi, ds:[si].Y + sub esi, ds:[bx].Y ; ESI = V1.Y-V2.Y + imul edx + mov ebx, eax + xchg ecx, edx ; ECX:EBX = (V1.X-V2.X)*(V3.Y-V2.Y) + mov eax, esi + imul edx ; EDX:EAX = (V1.Y-V2.Y)*(V3.X-V2.X) + sub eax, ebx + sbb edx, ecx + jl @@Next ; Polygon is visible + mov bx, WORD PTR [Dest] ; FS:BX -> current Dest entry + mov WORD PTR fs:[bx], -1 ; Remove polygon +@@Next: + add WORD PTR [Dest], 2 ; Next entry for dest + add di, [Step] ; Next polygon + dec [Count] + jnz @@Loop + + ret +tdBackPlaneCull ENDP + +MATH_TEXT ENDS +END diff --git a/16/xw_/modex/THREED.H b/16/xw_/modex/THREED.H new file mode 100755 index 00000000..b993ef86 --- /dev/null +++ b/16/xw_/modex/THREED.H @@ -0,0 +1,32 @@ +typedef struct { + long x, y, z; +} TVECTOR; + +#define PVECTOR TVECTOR far * + +#define TPOINT TVECTOR +#define PPOINT PVECTOR + +#define VPTR void far * + +#ifdef __cplusplus +extern "C" { +#endif + +long far pascal tdFixedMul( long, long ); +int far pascal tdGetSurfaceLight( PPOINT ); +long far pascal tdTransformToImage( VPTR, VPTR, short, short, short ); + +void far pascal tdBackPlaneCull( VPTR, VPTR, VPTR, short, short ); +void far pascal tdGetNormal( VPTR, PPOINT, PPOINT, PPOINT ); +void far pascal tdRotate( VPTR, VPTR, short ); +void far pascal tdSetLight( PVECTOR ); +void far pascal tdSetRotation( short, short, short ); +void far pascal tdSetTranslation( PVECTOR ); +void far pascal tdSetPerspective( long, long, long ); +void far pascal tdTransform( VPTR, VPTR, short ); +void far pascal tdTransformLight( VPTR, VPTR, short ); + +#ifdef __cplusplus +} +#endif diff --git a/16/xw_/modex/THREED.PAS b/16/xw_/modex/THREED.PAS new file mode 100755 index 00000000..8b712c9d --- /dev/null +++ b/16/xw_/modex/THREED.PAS @@ -0,0 +1,40 @@ +unit ThreeD; +interface + +type + TVector = record + X, Y, Z : longint; + end; + TPoint = TVector; + +function tdFixedMul( F1, F2: longint ): longint; +function tdGetSurfaceLight( var Normal: TPoint ): integer; +function tdTransformToImage( var Source, Dest; Count, DeltaX, DeltaY: integer ): longint; + +procedure tdBackPlaneCull( var Poly, Vertex, Dest; Count, Step: word ); +procedure tdGetNormal( var Dest, P1, P2, P3: TVector ); +procedure tdRotate( var Source, Dest; Count: word ); +procedure tdSetLight( var Light: TVector ); +procedure tdSetRotation( RX, RY, RZ: word ); +procedure tdSetTranslation( var TV: TVector ); +procedure tdSetPerspective( PD, XF, YF: longint ); +procedure tdTransform( var Source, Dest; Count: word ); +procedure tdTransformLight( var Source, Dest; Count: word ); + +implementation + +function tdGetSurfaceLight; external; +procedure tdSetRotation( RX, RY, RZ: word ); external; +procedure tdGetNormal; external; +procedure tdSetTranslation( var TV: TVector ); external; +procedure tdTransform( var Source, Dest; Count: word ); external; +procedure tdRotate; external; +function tdTransformToImage; external; +procedure tdSetLight( var Light: TVector ); external; +procedure tdSetPerspective; external; +procedure tdTransformLight; external; +function tdFixedMul( F1, F2: longint ): longint; external; +procedure tdBackPlaneCull; external; +{$L THREED} + +end. diff --git a/16/xw_/modex/demo01.c b/16/xw_/modex/demo01.c new file mode 100755 index 00000000..98086b62 --- /dev/null +++ b/16/xw_/modex/demo01.c @@ -0,0 +1,133 @@ +/* + DEMO01 - Sprites, page flipping and palette rotation + Copyright (c) 1994 Alessandro Scotti +*/ +#include ../../x/ + +#DEFINE MAX_SPRITE 100 + +/* Sprite structure */ +typedef struct { + int X, Y; /* Sprite coordinates */ + int DX,DY; /* Deltas for sprite movement */ + int W, H; /* Sprite width and height */ + unsigned char Image[16,16]; /* Sprite image data */ +} TSprite; + +/* RGB color structure */ +typedef struct { + R, G, B: byte; +} TRgb; +var + S : array[ 1..MAX_SPRITE ] of TSprite; /* An array of sprites */ + Palette: array[ byte ] of TRgb; /* Palette */ + Page : word; /* Page offset */ + I : word; + +/* Initializes a sprite structure */ +procedure sxInit( var S: TSprite ); +var + I: word; +begin + S.X = Random( 320 ); /* Initialize position with random values */ + S.Y = Random( 240 ); + S.DX = Random( 7 )-3; /* Initialize speed with random values */ + S.DY = Random( 7 )-3; + S.W = 16; /* Size is fixed in this program */ + S.H = 16; + /* The image is a square with a hole inside */ + FillChar( S.Image, SizeOf(S.Image), Random(15)+1 ); + for I=5 to 12 do FillChar( S.Image[ I, 5 ], 8, 0 ); +} + +/* Moves a sprite */ +procedure sxMove( var S: TSprite ); +begin + Inc( S.X, S.DX ); /* Get new position */ + Inc( S.Y, S.DY ); + /* Check sprite position, change delta if needed */ + if( S.X > 320 ) then begin + S.X = 320; + S.DX = -S.DX; + } + if( S.X < -16 ) then begin + S.X = -16; + S.DX = -S.DX; + } + if( S.Y > 240 ) then begin + S.Y = 240; + S.DY = -S.DY; + } + if( S.Y < -16 ) then begin + S.Y = -16; + S.DY = -S.DY; + } + /* Draw the sprite, note the Page offset added to the */ + /* Y coordinate of the image */ + mxPutImage( @S.Image, S.X, Page+S.Y, S.W, S.H, OP_TRANS ); +} + +void main() +{ + int i; + /* Initialize library */ + mxInit(); + + /* Enter graphics mode */ + mxSetMode( MX_320x240 ); + + /* Print initialization message */ + mxSetTextColor( 15, OP_TRANS ); + mxOutStr( 4, 4, 'Initializing...' ); + + /* Initialize sprites */ + for(i=1;i<=MAX_SPRITE;i++) + sxInit( S[i] ); + + /* Draw background */ + for(i=1;i<=192;i++) + { + mxCircle( 160, 480+120, I, I+63 ); + mxCircle( 161, 480+120, I, I+63 ); + } + + /* Compute and set palette */ + for(i=1;i<= 192;Palette[i+63]) + { + short R = 0; + short G = 0; + short B = 0; + if( i < 64 ) + R = i shr 1+31 + else if( i < 128 ) + G = (i-64) shr 1+31 + else + B = (i-128) shr 1+31; + } + mxSetPalette( @Palette[64], 64, 192 ); + + /* Main loop */ + short Page = 240; + while(!kbhit()) + { + /* Set clip region to current page */ + mxSetClipRegion( 0, Page, 320, 240 ); + mxSetClip( TRUE ); + /* Restore background */ + mxBitBlt( 0, 480, 320, 240, 0, Page ); + /* Draw sprites */ + for(i=1; i <= MAX_SPRITE; sxMove( S[i] )); + /* Print message */ + mxOutStr( 4, Page+4, 'Some sprites moving...' ); + /* Flip page */ + mxStartLine( Page ); + Page = 240-Page; + /* Animate palette */ + mxSetPalette( @Palette[64], 64, 192 ); + mxRotatePalette( @Palette[64], 192, 3 ); + } + + mxSetMode( MX_TEXT ); + mxTerm; + +} diff --git a/16/xw_/mxbb.asm b/16/xw_/mxbb.asm new file mode 100755 index 00000000..5598cd10 --- /dev/null +++ b/16/xw_/mxbb.asm @@ -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 index 00000000..efe64f3f --- /dev/null +++ b/16/xw_/mxcc.asm @@ -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 index 00000000..c29a48ec --- /dev/null +++ b/16/xw_/mxcg.asm @@ -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 index 00000000..549bc8ce --- /dev/null +++ b/16/xw_/mxcl.asm @@ -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 index 00000000..826e065a --- /dev/null +++ b/16/xw_/mxcr.asm @@ -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 index 00000000..e69de29b diff --git a/16/xw_/mxfb.asm b/16/xw_/mxfb.asm new file mode 100755 index 00000000..e20f1dc9 --- /dev/null +++ b/16/xw_/mxfb.asm @@ -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 index 00000000..7ff26176 --- /dev/null +++ b/16/xw_/mxfp.asm @@ -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 index 00000000..2f297632 --- /dev/null +++ b/16/xw_/mxgc.asm @@ -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 index 00000000..0570d498 --- /dev/null +++ b/16/xw_/mxgi.asm @@ -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 index 00000000..8ca07a17 --- /dev/null +++ b/16/xw_/mxgm.asm @@ -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 index 00000000..14dfc17a --- /dev/null +++ b/16/xw_/mxgp.asm @@ -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 index 00000000..44b30ddb --- /dev/null +++ b/16/xw_/mxgv.asm @@ -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 index 00000000..f664632b --- /dev/null +++ b/16/xw_/mxhl.asm @@ -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 index 00000000..25bce3c3 --- /dev/null +++ b/16/xw_/mxit.asm @@ -0,0 +1,98 @@ +;----------------------------------------------------------- +; +; MXIT.ASM - Initialization/termination functions +; Copyright (c) 1993,1994 by Alessandro Scotti +; +;----------------------------------------------------------- +;WARN PRO +INCLUDE MODEX.DEF + +PUBLIC mxInit +PUBLIC mxTerm + +PUBLIC mx_VideoSegment +PUBLIC mx_CodeSegment + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +DB 'MODEX library - Copyright (c) 1992-1994 Alessandro Scotti' + +mx_VideoSegment DW 0A000h +mx_CodeSegment DW SEG MX_TEXT + +;----------------------------------------------------------- +; +; Initialization. +; +; Input: +; none +; Output: +; AX = 0 on success +; +mxInit PROC FAR + LOCAL Result:WORD, \ + VideoSeg:WORD, \ + CStoDSalias:WORD = AUTO_SIZE + ASSUME ds:NOTHING + .enter AUTO_SIZE + .push ds, si, es, di + + mov [Result], -1 ; Assume an error + mov [VideoSeg], 0A000h ; Real mode video segment + mov [CStoDSalias], cs ; Real mode data alias for CS + +; Check if running in protected mode under DPMI + mov ax, 1686h + int 2Fh + or ax, ax + jnz @@1 ; DPMI not found, continue in real mode + +; Get a data alias for CS + mov ax, 000Ah ; DMPI: create data alias + mov bx, cs + int 31h + jc @@Exit ; Exit if service failed + mov [CStoDSalias], ax ; Save data alias for CS +; Get a protected-mode selector for the video segment + mov ax, 0002h + mov bx, 0A000h ; Real mode segment of video + int 31h ; DPMI: get segment selector + jc @@Exit ; Exit if service failed + mov [VideoSeg], ax ; Save protected mode video selector + +; Initialize variables +@@1: + mov ds, [CStoDSalias] + ASSUME ds:MX_TEXT + mov [mx_CodeSegment], ds + mov ax, [VideoSeg] + mov [mx_VideoSegment], ax + +; Don't bother with VGA check for now... + + mov [Result], 0 + +@@Exit: + mov ax, [Result] + .pop ds, si, es, di +; .leave +mxInit ENDP + +;----------------------------------------------------------- +; +; Termination. +; +; Input: +; none +; Output: +; always 0. +; +mxTerm PROC FAR + ASSUME ds:NOTHING + xor ax, ax + ret +mxTerm ENDP + +MX_TEXT ENDS +END diff --git a/16/xw_/mxll.asm b/16/xw_/mxll.asm new file mode 100755 index 00000000..f08de8d4 --- /dev/null +++ b/16/xw_/mxll.asm @@ -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 index 00000000..77d2b64b --- /dev/null +++ b/16/xw_/mxln.asm @@ -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 index 00000000..f7e6fde4 --- /dev/null +++ b/16/xw_/mxot.asm @@ -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 index 00000000..e431b138 --- /dev/null +++ b/16/xw_/mxot_.asm @@ -0,0 +1,333 @@ +;----------------------------------------------------------- +; +; MXOT.ASM - Text functions +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +;WARN PRO +;NOWARN RES ; We use the reserved name 'WIDTH' +INCLUDE MODEX.DEF + +PUBLIC mxOutChar +PUBLIC mxOutText +PUBLIC mxSetFont +PUBLIC mxSetTextColor +PUBLIC mxGetTextStep +PUBLIC mxSetTextStep + +MAX_WIDTH EQU 16 ; Must be <= 16 +MAX_HEIGHT EQU 32 + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_CodeSegment : WORD +EXTRN mxPutImage : FAR + +; 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 OP_MOVE ; Raster op +mx_DeltaX DW 8 ; Horizontal step +mx_DeltaY DW 0 ; Vertical step + +;----------------------------------------------------------- +; +; Sets the current font. +; +; Input: +; Font = pointer to font data +; Width = width of font character in pixels +; Height = height of font character in pixels +; Output: +; AX = 0 on success, else invalid parameters +; +; Note: when the high word of Font (i.e. the segment) is zero, the low +; word is used to select one of the system fonts. +; +mxSetFont PROC FAR + push bp + mov bp,sp + sub sp,0 + push ds + .enter 0 + .push ds + + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, WORD PTR Font[2] ; Get font segment + test ax, ax ; Null segment? + jnz @@UserFont ; No, install user font + +; Install system font + mov ax, WORD PTR Font[0] ; Get font number + cmp ax, MX_MAXSYSFONT ; Check range + jb @@SystemFont + xor ax, ax ; Out of range, use default font +@@SystemFont: + shl ax, 1 + shl ax, 1 + mov bx, ax + mov ax, tbl_SystemFont[bx] ; Get font offset + mov WORD PTR mx_FontPtr[0], ax + mov WORD PTR mx_FontPtr[2], cs + mov al, BYTE PTR tbl_SystemFont[bx+2] + xor ah, ah + mov [mx_FontWidth], ax + mov [mx_DeltaX], ax + mov dl, BYTE PTR tbl_SystemFont[bx+3] + xor dh, dh + mov [mx_FontHeight], dx + mul dx + mov [mx_FontCharSize], ax + mov [mx_DeltaX], ax + xor ax, ax + mov [mx_DeltaY], ax + jmp @@Exit + +; Install user font +@@UserFont: + mov ax, -1 ; Assume an error + mov bx, [bp+8] + cmp bx, MAX_WIDTH + ja @@Exit ; Invalid character width + mov dx, [bp+4] + cmp dx, MAX_HEIGHT + ja @@Exit ; Invalid character height + mov [mx_FontWidth], bx + mov [mx_FontHeight], dx + mov ax, bx + add ax, 7 + shr ax, 1 + shr ax, 1 + shr ax, 1 + mul dx + mov [mx_FontCharSize], ax + mov ax, WORD PTR Font[0] + mov WORD PTR mx_FontPtr[0], ax + mov ax, WORD PTR Font[2] + mov WORD PTR mx_FontPtr[2], ax + xor ax, ax + +@@Exit: + .pop ds + ASSUME ds:NOTHING + ;.leave ARG_SIZE +mxSetFont ENDP + +;----------------------------------------------------------- +; +; Sets the text color and raster op. +; +; Input: +; Color = text color (foreground + background*256) +; Op = raster op +; Output: +; none +; +mxSetTextColor PROC FAR + ARG Op:WORD, \ + Color:WORD = ARG_SIZE + .enter 0 + .push ds + + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, [Color] + mov [mx_FontColor], ax + mov ax, [Op] + mov [mx_FontOp], ax + + xor ax, ax + .pop ds + ASSUME ds:NOTHING + .leave ARG_SIZE +mxSetTextColor ENDP + +;----------------------------------------------------------- +; +; Writes a character using the current font and attributes. +; +; Input: +; X, Y = video coordinates +; C = character to print +; Output: +; none +; +mxOutChar PROC FAR + ARG C:BYTE:2, \ + Y:WORD, \ + X:WORD = ARG_SIZE + LOCAL Image:BYTE:MAX_WIDTH*MAX_HEIGHT, \ + Count:WORD = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, es, di + ASSUME ds:NOTHING + +; Gets the pointer to font data for the selected character + lds si, DWORD PTR [mx_FontPtr] + mov al, [C] + xor ah, ah + mul [mx_FontCharSize] ; Offset into font + add si, ax ; DS:SI -> font data for character + +; Converts font data into a 256-color linear image + mov ax, ss + mov es, ax + lea di, [Image] + mov dx, [mx_FontColor] + mov ax, [mx_FontHeight] + mov [Count], ax +@@HeightLoop: + mov cx, [mx_FontWidth] + mov bh, ds:[si] + inc si ; Get a byte from font data + cmp cx, 8 + jbe @@WidthLoop ; Ok for width <= 8 + mov bl, ds:[si] ; Get another byte + inc si +@@WidthLoop: + mov al, dl ; Assume foreground color + shl bx, 1 ; Is font bit set? + jc @@1 ; Yes, foreground is just great + mov al, dh ; Get background color +@@1: + mov es:[di], al ; Put pixel into image + inc di + dec cx + jnz @@WidthLoop + dec [Count] + jnz @@HeightLoop + +; Now pass image to mx_PutImage + lea ax, [Image] + push es + push ax ; Pointer to image + push [X] + push [Y] ; Image coordinates + push [mx_FontWidth] + push [mx_FontHeight] ; Image size + push [mx_FontOp] ; Raster op + call mxPutImage ; Write character + + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxOutChar ENDP + +;----------------------------------------------------------- +; +; Writes a string at the coordinates specified. +; +; Input: +; X, Y = text coordinates +; S = pointer to ASCIIZ string +; Output: +; none +; +mxOutText PROC FAR + ARG S:DWORD, \ + Y:WORD, \ + X:WORD = ARG_SIZE + .enter 0 + .push ds, si + ASSUME ds:NOTHING + + lds si, [S] +@@Loop: + mov al, ds:[si] + test al, al ; End of string? + jz @@Exit ; Yes, exit + inc si + push [X] ; Display character + push [Y] + push ax + call mxOutChar + mov ax, [mx_DeltaX] + add [X], ax ; Bump X coordinate + mov ax, [mx_DeltaY] + add [Y], ax ; Bump Y coordinate + dec [Count] + jnz @@Loop + +@@Exit: + xor ax, ax + .pop ds, si + .leave ARG_SIZE + ret +mxOutText ENDP + +;----------------------------------------------------------- +; +; Sets the distance between characters. +; +; Input: +; DeltaX = horizontal distance in pixels +; DeltaY = vertical distance in pixels +; Output: +; none +; +; Note: this function may be used to set the text direction. +; +mxSetTextStep PROC FAR + ARG DeltaY:WORD, \ + DeltaX:WORD = ARG_SIZE + .enter 0 + .push ds + + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, [DeltaX] + mov [mx_DeltaX], ax + mov ax, [DeltaY] + mov [mx_DeltaY], ax + + .pop ds + .leave ARG_SIZE +mxSetTextStep ENDP + +;----------------------------------------------------------- +; +; Gets the current distance between characters. +; +; Input: +; DeltaX = pointer to horizontal distance in pixels (integer) +; DeltaY = pointer to vertical distance in pixels (integer) +; Output: +; none +; +mxGetTextStep PROC FAR + ARG DeltaY:DWORD, \ + DeltaX:DWORD = ARG_SIZE + .enter 0 + .push ds, si + ASSUME ds:NOTHING + + mov ax, [mx_DeltaX] + lds si, [DeltaX] + mov ds:[si], ax + mov ax, [mx_DeltaY] + lds si, [DeltaY] + mov ds:[si], ax + + .pop ds, si + .leave ARG_SIZE +mxGetTextStep ENDP + +MX_TEXT ENDS +END diff --git a/16/xw_/mxpb.asm b/16/xw_/mxpb.asm new file mode 100755 index 00000000..b8536fd6 --- /dev/null +++ b/16/xw_/mxpb.asm @@ -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 index 00000000..f33158b8 --- /dev/null +++ b/16/xw_/mxpf.asm @@ -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 index 00000000..d252576f --- /dev/null +++ b/16/xw_/mxpg.asm @@ -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 index 00000000..2631d82f --- /dev/null +++ b/16/xw_/mxpi.asm @@ -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 index 00000000..e4f20b10 --- /dev/null +++ b/16/xw_/mxpn.asm @@ -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 index 00000000..42f7a6f0 --- /dev/null +++ b/16/xw_/mxpp.asm @@ -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 index 00000000..a71b4a0e --- /dev/null +++ b/16/xw_/mxra.asm @@ -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 index 00000000..03239eff --- /dev/null +++ b/16/xw_/mxrp.asm @@ -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 index 00000000..642d2dd7 --- /dev/null +++ b/16/xw_/mxsa.asm @@ -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 index 00000000..7d8bd47b --- /dev/null +++ b/16/xw_/mxsc.asm @@ -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 index 00000000..c9223532 --- /dev/null +++ b/16/xw_/mxsi.asm @@ -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 index 00000000..109ce3ba --- /dev/null +++ b/16/xw_/mxsl.asm @@ -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 index 00000000..96e746d3 --- /dev/null +++ b/16/xw_/mxsm.asm @@ -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 index 00000000..3385a6cf --- /dev/null +++ b/16/xw_/mxsp.asm @@ -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 index 00000000..558584c3 --- /dev/null +++ b/16/xw_/mxss.asm @@ -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 index 00000000..3f791b41 --- /dev/null +++ b/16/xw_/mxtl.asm @@ -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 index 00000000..c4728ff5 --- /dev/null +++ b/16/xw_/mxvs.asm @@ -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 index 00000000..c0d19aa2 --- /dev/null +++ b/16/xw_/mxwd.asm @@ -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 index 00000000..7dc66acc --- /dev/null +++ b/16/xw_/mxwm.asm @@ -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 index 00000000..e03c4040 --- /dev/null +++ b/16/xw_/mxwp.asm @@ -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 index 00000000..0d228d8b --- /dev/null +++ b/16/xw_/mxwr.asm @@ -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 index 00000000..306e8b9a --- /dev/null +++ b/16/xw_/readme.txt @@ -0,0 +1,8 @@ +ModeX - A graphical library for DOS programs +Copyright (c) 1993-1994 Alessandro Scotti +http://www.ascotti.org/ + +Please look at the above site in the "Art of..." and +then in the "Old programs" section for more information. + + diff --git a/16/xw_/xw.bat b/16/xw_/xw.bat new file mode 100755 index 00000000..1fd24399 --- /dev/null +++ b/16/xw_/xw.bat @@ -0,0 +1,39 @@ +@echo off +wdis -a MXBB.OBJ > mxbb.asm +wdis -a MXCC.OBJ > mxcc.asm +wdis -a MXCG.OBJ > mxcg.asm +wdis -a MXCL.OBJ > mxcl.asm +wdis -a MXCR.OBJ > mxcl.asm +wdis -a MXFB.OBJ > mxfb.asm +wdis -a MXFP.OBJ > mxfp.asm +wdis -a MXGC.OBJ > mxgc.asm +wdis -a MXGI.OBJ > mxgi.asm +wdis -a MXGM.OBJ > mxgm.asm +wdis -a MXGP.OBJ > mxgp.asm +wdis -a MXGV.OBJ > mxgv.asm +wdis -a MXHL.OBJ > mxhl.asm +wdis -a MXIT.OBJ > mxit.asm +wdis -a MXLL.OBJ > mxll.asm +wdis -a MXLN.OBJ > mxln.asm +wdis -a MXOT.OBJ > mxot.asm +wdis -a MXPB.OBJ > mxpb.asm +wdis -a MXPF.OBJ > mxpf.asm +wdis -a MXPG.OBJ > mxpg.asm +wdis -a MXPI.OBJ > mxpi.asm +wdis -a MXPN.OBJ > mxpn.asm +wdis -a MXPP.OBJ > mxpp.asm +wdis -a MXRA.OBJ > mxra.asm +wdis -a MXRP.OBJ > mxrp.asm +wdis -a MXSA.OBJ > mxsa.asm +wdis -a MXSC.OBJ > mxsc.asm +wdis -a MXSI.OBJ > mxsi.asm +wdis -a MXSL.OBJ > mxsl.asm +wdis -a MXSM.OBJ > mxsm.asm +wdis -a MXSP.OBJ > mxsp.asm +wdis -a MXSS.OBJ > mxss.asm +wdis -a MXTL.OBJ > mxtl.asm +wdis -a MXVS.OBJ > mxvs.asm +wdis -a MXWD.OBJ > mxwd.asm +wdis -a MXWM.OBJ > mxwm.asm +wdis -a MXWP.OBJ > mxwp.asm +wdis -a MXWR.OBJ > mxwr.asm diff --git a/16/xw__/default.fnt b/16/xw__/default.fnt new file mode 100755 index 00000000..12eb22cb --- /dev/null +++ b/16/xw__/default.fnt @@ -0,0 +1,260 @@ +; +; MODEX library default font +; Copyright (c) 1993-1994 by Alessandro Scotti +; + DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; #0 + DB 07Eh, 081h, 0A5h, 081h, 0A5h, 099h, 081h, 07Eh ; #1 + DB 07Eh, 0FFh, 0DBh, 0FFh, 0DBh, 0E7h, 0FFh, 07Eh ; #2 + DB 06Ch, 0FEh, 0FEh, 0FEh, 07Ch, 038h, 010h, 000h ; #3 + DB 010h, 038h, 07Ch, 0FEh, 07Ch, 038h, 010h, 000h ; #4 + DB 010h, 038h, 010h, 054h, 0FEh, 054h, 010h, 0FEh ; #5 + DB 010h, 038h, 07Ch, 0FEh, 0FEh, 07Ch, 010h, 0FEh ; #6 + DB 000h, 018h, 03Ch, 07Eh, 07Eh, 03Ch, 018h, 000h ; #7 + DB 0FFh, 0E7h, 0C3h, 081h, 081h, 0C3h, 0E7h, 0FFh ; #8 + DB 000h, 03Ch, 066h, 042h, 042h, 066h, 03Ch, 000h ; #9 + DB 0FFh, 0C3h, 099h, 0BDh, 0BDh, 099h, 0C3h, 0FFh ; #10 + DB 007h, 003h, 005h, 078h, 084h, 084h, 084h, 078h ; #11 + DB 07Ch, 082h, 082h, 082h, 07Ch, 010h, 038h, 010h ; #12 + DB 01Ch, 010h, 01Ch, 010h, 010h, 010h, 030h, 030h ; #13 + DB 03Eh, 022h, 03Eh, 022h, 022h, 026h, 066h, 060h ; #14 + DB 099h, 05Ah, 03Ch, 0E7h, 0E7h, 03Ch, 05Ah, 099h ; #15 + DB 000h, 010h, 030h, 070h, 0F0h, 070h, 030h, 010h ; #16 + DB 000h, 080h, 0C0h, 0E0h, 0F0h, 0E0h, 0C0h, 080h ; #17 + DB 010h, 038h, 054h, 010h, 010h, 054h, 038h, 010h ; #18 + DB 048h, 048h, 048h, 048h, 048h, 000h, 048h, 000h ; #19 + DB 07Eh, 092h, 092h, 072h, 012h, 012h, 012h, 000h ; #20 + DB 03Ch, 022h, 018h, 024h, 024h, 018h, 044h, 03Ch ; #21 + DB 000h, 000h, 000h, 000h, 000h, 03Eh, 03Eh, 000h ; #22 + DB 038h, 054h, 010h, 010h, 010h, 054h, 038h, 0FEh ; #23 + DB 000h, 010h, 038h, 054h, 010h, 010h, 010h, 000h ; #24 + DB 000h, 010h, 010h, 010h, 054h, 038h, 010h, 000h ; #25 + DB 000h, 008h, 004h, 0FEh, 004h, 008h, 000h, 000h ; #26 + DB 000h, 020h, 040h, 0FEh, 040h, 020h, 000h, 000h ; #27 + DB 000h, 000h, 080h, 080h, 080h, 0FCh, 000h, 000h ; #28 + DB 000h, 024h, 042h, 0FFh, 042h, 024h, 000h, 000h ; #29 + DB 000h, 000h, 010h, 038h, 07Ch, 0FEh, 000h, 000h ; #30 + DB 000h, 000h, 0FEh, 07Ch, 038h, 010h, 000h, 000h ; #31 + DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; + DB 010h, 010h, 010h, 010h, 010h, 000h, 010h, 000h ; ! + DB 000h, 024h, 024h, 000h, 000h, 000h, 000h, 000h ; " + DB 024h, 024h, 07Eh, 024h, 07Eh, 024h, 024h, 000h ; # + DB 038h, 054h, 050h, 038h, 014h, 054h, 038h, 010h ; $ + DB 000h, 002h, 044h, 008h, 010h, 020h, 042h, 000h ; % + DB 038h, 044h, 038h, 060h, 094h, 088h, 074h, 000h ; & + DB 020h, 020h, 040h, 000h, 000h, 000h, 000h, 000h ; ' + DB 010h, 020h, 040h, 040h, 040h, 020h, 010h, 000h ; ( + DB 040h, 020h, 010h, 010h, 010h, 020h, 040h, 000h ; ) + DB 000h, 024h, 018h, 07Eh, 018h, 024h, 000h, 000h ; * + DB 000h, 010h, 010h, 07Ch, 010h, 010h, 000h, 000h ; + + DB 000h, 000h, 000h, 000h, 000h, 010h, 010h, 020h ; , + DB 000h, 000h, 000h, 0FCh, 000h, 000h, 000h, 000h ; - + DB 000h, 000h, 000h, 000h, 000h, 000h, 010h, 000h ; . + DB 000h, 004h, 008h, 010h, 020h, 040h, 080h, 000h ; / + DB 07Ch, 0C6h, 08Ah, 092h, 0A2h, 0C6h, 07Ch, 000h ; 0 + DB 010h, 030h, 010h, 010h, 010h, 010h, 038h, 000h ; 1 + DB 078h, 084h, 004h, 018h, 060h, 080h, 0FCh, 000h ; 2 + DB 078h, 084h, 004h, 038h, 004h, 084h, 078h, 000h ; 3 + DB 01Ch, 024h, 044h, 084h, 0FEh, 004h, 00Eh, 000h ; 4 + DB 0FCh, 080h, 0F8h, 004h, 004h, 084h, 078h, 000h ; 5 + DB 078h, 084h, 080h, 0F8h, 084h, 084h, 078h, 000h ; 6 + DB 0FCh, 004h, 004h, 008h, 010h, 020h, 020h, 000h ; 7 + DB 078h, 084h, 084h, 078h, 084h, 084h, 078h, 000h ; 8 + DB 078h, 084h, 084h, 07Ch, 004h, 084h, 078h, 000h ; 9 + DB 000h, 000h, 010h, 000h, 000h, 000h, 010h, 000h ; : + DB 000h, 000h, 010h, 000h, 000h, 010h, 010h, 020h ; ; + DB 008h, 010h, 020h, 040h, 020h, 010h, 008h, 000h ; < + DB 000h, 000h, 0FCh, 000h, 000h, 0FCh, 000h, 000h ; = + DB 040h, 020h, 010h, 008h, 010h, 020h, 040h, 000h ; > + DB 078h, 084h, 004h, 008h, 010h, 000h, 010h, 000h ; ? + DB 07Ch, 082h, 0BAh, 0A6h, 0BEh, 080h, 07Ch, 000h ; @ + DB 078h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h ; A + DB 0F8h, 084h, 084h, 0F8h, 084h, 084h, 0F8h, 000h ; B + DB 078h, 084h, 080h, 080h, 080h, 084h, 078h, 000h ; C + DB 0F0h, 088h, 084h, 084h, 084h, 088h, 0F0h, 000h ; D + DB 0FCh, 080h, 080h, 0F0h, 080h, 080h, 0FCh, 000h ; E + DB 0FCh, 080h, 080h, 0F0h, 080h, 080h, 080h, 000h ; F + DB 078h, 084h, 080h, 09Ch, 084h, 084h, 078h, 000h ; G + DB 084h, 084h, 084h, 0FCh, 084h, 084h, 084h, 000h ; H + DB 038h, 010h, 010h, 010h, 010h, 010h, 038h, 000h ; I + DB 01Ch, 008h, 008h, 008h, 088h, 088h, 070h, 000h ; J + DB 084h, 088h, 090h, 0E0h, 090h, 088h, 084h, 000h ; K + DB 080h, 080h, 080h, 080h, 080h, 080h, 0FCh, 000h ; L + DB 0C6h, 0AAh, 092h, 082h, 082h, 082h, 082h, 000h ; M + DB 082h, 0C2h, 0A2h, 092h, 08Ah, 086h, 082h, 000h ; N + DB 078h, 084h, 084h, 084h, 084h, 084h, 078h, 000h ; O + DB 0F8h, 084h, 084h, 0F8h, 080h, 080h, 080h, 000h ; P + DB 078h, 084h, 084h, 084h, 094h, 088h, 076h, 000h ; Q + DB 0F8h, 084h, 084h, 0F8h, 090h, 088h, 084h, 000h ; R + DB 078h, 084h, 080h, 078h, 004h, 084h, 078h, 000h ; S + DB 0FEh, 010h, 010h, 010h, 010h, 010h, 010h, 000h ; T + DB 084h, 084h, 084h, 084h, 084h, 084h, 078h, 000h ; U + DB 084h, 084h, 084h, 084h, 084h, 048h, 030h, 000h ; V + DB 082h, 082h, 082h, 082h, 092h, 0AAh, 0C6h, 000h ; W + DB 082h, 044h, 028h, 010h, 028h, 044h, 082h, 000h ; X + DB 044h, 044h, 044h, 038h, 010h, 010h, 010h, 000h ; Y + DB 0FEh, 004h, 008h, 010h, 020h, 040h, 0FEh, 000h ; Z + DB 078h, 040h, 040h, 040h, 040h, 040h, 078h, 000h ; [ + DB 000h, 080h, 040h, 020h, 010h, 008h, 004h, 000h ; \ + DB 078h, 008h, 008h, 008h, 008h, 008h, 078h, 000h ; ] + DB 010h, 028h, 044h, 082h, 000h, 000h, 000h, 000h ; ^ + DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 0FFh ; _ + DB 020h, 020h, 010h, 000h, 000h, 000h, 000h, 000h ; ` + DB 000h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; a + DB 000h, 040h, 040h, 078h, 044h, 044h, 078h, 000h ; b + DB 000h, 000h, 03Ch, 040h, 040h, 040h, 03Ch, 000h ; c + DB 000h, 004h, 004h, 03Ch, 044h, 044h, 03Ch, 000h ; d + DB 000h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; e + DB 000h, 00Ch, 010h, 03Ch, 010h, 010h, 010h, 000h ; f + DB 000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 038h ; g + DB 000h, 040h, 040h, 078h, 044h, 044h, 044h, 000h ; h + DB 000h, 010h, 000h, 010h, 010h, 010h, 010h, 000h ; i + DB 000h, 004h, 000h, 004h, 004h, 004h, 044h, 038h ; j + DB 000h, 040h, 040h, 050h, 060h, 050h, 048h, 000h ; k + DB 000h, 030h, 010h, 010h, 010h, 010h, 010h, 000h ; l + DB 000h, 000h, 068h, 054h, 054h, 044h, 044h, 000h ; m + DB 000h, 000h, 078h, 044h, 044h, 044h, 044h, 000h ; n + DB 000h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; o + DB 000h, 000h, 078h, 044h, 044h, 078h, 040h, 040h ; p + DB 000h, 000h, 03Ch, 044h, 044h, 03Ch, 004h, 004h ; q + DB 000h, 000h, 05Ch, 060h, 040h, 040h, 040h, 000h ; r + DB 000h, 000h, 038h, 040h, 07Ch, 004h, 07Ch, 000h ; s + DB 000h, 010h, 038h, 010h, 010h, 010h, 018h, 000h ; t + DB 000h, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; u + DB 000h, 000h, 044h, 044h, 044h, 028h, 010h, 000h ; v + DB 000h, 000h, 044h, 044h, 054h, 054h, 06Ch, 000h ; w + DB 000h, 000h, 044h, 028h, 010h, 028h, 044h, 000h ; x + DB 000h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch ; y + DB 000h, 000h, 07Ch, 004h, 038h, 040h, 07Ch, 000h ; z + DB 000h, 008h, 010h, 010h, 030h, 010h, 010h, 008h ; { + DB 000h, 010h, 010h, 010h, 000h, 010h, 010h, 010h ; | + DB 000h, 020h, 010h, 010h, 018h, 010h, 010h, 020h ; } + DB 064h, 098h, 000h, 000h, 000h, 000h, 000h, 000h ; ~ + DB 000h, 010h, 028h, 044h, 082h, 082h, 0FEh, 000h ;  + DB 07Ch, 080h, 080h, 080h, 080h, 07Ch, 004h, 07Ch ; #128 + DB 000h, 028h, 000h, 044h, 044h, 044h, 038h, 000h ; #129 + DB 03Ch, 000h, 07Ch, 044h, 07Ch, 040h, 07Ch, 000h ; #130 + DB 07Eh, 081h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #131 + DB 024h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #132 + DB 078h, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #133 + DB 018h, 018h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #134 + DB 000h, 000h, 078h, 080h, 080h, 078h, 008h, 038h ; #135 + DB 07Ch, 082h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #136 + DB 048h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #137 + DB 078h, 000h, 038h, 044h, 07Ch, 040h, 03Ch, 000h ; #138 + DB 000h, 028h, 000h, 010h, 010h, 010h, 010h, 000h ; #139 + DB 010h, 028h, 000h, 010h, 010h, 010h, 010h, 000h ; #140 + DB 000h, 030h, 000h, 010h, 010h, 010h, 010h, 000h ; #141 + DB 048h, 000h, 078h, 084h, 0FCh, 084h, 084h, 000h ; #142 + DB 030h, 030h, 078h, 084h, 0FCh, 084h, 084h, 000h ; #143 + DB 038h, 000h, 0FCh, 080h, 0F0h, 080h, 0FCh, 000h ; #144 + DB 000h, 000h, 07Eh, 008h, 07Eh, 048h, 07Eh, 000h ; #145 + DB 07Eh, 090h, 090h, 0FCh, 090h, 090h, 09Eh, 000h ; #146 + DB 07Ch, 082h, 038h, 044h, 044h, 044h, 038h, 000h ; #147 + DB 028h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #148 + DB 070h, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #149 + DB 038h, 044h, 000h, 044h, 044h, 044h, 038h, 000h ; #150 + DB 070h, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; #151 + DB 028h, 000h, 044h, 044h, 044h, 03Ch, 004h, 07Ch ; #152 + DB 048h, 000h, 078h, 084h, 084h, 084h, 078h, 000h ; #153 + DB 048h, 000h, 084h, 084h, 084h, 084h, 078h, 000h ; #154 + DB 000h, 010h, 038h, 040h, 040h, 040h, 038h, 010h ; #155 + DB 038h, 044h, 040h, 0E0h, 040h, 040h, 082h, 0FCh ; #156 + DB 044h, 07Ch, 010h, 07Ch, 010h, 07Ch, 010h, 000h ; #157 + DB 0F0h, 088h, 08Ah, 0F7h, 082h, 082h, 082h, 000h ; #158 + DB 00Ch, 012h, 010h, 018h, 030h, 010h, 090h, 060h ; #159 + DB 03Ch, 000h, 038h, 004h, 03Ch, 044h, 07Ch, 000h ; #160 + DB 000h, 018h, 000h, 010h, 010h, 010h, 010h, 000h ; #161 + DB 01Ch, 000h, 038h, 044h, 044h, 044h, 038h, 000h ; #162 + DB 01Ch, 000h, 044h, 044h, 044h, 044h, 038h, 000h ; #163 + DB 07Ch, 000h, 078h, 044h, 044h, 044h, 044h, 000h ; #164 + DB 07Ch, 000h, 044h, 064h, 054h, 04Ch, 044h, 000h ; #165 + DB 018h, 024h, 024h, 01Eh, 000h, 03Eh, 000h, 000h ; #166 + DB 01Ch, 022h, 022h, 01Ch, 000h, 03Eh, 000h, 000h ; #167 + DB 010h, 000h, 010h, 020h, 040h, 042h, 03Ch, 000h ; #168 + DB 000h, 000h, 000h, 0FCh, 080h, 080h, 000h, 000h ; #169 + DB 000h, 000h, 000h, 0FCh, 004h, 004h, 000h, 000h ; #170 + DB 040h, 044h, 048h, 057h, 021h, 047h, 004h, 007h ; #171 + DB 040h, 044h, 048h, 052h, 026h, 04Ah, 01Fh, 002h ; #172 + DB 010h, 000h, 010h, 010h, 010h, 010h, 010h, 000h ; #173 + DB 000h, 024h, 048h, 090h, 048h, 024h, 000h, 000h ; #174 + DB 000h, 048h, 024h, 012h, 024h, 048h, 000h, 000h ; #175 + DB 022h, 088h, 022h, 088h, 022h, 088h, 022h, 088h ; #176 + DB 055h, 0AAh, 055h, 0AAh, 055h, 0AAh, 055h, 0AAh ; #177 + DB 0DBh, 077h, 0DBh, 0EEh, 0DBh, 077h, 0DBh, 0EEh ; #178 + DB 018h, 018h, 018h, 018h, 018h, 018h, 018h, 018h ; #179 + DB 018h, 018h, 018h, 018h, 0F8h, 018h, 018h, 018h ; #180 + DB 018h, 018h, 0F8h, 018h, 0F8h, 018h, 018h, 018h ; #181 + DB 036h, 036h, 036h, 036h, 0F6h, 036h, 036h, 036h ; #182 + DB 000h, 000h, 000h, 000h, 0FEh, 036h, 036h, 036h ; #183 + DB 000h, 000h, 0F8h, 018h, 0F8h, 018h, 018h, 018h ; #184 + DB 036h, 036h, 0F6h, 006h, 0F6h, 036h, 036h, 036h ; #185 + DB 036h, 036h, 036h, 036h, 036h, 036h, 036h, 036h ; #186 + DB 000h, 000h, 0FEh, 006h, 0F6h, 036h, 036h, 036h ; #187 + DB 036h, 036h, 0F6h, 006h, 0FEh, 000h, 000h, 000h ; #188 + DB 036h, 036h, 036h, 036h, 0FEh, 000h, 000h, 000h ; #189 + DB 018h, 018h, 0F8h, 018h, 0F8h, 000h, 000h, 000h ; #190 + DB 000h, 000h, 000h, 000h, 0F8h, 018h, 018h, 018h ; #191 + DB 018h, 018h, 018h, 018h, 01Fh, 000h, 000h, 000h ; #192 + DB 018h, 018h, 018h, 018h, 0FFh, 000h, 000h, 000h ; #193 + DB 000h, 000h, 000h, 000h, 0FFh, 018h, 018h, 018h ; #194 + DB 018h, 018h, 018h, 018h, 01Fh, 018h, 018h, 018h ; #195 + DB 000h, 000h, 000h, 000h, 0FFh, 000h, 000h, 000h ; #196 + DB 018h, 018h, 018h, 018h, 0FFh, 018h, 018h, 018h ; #197 + DB 018h, 018h, 01Fh, 018h, 01Fh, 018h, 018h, 018h ; #198 + DB 036h, 036h, 036h, 036h, 037h, 036h, 036h, 036h ; #199 + DB 036h, 036h, 037h, 030h, 03Fh, 000h, 000h, 000h ; #200 + DB 000h, 000h, 03Fh, 030h, 037h, 036h, 036h, 036h ; #201 + DB 036h, 036h, 0F7h, 000h, 0FFh, 000h, 000h, 000h ; #202 + DB 000h, 000h, 0FFh, 000h, 0F7h, 036h, 036h, 036h ; #203 + DB 036h, 036h, 037h, 030h, 037h, 036h, 036h, 036h ; #204 + DB 000h, 000h, 0FFh, 000h, 0FFh, 000h, 000h, 000h ; #205 + DB 036h, 036h, 0F7h, 000h, 0F7h, 036h, 036h, 036h ; #206 + DB 018h, 018h, 0FFh, 000h, 0FFh, 000h, 000h, 000h ; #207 + DB 036h, 036h, 036h, 036h, 0FFh, 000h, 000h, 000h ; #208 + DB 000h, 000h, 0FFh, 000h, 0FFh, 018h, 018h, 018h ; #209 + DB 000h, 000h, 000h, 000h, 0FFh, 036h, 036h, 036h ; #210 + DB 036h, 036h, 036h, 036h, 03Fh, 000h, 000h, 000h ; #211 + DB 018h, 018h, 01Fh, 018h, 01Fh, 000h, 000h, 000h ; #212 + DB 000h, 000h, 01Fh, 018h, 01Fh, 018h, 018h, 018h ; #213 + DB 000h, 000h, 000h, 000h, 03Fh, 036h, 036h, 036h ; #214 + DB 036h, 036h, 036h, 036h, 0FFh, 036h, 036h, 036h ; #215 + DB 018h, 018h, 0FFh, 018h, 0FFh, 018h, 018h, 018h ; #216 + DB 018h, 018h, 018h, 018h, 0F8h, 000h, 000h, 000h ; #217 + DB 000h, 000h, 000h, 000h, 01Fh, 018h, 018h, 018h ; #218 + DB 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh ; #219 + DB 000h, 000h, 000h, 000h, 0FFh, 0FFh, 0FFh, 0FFh ; #220 + DB 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h, 0F0h ; #221 + DB 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh, 00Fh ; #222 + DB 0FFh, 0FFh, 0FFh, 0FFh, 000h, 000h, 000h, 000h ; #223 + DB 000h, 000h, 062h, 094h, 088h, 094h, 062h, 000h ; #224 + DB 000h, 0F0h, 088h, 0F0h, 088h, 088h, 0F0h, 080h ; #225 + DB 000h, 0F8h, 088h, 080h, 080h, 080h, 080h, 000h ; #226 + DB 000h, 0FCh, 048h, 048h, 048h, 048h, 048h, 000h ; #227 + DB 0FCh, 084h, 040h, 020h, 040h, 084h, 0FCh, 000h ; #228 + DB 03Ch, 040h, 038h, 044h, 044h, 044h, 038h, 000h ; #229 + DB 000h, 000h, 044h, 044h, 044h, 078h, 040h, 040h ; #230 + DB 000h, 036h, 048h, 008h, 008h, 008h, 008h, 000h ; #231 + DB 038h, 010h, 038h, 044h, 044h, 038h, 010h, 038h ; #232 + DB 078h, 084h, 084h, 0FCh, 084h, 084h, 078h, 000h ; #233 + DB 078h, 084h, 084h, 084h, 048h, 048h, 0CCh, 000h ; #234 + DB 078h, 004h, 038h, 044h, 044h, 044h, 038h, 000h ; #235 + DB 000h, 000h, 06Ch, 092h, 092h, 06Ch, 000h, 000h ; #236 + DB 000h, 000h, 03Ah, 044h, 05Ah, 022h, 05Ch, 000h ; #237 + DB 018h, 020h, 040h, 078h, 040h, 020h, 018h, 000h ; #238 + DB 078h, 084h, 084h, 084h, 084h, 084h, 084h, 000h ; #239 + DB 000h, 0FCh, 000h, 0FCh, 000h, 0FCh, 000h, 000h ; #240 + DB 020h, 020h, 0F8h, 020h, 020h, 000h, 0F8h, 000h ; #241 + DB 020h, 010h, 008h, 010h, 020h, 000h, 07Ch, 000h ; #242 + DB 008h, 010h, 020h, 010h, 008h, 000h, 07Ch, 000h ; #243 + DB 00Ch, 012h, 010h, 010h, 010h, 010h, 010h, 010h ; #244 + DB 010h, 010h, 010h, 010h, 010h, 010h, 090h, 060h ; #245 + DB 000h, 010h, 000h, 07Ch, 000h, 010h, 000h, 000h ; #246 + DB 000h, 032h, 04Ch, 000h, 032h, 04Ch, 000h, 000h ; #247 + DB 038h, 044h, 044h, 038h, 000h, 000h, 000h, 000h ; #248 + DB 000h, 000h, 000h, 018h, 018h, 000h, 000h, 000h ; #249 + DB 000h, 000h, 000h, 000h, 018h, 000h, 000h, 000h ; #250 + DB 00Eh, 008h, 008h, 008h, 048h, 028h, 018h, 008h ; #251 + DB 038h, 024h, 024h, 024h, 024h, 000h, 000h, 000h ; #252 + DB 03Ch, 004h, 03Ch, 020h, 03Ch, 000h, 000h, 000h ; #253 + DB 000h, 000h, 03Ch, 03Ch, 03Ch, 03Ch, 000h, 000h ; #254 + DB 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; #255 diff --git a/16/xw__/makefile b/16/xw__/makefile new file mode 100755 index 00000000..cfe15232 --- /dev/null +++ b/16/xw__/makefile @@ -0,0 +1,132 @@ +# +# MODEX library makefile (for Borland MAKE) +# Copyright (c) 1993,1994 by Alessandro Scotti +# +!ifdef __LINUX__ +REMOVECOMMAND=rm -f +COPYCOMMAND=cp -f +DIRSEP=/ +OBJ=o +!else +REMOVECOMMAND=del +COPYCOMMAND=copy /y +DIRSEP=\ +OBJ=obj +!endif +LIBINCS = modex.def + +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) +#mxfp.$(OBJ) +# +# ASM compiler +# +ASMC =wasm +ASMO =-mh -0 + +# +# PAS compiler +# +#PASC = tpc +#PASO = /m -$D- -$L- -$S- + +# +# LIB maker, uses response file +# +LIBC = wlib + +# .asm.obj: +# $(ASMC) $(ASMO) $< + +mxbb.$(OBJ): mxbb.asm + $(ASMC) $(ASMO) mxbb.asm +mxcc.$(OBJ): mxcc.asm + $(ASMC) $(ASMO) mxcc.asm +mxcg.$(OBJ): mxcg.asm + $(ASMC) $(ASMO) mxcg.asm +mxcl.$(OBJ): mxcl.asm + $(ASMC) $(ASMO) mxcl.asm +mxcr.$(OBJ): mxcr.asm + $(ASMC) $(ASMO) mxcr.asm +mxfb.$(OBJ): mxfb.asm + $(ASMC) $(ASMO) mxfb.asm +mxfp.$(OBJ): mxfp.asm + $(ASMC) $(ASMO) mxfp.asm +mxgc.$(OBJ): mxgc.asm + $(ASMC) $(ASMO) mxgc.asm +mxgi.$(OBJ): mxgi.asm + $(ASMC) $(ASMO) mxgi.asm +mxgm.$(OBJ): mxgm.asm + $(ASMC) $(ASMO) mxgm.asm +mxgp.$(OBJ): mxgp.asm + $(ASMC) $(ASMO) mxgp.asm +mxgv.$(OBJ): mxgv.asm + $(ASMC) $(ASMO) mxgv.asm +mxhl.$(OBJ): mxhl.asm + $(ASMC) $(ASMO) mxhl.asm +mxit.$(OBJ): mxit.asm + $(ASMC) $(ASMO) mxit.asm +mxll.$(OBJ): mxll.asm + $(ASMC) $(ASMO) mxll.asm +mxln.$(OBJ): mxln.asm + $(ASMC) $(ASMO) mxln.asm +mxot.$(OBJ): mxot.asm + $(ASMC) $(ASMO) mxot.asm +mxpb.$(OBJ): mxpb.asm + $(ASMC) $(ASMO) mxpb.asm +mxpf.$(OBJ): mxpf.asm + $(ASMC) $(ASMO) mxpf.asm +mxpg.$(OBJ): mxpg.asm + $(ASMC) $(ASMO) mxpg.asm +mxpi.$(OBJ): mxpi.asm + $(ASMC) $(ASMO) mxpi.asm +mxpn.$(OBJ): mxpn.asm + $(ASMC) $(ASMO) mxpn.asm +mxpp.$(OBJ): mxpp.asm + $(ASMC) $(ASMO) mxpp.asm +mxra.$(OBJ): mxra.asm + $(ASMC) $(ASMO) mxra.asm +mxrp.$(OBJ): mxrp.asm + $(ASMC) $(ASMO) mxrp.asm +mxsa.$(OBJ): mxsa.asm + $(ASMC) $(ASMO) mxsa.asm +mxsc.$(OBJ): mxsc.asm + $(ASMC) $(ASMO) mxsc.asm +mxsi.$(OBJ): mxsi.asm + $(ASMC) $(ASMO) mxsi.asm +mxsl.$(OBJ): mxsl.asm + $(ASMC) $(ASMO) mxsl.asm +mxsm.$(OBJ): mxsm.asm + $(ASMC) $(ASMO) mxsm.asm +mxsp.$(OBJ): mxsp.asm + $(ASMC) $(ASMO) mxsp.asm +mxss.$(OBJ): mxss.asm + $(ASMC) $(ASMO) mxss.asm +mxtl.$(OBJ): mxtl.asm + $(ASMC) $(ASMO) mxtl.asm +mxvs.$(OBJ): mxvs.asm + $(ASMC) $(ASMO) mxvs.asm +mxwd.$(OBJ): mxwd.asm + $(ASMC) $(ASMO) mxwd.asm +mxwm.$(OBJ): mxwm.asm + $(ASMC) $(ASMO) mxwm.asm +mxwp.$(OBJ): mxwp.asm + $(ASMC) $(ASMO) mxwp.asm +mxwr.$(OBJ): mxwr.asm + $(ASMC) $(ASMO) mxwr.asm + +all: $(LIBOBJS) modex.lib +# modex.tpu modex.tpp + +#modex.tpu: $(LIBOBJS) modex.pas +# $(PASC) $(PASO) modex +# copy modex.tpu .. +# copy modex.pas .. + +#modex.tpp: $(LIBOBJS) modex.pas +# $(PASC) /cp $(PASO) modex +# copy modex.tpp .. + +modex.lib: modex.lbr $(LIBOBJS) + $(LIBC) modex.lib @modex.lbr + +$(LIBOBJS): modex.def diff --git a/16/xw__/makefile.bcc b/16/xw__/makefile.bcc new file mode 100755 index 00000000..d3ad8b71 --- /dev/null +++ b/16/xw__/makefile.bcc @@ -0,0 +1,81 @@ +# +# MODEX library makefile (for Borland MAKE) +# Copyright (c) 1993,1994 by Alessandro Scotti +# +LIBINCS = MODEX.DEF + +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 + +# +# ASM compiler +# +ASMC = tasm +ASMO = /m5 /p + +# +# PAS compiler +# +PASC = tpc +PASO = /m -$D- -$L- -$S- + +# +# LIB maker, uses response file +# +LIBC = tlib + +.asm.obj: + $(ASMC) $(ASMO) $< + +target: modex.lib +# modex.tpu modex.tpp + +#modex.tpu: $(LIBOBJS) modex.pas +# $(PASC) $(PASO) modex +# copy modex.tpu .. +# copy modex.pas .. + +#modex.tpp: $(LIBOBJS) modex.pas +# $(PASC) /cp $(PASO) modex +# copy modex.tpp .. + +modex.lib: modex.lbr $(LIBOBJS) + $(LIBC) modex.lib @modex.lbr + +$(LIBOBJS): modex.def diff --git a/16/xw__/modex.bak b/16/xw__/modex.bak new file mode 100755 index 0000000000000000000000000000000000000000..560a1c68304c56844f41325820f296a21192ac4e GIT binary patch literal 25600 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 literal 0 HcmV?d00001 diff --git a/16/xw__/modex.def b/16/xw__/modex.def new file mode 100755 index 00000000..7977a4a0 --- /dev/null +++ b/16/xw__/modex.def @@ -0,0 +1,163 @@ +;------------------------------------------------------------ +; +; MODEX.DEF - Include file +; Copyright (c) 1993-1994 by Alessandro Scotti +; +;JUMPS +;LOCALS + +TRUE EQU 1 ; Boolean constants +FALSE EQU 0 + +USE286 = FALSE ; TRUE enables 80286 instructions +USE386 = FALSE ; TRUE enables 80386 (and 80286) instructions + +IF USE286 EQ TRUE + P286 +ENDIF + +IF USE386 EQ TRUE + P386 + USE286 = TRUE +ENDIF + +MXVERSION EQU 0128h ; Library version (1.40) + +;------------------------------------------------------------ +; +; VGA definitions +; +MISC EQU 3C2h ; Miscellaneous output +TS EQU 3C4h ; Timing Sequencer index register +GDC EQU 3CEh ; Graphics Data Controller index register +CRTC EQU 3D4h ; CRTC index register +STATUS EQU 3DAh ; Input Status register one + +;------------------------------------------------------------ +; +; Raster operators +; +OP_SET EQU 0 +OP_MOVE EQU 0 ; Same as OP_SET +OP_AND EQU 1 +OP_OR EQU 2 +OP_XOR EQU 3 +OP_TRANS EQU 4 +OP_ADD EQU 5 ; Must be last op + +;------------------------------------------------------------ +; +; Polygon fill functions +; +POLYSCANBUFSIZE EQU 4*1024 + +;------------------------------------------------------------ +; Macro to push registers, variables or flags onto the stack +; Usage: .push "loc16"[,"loc16"...] +; where "loc16" is a 16-bit register, a word-sized variable or the +; keyword "FLAGS". +; Exmpl: .push ax, flags, var1 +; .pop ax, flags, var1 +; +.push MACRO r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10 + IFNB + .ERROR <.PUSH has more than 10 arguments> + ENDIF + IRP $reg, + IFB <$reg> ;; Is argument blank? + EXITM ;; Yes, exit + ELSEIFIDNI <$reg>, ;; Is argument the keyword "FLAGS"? + pushf ;; Yes, push flags + ELSE + push $reg ;; Push argument + ENDIF + ENDM +ENDM + +;------------------------------------------------------------ +; Macro to pop registers, variables or flags from the stack +; Usage: .pop "loc16"[,"loc16"...] +; where "loc16" is a 16-bit register, a word-sized variable or the +; keyword "FLAGS". +; Exmpl: .push ax, flags, var1 +; .pop ax, flags, var1 +; +.pop MACRO r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10 + IFNB + .ERROR <.POP has more than 10 arguments> + ENDIF + IRP $reg, + IFNB <$reg> ;; Is argument non-blank? + IFIDNI <$reg>, ;; Yes, is it the keyword "FLAGS"? + popf ;; Yes, pop flags + ELSE + pop $reg ;; Pop argument + ENDIF + ENDIF + ENDM +ENDM + +;------------------------------------------------------------ +; +.enter MACRO localsize + IF USE286 EQ TRUE + enter localsize, 0 + ELSE + push bp + mov bp, sp + sub sp, localsize + ENDIF +ENDM + +;------------------------------------------------------------ +; +;.leave MACRO argsize +; IF USE286 EQ TRUE +; leave +; ELSE +; mov sp, bp +; pop bp +; ENDIF +; IFNB +; ret argsize +; ELSE +; ret +; ENDIF +;ENDM + +;------------------------------------------------------------ +; +;.shr MACRO arg, count +; IF USE286 EQ TRUE +; shr arg, count +; ELSE +; $temp = count +; WHILE $temp GT 0 +; shr arg, 1 +; $temp = $temp-1 +; ENDM +; ENDIF +;ENDM + +;------------------------------------------------------------ +; +;.shl MACRO arg, count +; IF USE286 EQ TRUE +; shl arg, count +; ELSE +; $temp = count +; WHILE $temp GT 0 +; shl arg, 1 +; $temp = $temp-1 +; ENDM +; ENDIF +;ENDM + +;------------------------------------------------------------ +; +;.chk386 MACRO name, jump +; IF USE386 EQ FALSE +; .OUT "Warning: ", , " needs a 386 or better to run!" +; jmp @@jump +; ENDIF +;ENDM diff --git a/16/xw__/modex.h b/16/xw__/modex.h new file mode 100755 index 00000000..2c1f1ebe --- /dev/null +++ b/16/xw__/modex.h @@ -0,0 +1,153 @@ +/* + MODEX.H - C/C++ include file for the MODEX library + Copyright (c) 1994 Alessandro Scotti +*/ + +#ifndef _MODEX_H_ // Avoid nested inclusions +#define _MODEX_H_ + +// +// Video modes +// +#define MX_TEXT 0 // 80x25 text +#define MX_320x175 1 // 320x175x256 +#define MX_320x200 2 // 320x200x256, 4 pages, aspect 6:5 +#define MX_320x240 3 // 320x240x256, 3 pages, aspect 1:1 +#define MX_320x350 4 // 320x350x256 +#define MX_320x400 5 // 320x400x256, 2 pages +#define MX_320x480 6 // 320x480x256, 1 page +#define MX_360x175 7 // 360x175x256 +#define MX_360x200 8 // 360x200x256, 3 pages +#define MX_360x240 9 // 360x240x256, 2 pages +#define MX_360x350 10 // 360x350x256 +#define MX_360x400 11 // 360x400x256, 1 page +#define MX_360x480 12 // 360x480x256, 1 page +#define MX_400x600 13 // 400x600x256, 1 page + +// +// Fade effects +// +#define MX_FADEIN 0 +#define MX_FADEOUT 1 + +// +// Raster ops +// +#define OP_SET 0 // No operator +#define OP_AND 1 // And +#define OP_OR 2 // Or +#define OP_XOR 3 // Xor +#define OP_TRANS 4 // Transparent +#define OP_ADD 5 // Additive +#define OP_MOVE 0 // Alias for OP_SET + +// +// Temporary definitions +// +#define MXBYTE unsigned char +#define MXBOOL short int +#define MXSINT short int +#define MXUINT unsigned short int +#define MXAPI far pascal +#define MXPTR void far * + +// Functions + +#ifdef __cplusplus // Avoid C++ name mangling +extern "C" { +#endif + +// +// Initialization +// +MXSINT MXAPI mxInit( void ); // Returns 0 if successful +void MXAPI mxTerm( void ); +MXUINT MXAPI mxGetVersion( void ); +// +// Mode setting +// +void MXAPI mxChangeMode( MXUINT mode ); +void MXAPI mxSetMode( MXUINT mode ); +void MXAPI mxGetAspect( MXUINT far *aspectx, MXUINT far *aspecty ); +void MXAPI mxGetScreenSize( MXUINT far *width, MXUINT far *height ); +// +// Hardware support +// +void MXAPI mxWriteMode( MXBYTE wm ); +void MXAPI mxSplitScreen( MXUINT line ); +void MXAPI mxStartAddress( MXUINT sa ); +void MXAPI mxStartLine( MXUINT sl ); +void MXAPI mxWaitDisplay( void ); +void MXAPI mxWaitRetrace( void ); +void MXAPI mxWritePlane( MXBYTE wp ); +void MXAPI mxReadPlane( MXBYTE rp ); +void MXAPI mxRowAddress( MXBYTE ra ); +// +// Virtual screen +// +void MXAPI mxGetVirtualScreen( MXUINT far *width, MXUINT far *height ); +void MXAPI mxSetVirtualScreen( MXUINT width, MXUINT height ); +void MXAPI mxPan( MXUINT x, MXUINT y ); +// +// Clipping +// +MXBOOL MXAPI mxGetClip( void ); +MXBOOL MXAPI mxGetClipRegion( MXSINT far *x, MXSINT far *y, MXSINT far *w, MXSINT far *h ); +MXBOOL MXAPI mxSetClip( MXBOOL ); +void MXAPI mxSetClipRegion( MXUINT x, MXUINT y, MXUINT width, MXUINT height ); +// +// Graphics +// +void MXAPI mxBitBlt( MXSINT sx, MXSINT sy, MXUINT width, MXUINT height, MXSINT dx, MXSINT dy ); +void MXAPI mxFillBox( MXSINT x, MXSINT y, MXUINT width, MXUINT height, MXUINT color, MXUINT op ); +MXBYTE MXAPI mxGetPixel( MXSINT x, MXSINT y ); +void MXAPI mxPutPixel( MXSINT x, MXSINT y, MXBYTE color ); +void MXAPI mxLine( MXSINT x1, MXSINT y1, MXSINT x2, MXSINT y2, MXUINT color, MXUINT op ); +void MXAPI mxGetImage( MXPTR img, MXSINT x, MXSINT y, MXUINT width, MXUINT height ); +void MXAPI mxPutImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT op ); +void MXAPI mxPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT width, MXUINT height ); +void MXAPI mxTransPutTile( MXPTR tile, MXSINT x, MXSINT y, MXUINT w, MXUINT h ); +void MXAPI mxCircle( MXSINT x, MXSINT y, MXUINT radius, MXBYTE color ); +void MXAPI mxStretchImage( MXPTR img, MXSINT x, MXSINT y, MXUINT w, MXUINT h, MXUINT neww, MXUINT newh, MXUINT op ); +// +// Palette +// +void MXAPI mxColorToGray( MXPTR source, MXPTR dest, MXUINT count ); +void MXAPI mxGammaCorrect( MXPTR source, MXPTR dest, MXUINT count ); +void MXAPI mxGetColor( MXUINT index, MXSINT far *r, MXSINT far *g, MXSINT far *b ); +void MXAPI mxSetColor( MXUINT index, MXSINT red, MXSINT green, MXSINT blue ); +void MXAPI mxGetPalette( MXPTR palette, MXUINT index, MXUINT count ); +void MXAPI mxSetPalette( MXPTR palette, MXUINT index, MXUINT count ); +void MXAPI mxFadePalette( MXPTR, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT, MXUINT ); +void MXAPI mxRotatePalette( MXPTR palette, MXUINT count, MXSINT step ); +// +// Text +// +MXSINT MXAPI mxSetFont( MXPTR font, MXUINT charwidth, MXUINT charheight ); +void MXAPI mxSetTextColor( MXUINT color, MXUINT op ); +void MXAPI mxGetTextStep( MXSINT far *deltax, MXSINT far *deltay ); +void MXAPI mxSetTextStep( MXSINT deltax, MXSINT deltay ); +void MXAPI mxOutChar( MXSINT x, MXSINT y, char c ); +void MXAPI mxOutText( MXSINT x, MXSINT y, char far *sz ); +// +// Convex polygons +// +void MXAPI mxFillPoly( MXUINT, MXPTR, MXPTR, MXUINT, MXUINT ); +void MXAPI mxGouraudPoly( MXUINT, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT ); +void MXAPI mxTexturePoly( MXUINT, MXPTR, MXPTR, MXPTR, MXPTR, MXUINT, MXUINT ); + +#ifdef __cplusplus +} +#endif + +// +// Remove temporary defines +// +#undef MXBYTE +#undef MXBOOL +#undef MXSINT +#undef MXUINT +#undef MXPTR +#undef MXAPI + +#endif // _MODEX_H_ diff --git a/16/xw__/modex.lbr b/16/xw__/modex.lbr new file mode 100755 index 00000000..93fc7801 --- /dev/null +++ b/16/xw__/modex.lbr @@ -0,0 +1,39 @@ ++-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 & ++-MXPT.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 diff --git a/16/xw__/modex.pas b/16/xw__/modex.pas new file mode 100755 index 00000000..7d9d26ed --- /dev/null +++ b/16/xw__/modex.pas @@ -0,0 +1,194 @@ +(* + Turbo Pascal interface to the MODEX library + Copyright (c) 1993,1994 by Alessandro Scotti +*) +unit ModeX; +interface + +const + (* Video modes *) + MX_TEXT = 0; + MX_320x175 = 1; + MX_320x200 = 2; + MX_320x240 = 3; + MX_320x350 = 4; + MX_320x400 = 5; + MX_320x480 = 6; + MX_360x175 = 7; + MX_360x200 = 8; + MX_360x240 = 9; + MX_360x350 = 10; + MX_360x400 = 11; + MX_360x480 = 12; + MX_400x600 = 13; + + (* Fade effects *) + MX_FADEIN = 0; + MX_FADEOUT = 1; + + (* Raster ops *) + OP_SET = 0; + OP_AND = 1; + OP_OR = 2; + OP_XOR = 3; + OP_TRANS = 4; + OP_ADD = 5; + OP_MOVE = 0; (* Alias for OP_SET *) + +procedure mxBitBlt( SX, SY: integer; Width, Height: word; DX, DY: integer ); +procedure mxCircle( CX, CY: integer; Radius: word; Color: byte ); +procedure mxChangeMode( Mode: word ); +procedure mxColorToGray( ColorPalette, GrayPalette: pointer; Count: word ); +procedure mxFadePalette( Palette: pointer; Cmd, Start, Count, R, G, B: word ); +procedure mxFillBox( X, Y: integer; Width, Height: word; Color: byte; Op: word ); +procedure mxGammaCorrect( ColorPalette, GammaPalette: pointer; Count: word ); +procedure mxGetAspect( var AspectX, AspectY: word ); +function mxGetClipRegion( var X1, Y1, Width, Height: word ): boolean; +function mxGetClip: boolean; +procedure mxGetImage( Image: pointer; X, Y: integer; Width, Height: word ); +procedure mxGetPalette( Palette: pointer; Start, Count: word ); +function mxGetPixel( X, Y: word ): byte; +procedure mxGetScreenSize( var Width, Height: word ); +procedure mxGetTextStep( var DeltaX, DeltaY: integer ); +function mxGetVersion: word; +procedure mxGetVirtualScreen( var Width, Height: word ); +procedure mxInit; +procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word ); +procedure mxOutChar( X, Y: integer; C: char ); +procedure mxOutText( X, Y: integer; S: pointer ); +procedure mxPan( X, Y: word ); +procedure mxPutImage( Image: pointer; X, Y: integer; Width, Height, Op: word ); +procedure mxPutPixel( X, Y: word; C: byte ); +procedure mxPutTile( Tile: pointer; X, Y: integer; Width, Height: word ); +procedure mxReadPlane( Plane: byte ); +procedure mxRotatePalette( Palette: pointer; Count: word; Step: integer ); +procedure mxRowAddress( RowAddress: byte ); +function mxSetClip( Clip: boolean ): boolean; +procedure mxSetClipRegion( X1, Y1, Width, Height: word ); +procedure mxSetColor( Index, R, G, B: word ); +procedure mxSetFont( Font: pointer; Width, Height: word ); +procedure mxSetMode( Mode: word ); +procedure mxSetPalette( Palette: pointer; Start, Count: word ); +procedure mxSetTextColor( Color, Op: word ); +procedure mxSetTextStep( DeltaX, DeltaY: integer ); +procedure mxSetVirtualScreen( Width, Height: word ); +procedure mxStretchImage( Image: pointer; X, Y: integer; Width, Height, NewWidth, NewHeight, Op: word ); +procedure mxSplitScreen( Line: word ); +procedure mxStartAddress( StartAddress: word ); +procedure mxStartLine( Line: word ); +procedure mxTerm; +procedure mxTransPutTile( Tile: pointer; X, Y: integer; Width, Height: word ); +procedure mxWaitDisplay; +procedure mxWaitRetrace; +procedure mxWriteMode( Mode: byte ); +procedure mxWritePlane( Plane: byte ); + +procedure mxFillPoly( Count: word; var Map, Points; Color: word ); +procedure mxGouraudPoly( Count: word; var Map, Points, Colors; BaseColor: word ); +procedure mxTexturePoly( Count: word; var Map, Points, ImgPoints, Texture; Width: word ); + +procedure mxOutStr( X, Y: integer; S: string ); + +implementation + +procedure mxBitBlt; external; +procedure mxChangeMode( Mode: word ); external; +procedure mxCircle; external; +procedure mxColorToGray; external; +procedure mxFadePalette; external; +procedure mxFillBox; external; +procedure mxGammaCorrect; external; +procedure mxGetAspect( var AspectX, AspectY: word ); external; +function mxGetClipRegion; external; +function mxGetClip: boolean; external; +procedure mxGetImage; external; +procedure mxGetPalette( Palette: pointer; Start, Count: word ); external; +function mxGetPixel( X, Y: word ): byte; external; +procedure mxGetScreenSize( var Width, Height: word ); external; +procedure mxGetTextStep( var DeltaX, DeltaY: integer ); external; +function mxGetVersion: word; external; +procedure mxGetVirtualScreen( var Width, Height: word ); external; +procedure mxInit; external; +procedure mxLine( X1, Y1, X2, Y2: integer; Color, Op: word ); external; +procedure mxOutChar( X, Y: integer; C: char ); external; +procedure mxOutText( X, Y: integer; S: pointer ); external; +procedure mxPan( X, Y: word ); external; +procedure mxPutImage; external; +procedure mxPutPixel( X, Y: word; C: byte ); external; +procedure mxPutTile; external; +procedure mxReadPlane( Plane: byte ); external; +procedure mxRotatePalette; external; +procedure mxRowAddress( RowAddress: byte ); external; +function mxSetClip( Clip: boolean ): boolean; external; +procedure mxSetClipRegion( X1, Y1, Width, Height: word ); external; +procedure mxSetColor( Index, R, G, B: word ); external; +procedure mxSetFont( Font: pointer; Width, Height: word ); external; +procedure mxSetMode( Mode: word ); external; +procedure mxSetPalette( Palette: pointer; Start, Count: word ); external; +procedure mxSetTextColor( Color, Op: word ); external; +procedure mxSetTextStep( DeltaX, DeltaY: integer ); external; +procedure mxSetVirtualScreen( Width, Height: word ); external; +procedure mxSplitScreen( Line: word ); external; +procedure mxStartAddress( StartAddress: word ); external; +procedure mxStartLine; external; +procedure mxStretchImage; external; +procedure mxTerm; external; +procedure mxTransPutTile; external; +procedure mxWaitDisplay; external; +procedure mxWaitRetrace; external; +procedure mxWriteMode( Mode: byte ); external; +procedure mxWritePlane( Plane: byte ); external; + +procedure mxFillPoly; external; +procedure mxGouraudPoly; external; +procedure mxTexturePoly; external; +{$L MXPB} +{$L MXPF} +{$L MXPG} +{$L MXPT} + +{$L MXBB} +{$L MXCC} +{$L MXCG} +{$L MXCL} +{$L MXCR} +{$L MXFB} +{$L MXFP} +{$L MXGI} +{$L MXGM} +{$L MXGP} +{$L MXGV} +{$L MXHL} +{$L MXIT} +{$L MXLN} +{$L MXOT} +{$L MXPI} +{$L MXPN} +{$L MXPP} +{$L MXRA} +{$L MXRP} +{$L MXSA} +{$L MXSC} +{$L MXSI} +{$L MXSL} +{$L MXSM} +{$L MXSP} +{$L MXSS} +{$L MXTL} +{$L MXVS} +{$L MXWD} +{$L MXWM} +{$L MXWP} +{$L MXWR} + +(* + Prints a Turbo Pascal string. + Note: BP 7.0 supports ASCIIZ strings (PChar type). +*) +procedure mxOutStr; +begin + S := S + #0; + mxOutText( X, Y, @S[1] ); +end; + +end. diff --git a/16/xw__/modex/DEMO01.EXE b/16/xw__/modex/DEMO01.EXE new file mode 100755 index 0000000000000000000000000000000000000000..28caff88c58a0b8ce5a4d23c6544c00cda8482fc GIT binary patch literal 10208 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 320 ) then begin + S.X := 320; + S.DX := -S.DX; + end; + if( S.X < -16 ) then begin + S.X := -16; + S.DX := -S.DX; + end; + if( S.Y > 240 ) then begin + S.Y := 240; + S.DY := -S.DY; + end; + if( S.Y < -16 ) then begin + S.Y := -16; + S.DY := -S.DY; + end; + (* Draw the sprite, note the Page offset added to the *) + (* Y coordinate of the image *) + mxPutImage( @S.Image, S.X, Page+S.Y, S.W, S.H, OP_TRANS ); +end; + +begin + (* Initialize library *) + mxInit; + + (* Enter graphics mode *) + mxSetMode( MX_320x240 ); + + (* Print initialization message *) + mxSetTextColor( 15, OP_TRANS ); + mxOutStr( 4, 4, 'Initializing...' ); + + (* Initialize sprites *) + for I:=1 to MAX_SPRITE do sxInit( S[I] ); + + (* Draw background *) + for I:=1 to 192 do begin + mxCircle( 160, 480+120, I, I+63 ); + mxCircle( 161, 480+120, I, I+63 ); + end; + + (* Compute and set palette *) + for I:=1 to 192 do with Palette[I+63] do begin + R := 0; + G := 0; + B := 0; + if( I < 64 ) then + R := I shr 1+31 + else if( I < 128 ) then + G := (I-64) shr 1+31 + else + B := (I-128) shr 1+31; + end; + mxSetPalette( @Palette[64], 64, 192 ); + + (* Main loop *) + Page := 240; + while( not KeyPressed ) do begin + (* Set clip region to current page *) + mxSetClipRegion( 0, Page, 320, 240 ); + mxSetClip( TRUE ); + (* Restore background *) + mxBitBlt( 0, 480, 320, 240, 0, Page ); + (* Draw sprites *) + for I:=1 to MAX_SPRITE do sxMove( S[I] ); + (* Print message *) + mxOutStr( 4, Page+4, 'Some sprites moving...' ); + (* Flip page *) + mxStartLine( Page ); + Page := 240-Page; + (* Animate palette *) + mxSetPalette( @Palette[64], 64, 192 ); + mxRotatePalette( @Palette[64], 192, 3 ); + end; + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw__/modex/DEMO02.EXE b/16/xw__/modex/DEMO02.EXE new file mode 100755 index 0000000000000000000000000000000000000000..14e7dc72b16e421ae94767feaa07cb3988f49db1 GIT binary patch literal 24688 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 L6~S)>H$VReFZ-F@ literal 0 HcmV?d00001 diff --git a/16/xw__/modex/DEMO02.PAS b/16/xw__/modex/DEMO02.PAS new file mode 100755 index 00000000..6b4fb6f9 --- /dev/null +++ b/16/xw__/modex/DEMO02.PAS @@ -0,0 +1,125 @@ +(* + DEMO02 - Texture mapping and palette rotation + (c) 1994 by Alessandro Scotti +*) +uses Crt, Modex, Plasma, Threed; + +const + LSIZE = 85; + Trans : TPoint = ( X:0; Y:0; Z:0 ); +type + T2DPoint = record + X, Y: integer; + end; + TTexture = record + Desc : array[ 0..3 ] of T2DPoint; + Width : word; + Data : array[ 1..64*64 ] of byte; + end; + TQuad = record + VtxCnt : word; + Vtx : array[ 0..3 ] of word; + Texture: word; + end; +var + Vtx : array[ 0..7 ] of TPoint; + XVtx : array[ 0..7 ] of TPoint; + VVtx : array[ 0..7 ] of T2DPoint; + Face : array[ 0..5 ] of TQuad; + Txts : array[ 0..5 ] of TTexture; + Nrm : array[ 0..5 ] of TPoint; + XNrm : array[ 0..5 ] of TPoint; + Page : word; + Palette: array[ byte ] of record R, G, B: byte; end; + +(* Make a 64x64 plasma to be used as texture *) +procedure MakeTexture( Idx: word ); +var + I: word; +begin + mxFillBox( 0, 0, 64, 64, 0, OP_SET ); + MakePlasma( 0, 0, 64, 64, 96, Random(192)+1, Random(192)+1, Random(192)+1 ); + mxGetImage( @Txts[Idx].Data, 0, 0, 64, 64 ); + (* Texture vertexes are 8:8 fixed, add $80 (0.5) for best results *) + with Txts[Idx] do begin + Desc[0].X := $80; Desc[0].Y := $80; + Desc[1].X := $80; Desc[1].Y := $3F80; + Desc[2].X := $3F80; Desc[2].Y := $3F80; + Desc[3].X := $3F80; Desc[3].Y := $80; + Width := 64; + end; +end; + +procedure Init; +var + I: integer; +begin + (* Build vertexes for a cube *) + with Vtx[0] do begin X:=-LSIZE; Y:=-LSIZE; Z:=-LSIZE; end; + with Vtx[1] do begin X:=+LSIZE; Y:=-LSIZE; Z:=-LSIZE; end; + with Vtx[2] do begin X:=-LSIZE; Y:=+LSIZE; Z:=-LSIZE; end; + with Vtx[3] do begin X:=+LSIZE; Y:=+LSIZE; Z:=-LSIZE; end; + with Vtx[4] do begin X:=-LSIZE; Y:=-LSIZE; Z:=+LSIZE; end; + with Vtx[5] do begin X:=+LSIZE; Y:=-LSIZE; Z:=+LSIZE; end; + with Vtx[6] do begin X:=-LSIZE; Y:=+LSIZE; Z:=+LSIZE; end; + with Vtx[7] do begin X:=+LSIZE; Y:=+LSIZE; Z:=+LSIZE; end; + for I:=0 to 7 do begin (* Make points 16:16 fixed *) + Vtx[I].X := Vtx[I].X*$10000; + Vtx[I].Y := Vtx[I].Y*$10000; + Vtx[I].Z := Vtx[I].Z*$10000; + end; + (* Build faces *) + with Face[0] do begin Vtx[0]:=0; Vtx[1]:=2; Vtx[2]:=3; Vtx[3]:=1; end; + with Face[1] do begin Vtx[0]:=4; Vtx[1]:=5; Vtx[2]:=7; Vtx[3]:=6; end; + with Face[2] do begin Vtx[0]:=0; Vtx[1]:=1; Vtx[2]:=5; Vtx[3]:=4; end; + with Face[3] do begin Vtx[0]:=1; Vtx[1]:=3; Vtx[2]:=7; Vtx[3]:=5; end; + with Face[4] do begin Vtx[0]:=2; Vtx[1]:=0; Vtx[2]:=4; Vtx[3]:=6; end; + with Face[5] do begin Vtx[0]:=7; Vtx[1]:=3; Vtx[2]:=2; Vtx[3]:=6; end; + for I:=0 to 5 do Face[I].Texture := I; + (* Build textures and palette *) + Randomize; + FillChar( Palette, SizeOf(Palette), 0 ); + MakePlasmaPalette( Palette, PAL_RGB ); + mxSetPalette( @Palette, 0, 193 ); + for I:=0 to 5 do MakeTexture( I ); +end; + +var + AX, AY, AZ: byte; + I: word; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; (* Start with hidden page *) + + AX := 0; + AY := 0; + AZ := 0; + (* Init 3D transforms, perspective is intentionally exaggerated *) + tdSetTranslation( Trans ); + tdSetPerspective( 400*$10000, $10000, $10000 ); + (* Main loop, all magic here! *) + while( not KeyPressed ) do begin + tdSetRotation( AX, AY, AZ ); (* Set new angles *) + tdTransform( Vtx, XVtx, 8 ); (* 3D transform points *) + tdTransformToImage( XVtx, VVtx, 8, 160, 120+Page ); + Inc( AX, 1 ); (* Bump angles *) + Inc( AY, 1 ); + Inc( AZ, 2 ); + mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *) + mxSetClip( TRUE ); + mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *) + mxRotatePalette( @Palette[1], 192, 3 ); (* Rotate palette *) + (* Draw cube: backface culling is straighforward in this case, so *) + (* it can be handled by the polygon filling procedure *) + for I:=0 to 5 do + mxTexturePoly( 4, Face[I].Vtx, VVtx, Txts[I].Desc, Txts[I].Data, Txts[I].Width ); + mxStartLine( Page ); (* Flip pages *) + mxSetPalette( @Palette[1], 1, 192 ); (* Set new palette *) + Page := 240-Page; + end; + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw__/modex/DEMO03.EXE b/16/xw__/modex/DEMO03.EXE new file mode 100755 index 0000000000000000000000000000000000000000..c646c4b0283db932174d915432747c2176034195 GIT binary patch literal 14256 zcmeG@dt6gjn&&=pa|sYokfvHeTbs7hW|Xw31S!=Lt6MEigYO&}Bn@Cbkg;AMb60GtH41rS6c^aQ|SfHwe)0B-^81o#%00DA#C0B!;Z0NWXa zJ_4`;lmjs6RrE7}HN>lE7rMbh%ACYM~O+q zQ6fijl+dzAi5CI#0CoX@Ys9}a^JN>2N@oB`;dQz;pH*@aC6`8;wO;cIUu`}eXyYEU zL}^YVIjxuT_xRi9>)ACd8q0^%(%cHh&%;Kd)Y7lRj}k$4V}!rM)9h(0Y#03fetwt> zEplOowP9=*RH>yF@+e_F!J4D$*}Lsi(EfT<`!uwhMzx!v{S90C;<%&4OuJd@b5nxW zXA40dov$|O1WWas^9PHxURzN>wVBP2X;EQ2ntAdFfl9s1QKB|~FktULBTAvcE6hxL zwH7T)<@>;AFfs+al_s-M0seC#vBIH)N#9h*A|{>R>T^$=OCaL}KyIp|0VP(%zE?*y zJ#|;p%Db9oVNFFTVmxd=+2z+t$wA4bF-mSRl-Z1E+OkwU*dJyk7YcY%#AmLg91$&r zgQ!5dK|1%7m|W7mO{DxE@ZjpXcH1X0Gn-=_lUg!Y;@_a=H>H7qm#RaK5~Wx0&y(;2 z?y9>Z8uHKFm2v0qyDL#-;Wy`};y3JrAN7qm2r@oR_Tx@5e4FxpS1AM4RdWX?4TLD^ zH2jKLxK7M0>v}~U^OnMnAbXv729U$KOWsYpvbPlJbpE%jBN;(m58>(Y+6+P$#^Ns?3HshZy z3UrJ_(dnftVF887x&yKg3IgVApa90N0-;5L_P(Q-(V4n;v-rCO|CT-keg5#*CN<+E z;HlJ74p{k{$G&BwMVxIfN-fJ(NY=x2{S=mIAE@914NRZ_Z?GYR%+=r0{2+ADcrQcY*TPa+Z3*=uB*Zq-?De>Z7g2dl-m?o7o0gT zn;@mD#^ZcB5BVZ7p~7a6_c?fJ6R@~S84qDaN*Nm5)`McfTh?5~-t~$mK4&KX#GSGY z3W6~y%JQLjTTz%~QlJge!lbtqXd~#c9x&?_v{3?@tyj1g3i7uA^A>a_;ZFaI;DE$+ zmD?;wRuky$Z$u&M+arx=WZf{*P$Fx-qLihw2-a?-x;FT*^*ETNt3l~(h;tNdWUyn^ z14P@}$l^8~rzNwk|<3?B52P0DS7md%UCE=Xq|P1SOJe@v8$y(Pm4#J=oL(Q z*j{l+SY>VqoD#O4-JyG#1Gy@!TfL5Jhvw6`4U(yPU4+rg0d27fY$+$C_sdk& zuh`Aa1*E!JX`ZlP0cZ$z8>@!30;{nU9f%o|L!&Z5Or=qo0PQiEAcjg*NUU)^ViI~( zBe4!J7>RX&!Pr=PRG_jy>cb31!W>{Q66OGdv0)y?;DpY>hf@p~Zr@0%?W?6a9AHTP zF%E4DB!3{O{@a-^Dk)~Xf69#58JIF7c8Uq(QH`}z`M=C!5I8z-7mm(bFiTueJ?j{3 z`N>l((yh>?>nOVp_7ELcql2KR1xQB^%*iX^ICDG~bkqr5L@V|=p>ti+d3tpkr?C^} zEUR0sTji{u=Fh(4x$@zKB^GD?U;JxJETo-TdjU6K)}=A4}u~q91gg zyEOf{5tuA6NpS;D75}kFl`G;(7izXqdt{<-$j$T=6RK zV|cMn1|B0F7f7znb%AQ5R)s*D#_b+x_fWYZIxa*P8>Zu)hy5lUKgx~m1guoY8KB66 z1^ODcd@IcQ6SyvVa0AP&VqdP43PPclC8_*KJmD?F6FwZ0b(gVnJ<(!K~5$2Q8J{b*p9;O@wg3(w#2XK zYAKGEx=+O=kw{awF*3G4wl#kdSH}%{E^<9wtEvoa;*uEXEKo0q9gOYYNK&nUfh&sh z8$)A3Qr zTkdl8?ssmJQtcgsPR?VQwvE)lg*xLt@8EQ^s zUJ|lR>)WRDs>*_>Vta9$w@y3QMAT{fj}zeVL@MvzL}Zv?zd%_oR8ZBYscz`Mi2GX! zi_RzOG~82NOI48FDlRIS=9b8~^A;^DtQcGX!Y)mNJ{uX<4JhtBh)(B*gcbeJqoSgd z=|#q#)l`0nMdt-JQ9sQFB*HU7H(tc?gbIPwr4WhWR4ET(5kW~wM&(h0aoyqoujudE?4Gfr}49U9A<|~!vMSKPyo9JL>8kMERmTmLI{ZFPVg_p zf!Ri@?U<$i=m;SeiFa1FQ`bLZjYHMnP!%DTtApJYp_WVCLw>YjNNvY+`tDy)awNLv z65PZ+YhSxC(Kvu^j!>@DrxZ___bD2V4XxP>rXmg*D;hTi6Eoh1B3RihV;$2~j zfU&FaWTlyI8zQ=^Yp4S^aT`(HI3>p2oOgX%!Oer#MEamL31Bwu;$6Ho8LA01cMfQ{ zS@Y*_?lZ6lH`@)p-R^!Nel{)4lJnjH%m)^MVkU@E3suOZw)d6~GYv7_RNKpD)BfpA zj_jACbk2JT*sdDZ^?#=1kF^UCwM&dJc)Hy`{9_%C!(1y%q|Nm4Tt-!v1Qk4O{5wtb z3bA+gaBsp$FOI2rBPt;A=~ujB;vYuG_9~*&<@^*%td!Ql)$Osp_hM8iprBIvHK4K^ zD#Q41B#BakERo7(Af$X6;y*@}Y@EO!l~`)073}*^v9Cm-w(omav2TxJ-$#n%eMO35 zrkXwWYoxSHRwhg~3_)q@6h7b+Nl%lfxoQ^j+_LUgM9X8UXA`zb4>nGXapDn5lX5Ha zfiNbK){_-fY9->+B^j_7KV}<0?sLR1lGtX9`x82h_+*J`aJn%{X_9Y61SCimV)#cT zmE%93!apc+g3>XP)M464NyZ^0Yc{fn6|jAfhX~8}mT!EgDv`;j$R#TY>kfrEs#LK} zzFl#GDOM10FnA9zyA;k;|0RJbsYrngk`v5F3L+-sj4A0O1u_y&+(wl|W0ZlZM2%7I zA1YSylc|dNyn^E8RF~Pu{Ux4TK=Tg>{AonTGttw_wROJu8D(Tc zs4Fj4e0gQQ#d&3(rS8f+7~1*bH1Cxc8%#-iAaX2@Sp_nX6-2|{JrHw1%IwDRah;7( zP|CI`_b6nYMo2(D!UsA<#~&}C>r%*y*18nhgx=k3Lgti^qHK9xO88o;Xz}(mUZ6pu18e}l?aI5WEnrkzsL>4WMGG{A_7Ed%UzOQI;G#nOTTpD*B zAN{yAdeI^!XJnPN8$;A*MZM(w&xI-iC9;OcVUd`TNE@DBm^jJsP$FS?AdxZ5N}OoW zCWacGOPr!VqiHuZD7O*w`Q1o!F4xZWx{n5*HP|Xxek-b&!oQ86wh{eH$2IpSnsbJ| zN(%v_KHz_a=67_ve`88|7n0n98MtNq5~QpnLS^&kgJNnsez?S!sM(^C@wEl;6tI|8 zKC+m-bT3xclvE6U4OUtt{C#LahsRCvA0qx+ui6d+#Gi^#o5Lvz&oPxPiERc@wdn)DpbA&r00UCx--zj&Hh^BZJ z@sA;CR_02l?*vZLT!ruS(q)kDV`fMsk(KGJq~e4w8Bs|>K@ri#(bX&$m5O4xcFqHO zgFaJ1pGUDSpwpZM0RHl$Zxul<@h}KT~rZ<>yCLhW1Jd~ zVa?KI>Cp^#Cib*A*it7B6ey?b0@sg+7S=GPq=iTtQ)Xw4RM}UoC3?F8+swoi+r6^0 zhNuIUw(Fk}#-Ty@H4Jgi@}Z9FZpL!;KzWB(8nYT4vLZc=X$+Uby`2+P!);xA5%ULD zeS_aUj^B&8T1f=FA#LG{nyDJAiM77XQp{Vd^&Qq)%vwuWYbjd{8)n7!<` zs7St#J+^n^S98d!2(-hiI#BsU<5ctHBDjUBqdU6sY99hiHLUj45rpjlT%JX?X}F{b z+mm<~u)(I38l7reL(1V<>JTmGVX}TJ=e9woOrprC1J3R(@ zvgu4uplu+M_tmgYNIVh^71lBtg;!%X)$Kwi@0=X!m>{HAKHoT%yKY(%MP#hZ%v!ZN zJ4SlO)`Wl*7R!2+xza7Q2}pfXeOC0$ko7Z`a|AmLbIZ1{!FI#XitS2xu!Gv9SZCfn zp0>FtJSV(59C@=US*8gCwhgsV?LY~SjZxCG|=ijA8yXE{l^jM!h7=3&KcnZ6;r))nP%p711j~scH zDihlwfd4c4mn56RA#;GccRAx6Y{A@Je-RnH` zGV~mh!31@~@xJdCJtGx3WLRpQsg_!vKpCm9bn`rgGNy&mGZGW@BrUZxRWglJors(? z^?_-RKM_A`_M8Mw;@qSsjmwPd48MHs7gK(r*T1fxf~LG^n1WQHGL-td-tf!U*X2x^ z|N0wm>VLWR6~mN=*E}+1=A7B;N9V*%nfJQ>*DtPn8J0qL1mNu`TTemsYz?UE4WA!b zyM!%r^8ZTU9tPRIMqMlL4hxHsw`>PnURJ`E-(8++=bDptutiJ>Yfjn?Who1NN4%ta z)}|U1?v_wb)B4-g^UU$bi_U7!8+)8b?xWn3G|w}6p?ZntX*!32YfNsW|BAEhJyqT4U=cwHICtqw1({ z=^o%ZEsX0gu2F86D7UAOO0)kh8fLs&8hCw|k<|}*|ABMV5DloUXY(G^Fz>N>F-$r) zQ0%nsfOp#^__7$kj90@erRcpZ9xKFOpNQ*;g#J&4FUzh^>`D~Clq`?KBN&%!qKnx) zR{t*=c@e8m(L|SE#&b3D9c<1l{(Xcw<7+|uDjQqfR&3|$ifa5;pUdmjGnzAbHw+>0 z$~Fil8BZg84S`9-krdcNWiuv6Phkr(T@2H-8xu73#&`{AY7EnW=Z!(bQFTVAb3MiF z-rxQ1V9CJ}B_&Z(X=K1hl*&|AdA2~TbaXbLt)Zk7EW;u zWrx|WP%rmGeDTvH1cik6){#n$L?4DDw1F*v=?oDf8f+&~*X1EwE9yEwBtfJ;G`2P; z$kV1_Dp)=Ao)$;OpQw-%rfE&k_+l~@| ztCFMM@~Y=haI-P!Ktg>kZK=P+9)PJy?eFN1v+s|A^PZUEGJKH4u7wg`?1w-J(MypJ z@69PPcwbO`sMXC@A8vJ1)t|QxA1YGFxo`>@KlgB}A#`pFj7mB-WIsu3spgiXG*GJN&O`8)sT4A>$n&WcfQ}ji=r+aeqYi6w{39emb#2P;km@MadmM2R-ctY zwNNfNP~yQ4{q11GD!7C74B+=6;)|!SPa47-($qJCo8M$p;JcM(AzBi992v&-dbNsc`|>3ojl8R~Sz`NhVrY{4Cn z1D8BIOFXxBdTzmx7WG-zjT|<>EM>7#8W58m(2@x|*wk{Zq3~jifq}Wu)-gEJ@w=Lq z3xN(02_1oxtoo!m)Q0BzgC1Hz3KFP(-fAE#6HOauAVbi*X*0l)S!RiC9aDXjz&oa& z_-EW?8+y8NYF~}X=EPn2a|2_fINV6_vB>t(@Bs0A3`b*gT9kRQ!kj&^F6F*UOkGMe z@DoF)ZdRWJcI3RqsgJ=+=ysF?S4J??z)e^Rpx=GpgsM!)pGY|nSM^yAOyHzb~u5Yn>@%QJ8AegNZa)Zj$Fxaww~MCI^EINmiS1{+AWT>RLd1p zr-|d$br~O4Ak%5nrZdQ78esL~EVY(Pmh+ZD%eQfTrY_cf4cN%Qt7lzpzLUnjJ?m$| zXE5g?TDivT92u-W81FDl!7tHU@OyN9n8jhbQXsqS zV=8}rK%D!<1}tf(ruXLxe=Lu^VcpyC(K5t03VE4NbR^(VR1q377TE^vmGmZdbE@ zTvI2w@jr7q{Fr{X+gHC{whYLPmk%eqFLE`9n3fAGvof>c-lC=OdjYg+!j50K$zd{e ztreE3TeIGjEORwyIr~nS3{u$A43W2;2@aziG?HmrhlM)1w%~Td6PBB>07yOU_{%lK zwZVrTu=Iy)ZK>EH>od|@zOUF8+`OLk)l+99n&0e~-B?dSk~nuB+B>~LztVCJGSDZ%Yr$US=-AE@_X*+A87!l)A?OKeM|!{6&m=* zgoZB=zedmpHGDzvD+Rm>ok*U=yF0`=t&kVX6+Z|17iPF&kQQhWB!FfPT1 zYl)xbEcDBQTk*5lDpT$pY$aU%a_!ZE0A{+o{e}kS-Isu4L8ssWJiVI!0+!x>p!I=s z_g`*^vo|bT4i6BY34Wd#E3^0rZv$*$h1Xd>3Zjz;5i>qz*7loM4VqVYO%7Aj0Q^`S zk4C~92za^1ts3N3c=-&0pC$O}fg^us zE?nJrN6-2k5ORLy5HJclRux($Mf{iK9z8z2WBv^pd**!nWa|s__sl4nv3CEH5688x z`*Ql^?%9UWCKTHA);9QK^UL?cAB>P-ISf{Ia_^x{(;cZ6N0n*lD|PQN`U$>z$nO~2 zCWHgPKkWm9#YQzU@!t(%O+WA+dqrNwAU=-t*{cegzw+F3Oh1!9I+zKx7RT-nc*UJ6 z(=hs#Aw1^e!Nj#WaD{-GHf*%)X){mW*tL&SC2TCdG`o0B{=$-J3&-a-e*N{=&lX@s zr-PCof~W5CdBB^vEhh~m`0QT@{P#GAQkU|7@MeNZq_19Fv-!sdj|uWBxDTixGF@Fc z@}*UqhAq1=m`OVHk$Vi`V=ZhLYRJI38vgxjs>$PCnE8hGQQzePL;MEwJ5%$PCkjs0 zTg@9+zCU@xgEno(n*1nl_Z_3D*>jJ6rkF?!ToqAWP4JY6-AX?NI)hMnW2YAQt3&z_ zzh1hb%%`4OT9v=(tKzO>uZQrBLpc)u26E>e3lFa%(b9Ak7pmfnq>9@}^A$s@Gxcm? z-T02Hh22bH9Ru%p%&YJxv}4FV_kuGx?I5=be?!Zo!C|rLfxG#BW02p1Rs)aG0>%$y z_BlvHMM@q9tw5Bp{W75vKa8yREz;v>uJ zPn+I;G@&uVBw{v+H_N7}``W`6ZsZ}N)uSR>GAg3`k0pm!Nf79~G~F+kUp%lnlV=b_ zvTNRe-_{BtIAJgyT4T1qnej%3POV53TR$jk81a8u%%wG4W&Op>d6~ zm`b)WaX0h8xW*^$G|u_1ac%=x``iVgtdixTzl1deUQ(?d=emghkzJIFY5`W4s1~yK zkfh}j*(-so%4TG(gr}@8S*PTk%17ZUMDB0G;i{+|o)2VjAZ74HWl8+zv;1@zl>kFI>wmpuN5O;Yr}w2{u|p9S@>MYGctGw`L;AJ+o1-IteXW@HDzN zbrI4pPDQ^;T7f3q|8vB7UPPDwycQ)JUPIOQ<{;z2^=PLmAI<%+5dHh@ZK!=tF`E9$ zPGm3Gja&tL&_x$Y zKOkv!AL?J;kM`6Jpsyl_(8C%pI*@P&O^fiM*J=Tl2q^53faYHp%_ne)+Zd1gF&(DI z@_8ZUt>=W$p+&-1ztsxTrSpUx4PfZnGNr)CcO`9Y<{GLL{?3*C$+YlkV^w2n=zfUey zxkH58l3-yVB}iZoNQE`C8DSoL=h{|F3C|xVg}+=Ugq<3ILrA!_1POnRKsW)!61OoP z_hULtkH_Khm=ETM`C|T94wi@IV)xcEk`eMDY{@4y|54H>2hwa4nV!N^Z z*bmqr*e}>W*iYDB*l*Z>*pJws*ss{X*w5JC*zef?I1V@-I4(FoI8HcTIBqz8IF2}; zIIcLpIL RADIUS*RADIUS ) then goto Retry; + Z := Toggle( Round( Sqrt( Abs( RADIUS*RADIUS-X*X-Y*Y ) ) ) ); + case Random(3) of + 0: Swap( X, Z ); + 1: Swap( Y, Z ); + end; + X := X * $10000; Y := Y * $10000; Z := Z * $10000; + end; + end; + (* Initialize morphing *) + Move( CubeVtx^, Vtx^, SizeOf(Vtx^) ); + Status := 0; + Count := WAITCOUNT; +end; + +procedure Morph; +var + I: integer; +begin + (* Fully unoptimized, slowest loop I could think of! *) + for I:=0 to MAXVTX-1 do begin + Vtx^[I].X := ((CubeVtx^[I].X * Morph1)+(SphereVtx^[I].X * Morph2)) div MS; + Vtx^[I].Y := ((CubeVtx^[I].Y * Morph1)+(SphereVtx^[I].Y * Morph2)) div MS; + Vtx^[I].Z := ((CubeVtx^[I].Z * Morph1)+(SphereVtx^[I].Z * Morph2)) div MS; + end; +end; + +var + AX, AY, AZ: byte; + I: word; + C: char; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; (* Start with hidden page *) + + AX := 0; + AY := 0; + AZ := 0; + (* Init 3D transforms, perspective is intentionally exaggerated *) + tdSetTranslation( Trans ); + tdSetPerspective( 400*$10000, $10000, $10000 ); + C := #0; + repeat + tdSetRotation( AX, AY, AZ ); (* Set new angles *) + tdTransform( Vtx^, XVtx^, MAXVTX ); (* 3D transform points *) + tdTransformToImage( XVtx^, VVtx, MAXVTX, 160, 120+Page ); + Inc( AX, 1 ); (* Bump angles *) + Inc( AY, 1 ); + Inc( AZ, 2 ); + mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *) + mxSetClip( TRUE ); + mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *) + (* Draw points *) + for I:=0 to MAXVTX-1 do + mxPutPixel( VVtx[I].X, VVtx[I].Y, 128 + XVtx^[I].Z shr 18 ); + mxStartLine( Page ); (* Flip pages *) + Page := 240-Page; + (* Morph *) + if( Odd(Status) ) then begin + Morph; + Inc( Morph1, Delta1 ); + Inc( Morph2, Delta2 ); + if( Morph1 < 0 )or( Morph2 < 0 ) then Inc( Status ); + if( Status = 4 ) then Status := 0; + end + else begin + Dec( Count ); + if( Count < 0 ) then begin + Inc( Status ); + Count := WAITCOUNT; + Morph1 := InitMorph1[Status]; + Morph2 := InitMorph2[Status]; + Delta1 := InitDelta1[Status]; + Delta2 := InitDelta2[Status]; + end; + end; + until( KeyPressed ); + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw__/modex/DEMO04.DAT b/16/xw__/modex/DEMO04.DAT new file mode 100755 index 0000000000000000000000000000000000000000..72aaad08ac55e4d161e7868374296a4e42554684 GIT binary patch literal 37662 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%0D)*4A2IO9KMZYD#oU43C^WOCfTg8_%RD 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�-ncKj8QX2BIutynAlnfJ{;J0ue86t5F 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 XG;Ye`)EVP3#M6mPm!(a=?*#mR$DZhs literal 0 HcmV?d00001 diff --git a/16/xw__/modex/DEMO04.EXE b/16/xw__/modex/DEMO04.EXE new file mode 100755 index 0000000000000000000000000000000000000000..1fec5e8aa383353d986ca1e4420838b09e61eef4 GIT binary patch literal 24384 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 Im202>1y)VB#{d8T literal 0 HcmV?d00001 diff --git a/16/xw__/modex/DEMO04.PAS b/16/xw__/modex/DEMO04.PAS new file mode 100755 index 00000000..1a946315 --- /dev/null +++ b/16/xw__/modex/DEMO04.PAS @@ -0,0 +1,198 @@ +(* + DEMO04 - Multiple textures and triple buffering (3 pages) + (c) 1994 by Alessandro Scotti +*) +uses Crt, Modex, Threed; + +const + MAXVTX = 256; + MAXCUB = 2; + MAXTXT = 2; + Trans : TPoint = ( X:0; Y:0; Z:0 ); + TxtSunDial: array[ 0..7 ] of word = ( + $7F80,$0080, $0080,$0080, $0080,$7E80, $7F80,$7E80 ); + TxtSapphire : array[ 0..7 ] of word = ( + $0080,$0080, $0080,$1F80, $1F80,$1F80, $1F80,$0080 ); + TxtMarble: array[ 0..7 ] of word = ( + $0080,$8080, $0080,$FD80, $7F80,$FD80, $7F80,$8080 ); +type + T2DPoint = record + X, Y: integer; + end; + TTexture = record + Desc : array[ 0..3 ] of record X, Y: word end; + Width : word; + Data : pointer; + end; + TQuad = record + Vtx : array[ 0..3 ] of word; + Texture: word; + end; + TCube = record + Face : array[ 0..5 ] of TQuad; + Base : integer; + end; +var + Vtx, XVtx: array[ 0..MAXVTX ] of TPoint; + VVtx : array[ 0..MAXVTX ] of T2DPoint; + Cube : array[ 0..MAXCUB ] of TCube; + ZList : array[ 0..MAXCUB ] of integer; + VtxCnt : word; + Txts : array[ 0..MAXTXT ] of TTexture; + Page : word; + Palette : array[ byte ] of record R, G, B: byte; end; + TxtDat1, TxtDat2: pointer; + +(* Add a new entry to the vertex array *) +procedure AddVtx( PX, PY, PZ: longint ); +begin + with Vtx[VtxCnt] do begin X:=PX*$10000; Y:=PY*$10000; Z:=PZ*$10000; end; + Inc( VtxCnt ); +end; + +procedure MakeCube( var C: TCube; X1,Y1,Z1, X2,Y2,Z2, TX,TY,TZ, Texture: integer ); +const + FaceIdx: array[ 0..23 ] of integer = ( + 0,1,2,3, 0,4,5,1, 1,5,6,2, 2,6,7,3, 3,7,4,0, 6,5,4,7 ); +var + I, VC: integer; +begin + VC := VtxCnt; + C.Base := VC; + AddVtx( X1+TX, Y1+TY, Z1+TZ ); + AddVtx( X2+TX, Y1+TY, Z1+TZ ); + AddVtx( X2+TX, Y2+TY, Z1+TZ ); + AddVtx( X1+TX, Y2+TY, Z1+TZ ); + AddVtx( X1+TX, Y1+TY, Z2+TZ ); + AddVtx( X2+TX, Y1+TY, Z2+TZ ); + AddVtx( X2+TX, Y2+TY, Z2+TZ ); + AddVtx( X1+TX, Y2+TY, Z2+TZ ); + for I:=0 to 23 do C.Face[I shr 2].Vtx[I and 3] := VC+FaceIdx[I]; + for I:=0 to 5 do C.Face[I].Texture := Texture; +end; + +procedure MakeTexture( Idx: integer; var VtxData ); +var + P: ^word; + I: integer; +begin + P := @VtxData; + with Txts[Idx] do begin + for I:=0 to 3 do begin + Desc[I].X := P^; Inc( P ); + Desc[I].Y := P^; Inc( P ); + end; + Width := 129; + Data := TxtDat1; + end; +end; + +procedure Init; +var + I: integer; + V: integer; + F: file; + P: array[ 1..768 ] of byte; +begin + (* Initialize objects *) + VtxCnt := 0; + MakeCube( Cube[0], -64,-64,8, 64,64,-8, 0,0,0, 1 ); (* Sundial *) + Cube[0].Face[0].Texture := 0; + V := VtxCnt; + MakeCube( Cube[1], -16,-16,16, 16,16,-16, 0,0,0, 2 ); (* Sapphire *) + tdSetTranslation( Trans ); + tdSetRotation( 32, 32, 00 ); + tdRotate( Vtx[V], XVtx[V], 8 ); (* Got to rotate this cube *) + for I:=V to V+7 do begin + Vtx[I].X := XVtx[I].X; + Vtx[I].Y := XVtx[I].Y; + Vtx[I].Z := XVtx[I].Z + 100*$10000; + end; + MakeCube( Cube[2], -64,-4,48, 64,4,-48, 0,68,56, 1 ); (* Marble *) + (* Load texture and palette *) + Assign( F, 'DEMO04.DAT' ); + Reset( F, 1 ); + BlockRead( F, P, SizeOf(P) ); + mxSetPalette( @P, 0, 256 ); + GetMem( TxtDat1, 63*1024 ); + BlockRead( F, TxtDat1^, 129*286 ); + Close( F ); + TxtDat2 := Ptr( Seg(TxtDat1^), Ofs(TxtDat1^)+129*254 ); + (* Init textures *) + MakeTexture( 0, TxtSundial ); + MakeTexture( 1, TxtMarble ); + MakeTexture( 2, TxtSapphire ); + Txts[2].Data := TxtDat2; +end; + +(* Sort procedure, not worth optimizing with only a few objects *) +procedure SortObjects; +var + I, J, K: integer; + ZMax: array[ 0..MAXCUB ] of longint; + ZI: integer; + L: longint; +begin + for I:=0 to MAXCUB do begin + L := XVtx[Cube[I].Base].Z; + for J:=1 to 7 do + if( L > XVtx[Cube[I].Base+J].Z ) then L := XVtx[Cube[I].Base+J].Z; + ZMax[I] := L; + ZList[I] := I; + end; + for I:=0 to MAXCUB-1 do begin + ZI := I; + for J:=I+1 to MAXCUB do + if( ZMax[ZList[J]] > ZMax[ZList[ZI]] ) then ZI := J; + if( ZI <> I ) then begin + K := ZList[I]; + ZList[I] := ZList[ZI]; + ZList[ZI] := K; + end; + end; +end; + +var + AX, AY, AZ: byte; + I, J, K: word; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; (* Start with hidden page *) + + (* Init 3D transforms, perspective is intentionally exaggerated *) + AX := 0; AY := 0; AZ := 0; + tdSetTranslation( Trans ); + tdSetPerspective( 600*$10000, $10000, $10000 ); + (* Main loop, all magic here! *) + while( not KeyPressed ) do begin + tdSetRotation( AX, AY, AZ ); (* Set new angles *) + tdTransform( Vtx, XVtx, VtxCnt ); (* 3D transform points *) + tdTransformToImage( XVtx, VVtx, VtxCnt, 160, 120+Page ); + Inc( AX, 1 ); (* Bump angles *) + Inc( AY, 2 ); + Inc( AZ, 1 ); + mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *) + mxSetClip( TRUE ); + mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *) + (* Draw objects *) + SortObjects; + for I:=0 to MAXCUB do with Cube[ZList[I]] do begin + for J:=0 to 5 do begin + K := Face[J].Texture; + mxTexturePoly( 4, Face[J].Vtx, VVtx, Txts[K].Desc, Txts[K].Data^, Txts[K].Width ); + end; + end; + (* Flip page: at 320x240 the Start Address Register Low is always zero *) + case Page of + 0 : begin PortW[$3D4] := $000C; Page := 240; end; + 240: begin PortW[$3D4] := $4B0C; Page := 480; end; + 480: begin PortW[$3D4] := $960C; Page := 0; end; + end; + mxWaitRetrace; (* If the frame rate seems low, try to remove this line *) + end; + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw__/modex/DEMO05.EXE b/16/xw__/modex/DEMO05.EXE new file mode 100755 index 0000000000000000000000000000000000000000..21a7c207f7134ed187a08530637509b96b37b19e GIT binary patch literal 22528 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 CoI~RP literal 0 HcmV?d00001 diff --git a/16/xw__/modex/DEMO05.PAS b/16/xw__/modex/DEMO05.PAS new file mode 100755 index 00000000..819c5cf3 --- /dev/null +++ b/16/xw__/modex/DEMO05.PAS @@ -0,0 +1,131 @@ +(* + DEMO05 - A Gouraud-shaded rotating torus + (c) 1994 Alessandro Scotti +*) +uses Crt, Modex, Threed; + +(* Define ALTPAL for alternate palette *) +{$define ALTPAL} + +const + MAXVTX1 = 15; RADIUS1 = 70; (* MAXVTX1+1 must be multiple of 4 *) + MAXVTX2 = 15; RADIUS2 = 30; + MAXVTX = (MAXVTX1+1)*(MAXVTX2+1)-1; + MAXFACE = MAXVTX; + Trans : TPoint = ( X:0; Y:0; Z:0 ); (* Object translation *) + Light : TPoint = ( X:0; Y:0; Z:-63*$10000 ); (* Light direction *) +type + TQuad = record + QVtx : array[ 0..3 ] of integer; + end; +var + Vtx, XVtx : array[ 0..MAXVTX ] of TPoint; (* Points *) + VVtx : array[ 0..MAXVTX ] of record X, Y: integer end; + Face : array[ 0..MAXFACE ] of TQuad; (* Polys *) + Culled : array[ 0..MAXFACE ] of integer; + GNrm,XGNrm: array[ 0..MAXVTX ] of TVector; (* Gouraud normals *) + VtxLight : array[ 0..MAXVTX ] of integer; (* Points brightness *) + Page : word; + +function GetVtx( I1, I2: integer ): integer; +begin + GetVtx := (I1 mod (MAXVTX1+1))*(MAXVTX2+1) + I2 mod (MAXVTX2+1); +end; + +procedure Init; +var + R, N, X, Y, Z: real; + I, J, K, V: integer; +begin + (* Build vertexes *) + for I:=0 to MAXVTX1 do begin + K := (I + (MAXVTX1+1) shr 2) mod (MAXVTX1+1); + R := RADIUS1 + RADIUS2*Cos( 2*K*Pi / (MAXVTX1+1) ); + for J:=0 to MAXVTX2 do begin + V := I*(MAXVTX2+1)+J; (* Index of current vertex *) + (* Compute coordinates of current vertex *) + X := R*Cos(2*J*Pi / (MAXVTX2+1)); (* Get coordinates *) + Y := R*Sin(2*J*Pi / (MAXVTX2+1)); + Z := RADIUS2*Sin(2*K*Pi / (MAXVTX1+1)); + Vtx[V].X := Round( X )*$10000; (* Save coordinates *) + Vtx[V].Y := Round( Y )*$10000; + Vtx[V].Z := Round( Z )*$10000; + (* Compute direction of Gouraud normal thru current vertex *) + X := X - RADIUS1*Cos(2*J*Pi / (MAXVTX2+1)); + Y := Y - RADIUS1*Sin(2*J*Pi / (MAXVTX2+1)); + N := Sqrt( X*X + Y*Y + Z*Z ); (* Get vector length *) + GNrm[V].X := Trunc( X*$10000/N ); (* Save normal vector *) + GNrm[V].Y := Trunc( Y*$10000/N ); + GNrm[V].Z := Trunc( Z*$10000/N ); + end; + end; + (* Generate faces so that depth-sorting is not needed: there are still *) + (* some *very* little errors, but this is the best I could devise *) + J := 0; + K := 0; + for I:=0 to MAXFACE do with Face[I] do begin + QVtx[0] := GetVtx( J, K ); + QVtx[1] := GetVtx( J, K+1 ); + QVtx[2] := GetVtx( J+1, K+1 ); + QVtx[3] := GetVtx( J+1, K ); + Inc( K ); + if( K > MAXVTX2 ) then begin + K := 0; + Inc( J ); + end; + end; +{$ifndef ALTPAL} + for I:=0 to 63 do mxSetColor( I+64, 0, 0, I ); (* Blue palette *) +{$else} + for I:=0 to 31 do mxSetColor(I+64, 0, I shl 1, 0); (* Green neon palette *) + for I:=32 to 63 do mxSetColor ( I+64, (I-32) shl 1, 63, (I-32) shl 1 ); +{$endif} +end; + +var + AX, AY, AZ: byte; + I: word; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; (* Start with hidden page *) + + AX := 0; + AY := 0; + AZ := 0; + (* Init 3D transforms, perspective is intentionally exaggerated *) + tdSetTranslation( Trans ); + tdSetLight( Light ); + tdSetPerspective( 400*$10000, $10000, $10000 ); + (* Main loop, all magic here! *) + while( not KeyPressed ) do begin + tdSetRotation( AX, AY, AZ ); (* Set new angles *) + tdTransform( Vtx, XVtx, MAXVTX+1 ); (* 3D transform points *) + tdTransformToImage( XVtx, VVtx, MAXVTX+1, 160, 120+Page ); + tdRotate( GNrm, XGNrm, MAXVTX+1 ); (* Rotate Gouraud normals *) + tdTransformLight( XGNrm, VtxLight, MAXVTX+1 ); + (* Backplane culling is not really needed here! *) + FillChar( Culled, SizeOf(Culled), 0 ); + tdBackPlaneCull( Face, XVtx, Culled, MAXFACE+1, SizeOf(TQuad) ); + Inc( AX, 1 ); (* Bump angles *) + Inc( AY, 2 ); + Inc( AZ, 3 ); + mxSetClipRegion( 0, Page, 320, 240 ); (* Set clip to new page *) + mxSetClip( TRUE ); + mxFillBox( 0, Page, 320, 240, 0, OP_MOVE ); (* Clear screen *) + (* Draw polygons *) + for I:=0 to MAXFACE do with Face[I] do + if( Culled[I] >= 0 ) then mxGouraudPoly( 4, QVtx, VVtx, VtxLight, 64 ); + (* Flip page: at 320x240 the Start Address Register Low is always zero *) + case Page of + 0 : begin PortW[$3D4] := $000C; Page := 240; end; + 240: begin PortW[$3D4] := $4B0C; Page := 480; end; + 480: begin PortW[$3D4] := $960C; Page := 0; end; + end; + mxWaitRetrace; (* Uncomment this instruction if screen flickers *) + end; + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw__/modex/DEMO06.DAT b/16/xw__/modex/DEMO06.DAT new file mode 100755 index 0000000000000000000000000000000000000000..1ac2c2bb8f8c79a7cf1f3c968f75e8e5ac8cd705 GIT binary patch literal 77568 zcmchgjbmQbeczE~S$ZDHkC7~cgskYzI5w7yz#^nkV$Tp#mQHOv6)P3930bl0tPRBG z%`mnkOVUDzaAy~Z6>pO*b!26B?JX|`ONvv-oN0;I)E!yUHEk2N@n7uw{hjx7&%Mth z13MwlJ?GqWU(VlzwX)z`0ST-CUGbz@7zn!4t? z=H`a_`tq7p&8r%k8yd>>^(|}a*R5GoDX%K8X9(=&20_WbzN8A-co5>+p@88eS2g3`j(s4S8nL4+;mfA z&6?K6#tm!Nv^B16ZE9*;S6W{}yR~i2%{Q(qZ78j4U%PfgV`JCa#*W5yJm2zik zU1v*6XLIuhn%4HLUEAHhWkX|p+|b(Ex?#ih8*aGahRz#X+q>3xZN$#5&J8!M@4Bh0tE;cPuJ8JFo0?m< zS8lj%-Ho@e>)6!RI@r3QudD6W^*7yq{f&2A-}#ZYjkkC9T-Sfyb=$7Hp>JK+z`8X9 zH?HkpUm4ucvZ-s$mYZ4zyV?iZHx9J7Z)?A4+lIDHU0s{H)(>v%+ICaR@W$5LZd`v` z*GxO~NU0eD)Hf`IuZCmGuKGgk@k9?rHvA4N-prxh1xp~vtrVqBX zY+k!|>-sgl8`t!Z291( z@~vCTTenuW-cq`CsJwl!WpH!*=FJ;7Z(BdOb>l5NHui5S4-b}yhs(n)n>Mu!Zff2% z*t~79ZD7;-!GX?g{jDFoW&PkS&BL4458u3T_?B}2aCz%+YwvJ>e}C`hfr0*;H}`Eu zx^-alwr!g?Z@OhG{@c2B+qR*>Tec4k4c*bdd3by8hi=~bp{;`-9=vt?@CSG7=-;&q z|83j8efW-{;SX=WZDhyDFWo+}YuAns-SOekJ3sufk9};{yG|qdY1gwR?HV1;G;@1R zE4$sbYouT=n(YeCHX1b!_XbT-7=1QzGq%yFy$O@q<=uLAuW7|CuREIG#5<3>T=Bi` zde*22}QltSp;ede}zWom*O&fH3H z{-_`Jd(;`8+PikNJ2;cMsPk9F_oc^4Mee1SUpB|6za= zx(yc18Aj8jgDd-ml}a>A+TLm6u6Sek|MM?jG3lkKmAP+oPtn;-b$SaX22Y}aI+fc| zjbQQq_(qj+o8IIpL0?@?oqMZMpY1t$$q9!}Bg_+FY~K1bka|v%o66Z|s-Jz<@f*n< zZdA{5x?#FwB^r{myZsA=dFfeL6_>*APVQ%7*=R1a&4|$6L^5Mwxb3sQ?-Ihzq7>d~ zeEv`q)d=R0GbgnY-8o^d>WjkeHaml@zBX@YVlqQ4uCO9B@^U;XJF(yG&X9}^ z%OKhnk~3W~yA2YzmG=3&Rl`x&_lZzavOkZY-1RO9VdrGVTw`*!{8H4{T?sH=)vh!; z(;|Uzmz>d%vD>2A5gR#VIv0}8>^2oI1zlfWUbY%BEwJU+8TDI7bm8HaQbFcw=0t(E zo_FcF-8-3{b2X`)Y9uXpyQY>K?%PPh)unPyWFa}z*2AH)&jo!4Ih*2vitU45)0|#< z`3D7*QoF9IBwY*Or{_du-JPjouc|k9>&+;zjykmQ~Z4^N?r>ohvq1ZZr*NJop#*6U0@LOCGD_q@@ZCTBKz1dT`|qH*!rP;)7A zmf=etJL1Dov+LSL=K+k-nDXxDJySH5-qsLy;tN=ZgblFFHbXEHX^hO4L-%Mg6=Yu4 z2#IcVXEvmZMHZJmW`1_((kovfHE;6v8c2=A1$85EgqO#$7rqZ2_$Rt-~Xe|1z*i;z~PG%4iN z$7CqFkY5^+XS+p&)oAei^DY{(1dZLwh?dyTh8XBW@0cP}tuEqHLoov@Q4#R-hq9QS zlzkDVVEg;c@MpI;pl~r!Vln5Tt)mR$ifWWn`)fcIHA#TVsS5d_uSsrRC2^!JTpFeA z*s!L^peH{R4kB0H?J@R76_Sk^7b59m}f-F7a*AN1^AKVuMP(3wU7 zLh>`l?5z}4XOwP{Pbha!RWQ{XOy1qr-acmd8Ft*F&)IP+JN6kgdRr}UHi!*4gu-@> zEzPBd+FU@nJF0`J-U8^_)~s36);?zWIraVQXSRo7CSQb_c2&fI2%qm_SXKk0bdy{_ z`8%qEsoLVor}w8f+$sFJ#;T~z+uc?D8DhY(Dwi4>Oy1_ewHa{S{<5#X94 z%Mp*DNDrHF1wjiGti}{651q7BwTfR??F4Z^jRb1|Q?<#JNsnCHUH2d4t7OMiz>fh; zv;gCyQ@zh&>~VZ9g--To_;rmhq`-SIHtIP+}B@~r0C(( zx8KRhaZi83&rZw|=&BRc>dPURbu@JNZ>i0-= z%l=Szy+sFlubzMH!s*v6KMl~DZ#4c*e#+zb=T<4mRMnuYLl;ZcKcD1@HX>q+;~91t zdT48A?$y1J2lAdjPLy`Ju*YFN4lBFA|{&2fY^mAN3d5 zYum?Rs5Ds)cxRNULS+|(8jG*LCfHDQ>Nsna13r89JS;fUpW`>a#p4$ZfCdkYG#JNh zz03Flv%EbsM@v(^Vt(zuPABu+LRfz#KzA1-I;K~U&H<2>oaCW8!6*Dc?!u|*In{#J z3mq2l3k}!-aXCR#jUSqO5(BD~Ru#dO@@roqzhJ0q0Xj+K_pi>-ERiffC?~^xG~9AOHSJ?Mmyu4B#NKH1p6d7T~O`Ng6Z_^XbHiI^jZo+F-gFv+gqb%6dpU4jmLsWN1j> z*^d!}hFh($d^@*IVs~-%N{XYfp+@BsiPo> z=G<}mKXD>fBKToi-N3<#YPM)59YG!su z+F{@9(&I~)mma@wfoc``nbA*~FuZV<-xzKbJ+rFQ=!OQF8EiF0WJypMOsQmCZU`+b zJ%^@dP+bu}hp!qxS#=`63#T#e&t95aoCS;Hr%s;~&CS9n=a&BG(fL_$oYiE-#PM-z z=FNw{dkM7o->KO*_C9mVkPiJ2mpTonpq%`UvyQcsI4jWOVvI@qB6>6y;Xo;Mek z-sHqg{0N&7@!aEkd%k#aZtjgmG@t(@@pX1?xxC0|n-dn}KhB;#rywTzT~YiZ)oFBQ z;~3M7M*=>+2zN*5OhfBG-fMo}BsiVWX%1v_Z!XNwEna@~@*DG)zrXiOw>;I^x%bGC zqfb2rQ>6kaLiml@*^67iYw7aEE%(jL%}Ig$o?e)9_6rY;gk=N)2w#u!kE@W@ekUid zwC2dpuv6PmgslN5CBj&ChMn4q{+`=i;{s~U`uirwKZ$^KI1Gn-`N?ONo<97=r=R}* z!kc5%6w{W@qcc<>31gD`#L>C=r46Wm`qv)syzh}GE-&>+GqC=i@*g??BtBWi0>Ko& zWzk>ADqT_p`AKiwy36D9e4g%H8?Dm!T7TaHzw_)W*HB==(BSOiuiUwiXu z&4int!%w^c0m8|^a`!&@@b~XK47k5avY+ZY@_Ezrw=ctib2wlCNDGFCSF2baKjnV) zLw#kNX=Y)qCP-6fR44Wr9@@3+izj5#8`%?RH(ffcH;UE6Tvmr@n{yOx>^=QM- zN>4H#KM$QjSXT#zgPNUc8W9Xu7jn&5{0AhMi!9i24g93LjO`G@9Fd1~SVn*bapY(AoK$vR_!&Y0ludXmDx~ z@$w){%ox8p+uV^9p$)Fz6MoqjIQ~M$zq1(XDHX=XTydFOT6#KV!b{&@3aN(hSbA(> z>vv=X6nyej$lf?q(e(u|erkf53Qs@nI2U-ktA!;eE15W>(sqsn}Qh{@eJ}3jS>uEj7?d;59$Lf2r(7>7Uj9o+pKX3k)#}A=P z1kDyJ-a1xH5(G_T(~PS50J>OxnWQiWCpRS z+FFMnG?!J=3_p*Z!tV&mTK`}W1UfT*clMjdPo}BDPn!h(W6He zF^!Wo)GGX5R{hr!#1migL*lA*9cnZDGU)UPd^3hGs)RwH(O+!~SYDTE(VyYR7={y& zxy3iJ>gSSox*D^$9GyNM<4fyrIp9}ms3?B0#Gyf@KM*wf%VVd`;SnUjR)4Mk{pTn1 z1WdiSKDFTR)d(zX_T--(mPIVR@Pe_APtcS0`vVt)aJ8VWBI<+u3_mImJ65>LIyA_E z)UEZuC;SpG5OI7L`H2G-?}0h)VWqtg$_h$P&Er`U-LE(LFdziECBA0p_}GxJX@J^V~(dyUS*yOPQF z+;@~y5Ig{J{Nx3Wr2fcH5d@lw;WsieJUl!CegHTKw9?2awUDAEh+`T2h#9YpU(N%} zBtH)y_??9j7W#WQq8k0JIDql(H;12^dB}Rx%pzVxI5jsrKY#gY582)o zS#!_KsS{_;oFPCCuiATX{43(e;JH$v{wjmQuVbhI9f$p*UfHku45a0ALf+bL0NU|; zuEsa8T;F|ui5G~l&aRf7@$BP|Id_8xK8_WH>C124*keri@yFcxYRFxjnm%#-#EEm~ z@TR^3DDq45o6u+&Jahi0_ziV*jA(v9XyX@yF`}l59=j}Pypp9nNx&nw;CdM}$u0nL zp`GvhaOH&oFE(oS|M=!D3x|6i-7>l5lTSar)t#?~+|mpHo;h>;gf`)G`VHQs{z85X z+u$#T$ZvQE!Jy1WGW@K=F(5PSVuE%)67a|^xLyWLviwL)EncbR13<*u(;v@%_wwT9 z%TI1wcxnNQeh<6T)sXwuuHRT(IC19OxpOBt1fDo|R>`kGe=tdXn~0Su;NE0qN)SopYX%m zlWBg$QWHOsDjpBNFXNv?x$G*VHM0bx-e#89u=uomMb5Xqec`(&kDt+hJ6kQe7pIieR|p(p&z!=(G%$!f{nH{fl0hYNw8$-*bNQmL9t)01*np`_hB(Qy#`m&p)w3`(65@6MFdL zSslJKza4_WF5H8i%;bhK0U3o$Z z7KVHhH}}-N-pQ(GZ{Btoqn`|a8lM^d^7#1=-uT8#$WKN@O{r*;?@ENc*5A&ZD_ubK z@g?RTf2vlP*i~3C{|s89L79_4fTw0>%p{~bI%)CZ^l_QIozqi~YWkzmx>RYTw?)GG zi_#zWNlg(v*_R?{ReR0+f;aH9`uisOCrJS6zo;ZcCgJxe|Hz>Bw1}w(LTAJ;IHNkX z4*$~nv+P8A!jF>kBZ;?>}mM{Jk5zXzQM13O>A% zKeu#)cd}~PEuWlGgCD|XgRj_rg%DIH39f>p9TMa>g!skqt5t)VV91WA20!&sy|x7y zub;*I{#TGQB5Qzy=xP_bXF{KVa|i=c)D1mQO{1otrr zehq4H6ppoOkmt%IJAbRqfp{HW0Y3+ji!uDej_J=I3DyC<^QN+wreyGw@1aJ1poY#; za!7dc3!GfQqx%(p5)}d@l~|Ra8Uh2u)g&#y=X@Tyd9QPRo9qi5f&M&x%6v~fvUdge z9{t1PvTUUSXKTL2_Uq$w{06c9V)%g|_~~cr8DZH9-+g2WzEAwFe8bo;6gpP9bznkaIuV?(@jadmZ)L=og5*S9p^A&Yx!l0)8isPt82yovSF@Gd+cgn*&Ha zYjGE?UwOU6_}8q)KUx1%{=@L|HE0P|n|8R9s~>I0pJosFJo59dr+%C4?+{IZyPo=OvcHA;LoJa6KRm-YJ~h3#^rSmiVQvw_ACnlcntsSx?GJFMpP%%^&#aLM z7hW3hA};x%PWTP77$g@EW?m}K;i(C_y*`ipyz8moCd=;|>Nhqce6U{`{=jdt=TUdA z!rXlv{un(Y9k(fxj9>99LdwcKIF5AzRMzS5HB^AF1puOGzkpXTwy z`$Nq`y73B8LVD6@t4o=9|0D$Muog_XDu-fDjc`aX$)TCJ`4IB7h{sjUZF8Sg0Qzbw|Gp32!vVo*#70U24Sh#XS zp&9am6Zm?{&!_bl4?cz;fBn@yF+&E+cjq9%sp-8lOBWYES<4dYy~cd0I~-2%u+{YI^aisb#c!~}mQ*J)ZFKNHv zclNBscV15)L_^1?j$;N_oBi%R&frh*;R7JWCD9Al#!td$ZND7*EWZ@KW=RAH4H}Nk zV!2s%q~;z#y)XPMHPe6e{v-ksc#)}@tvBvv@WK=H*-C!;Bu0N4V4?k1@W(@# zenkAhA|XEokDmfitt^NwHxpGd5v|(sKJeqjmqJ0Z{LT{x0Z!d_-{%ik9RX*iU$oZC zbMZVhW;v-6;Mecspa16g5AbU>{P?(1=}+-<@rxo*u>ci6Xize=W4p8vQ50#e0HBje zVB&BXQ9@kt>e(~WP5H0@#R;FplEBo=%p+C!ZCRQ^@TY?oeJ*&U6Br8|z^}{Cm&8*b z_KD$&=ui1y%a1+)`eTC-hb5>15*(9^gke)%5`N|(a)2aVSP?&Ycw`V7fS>^YNC3FF zP#i;deUfXZ+IhGWF^EA)z8(0FBtOP_NC7{LR-!+}5A38xz{L>M%tU&IU`m6EU+p%$ zGJZ5L(`{?QB0#ZVtil{Fev9Mql+0Pk-kt|OT@lslPV*BsmLKOI@E7uGn#dCR)BL#g z6A2p0iS7zDX!zlakqJv$b*^^h{47EzKp6pHz!czPUv#Gob6xN*kI!JZRFRM4hi?Mw zFkDQ)BFx#dIsBBml>caMY&85J6;6Kzq9`=dAVO@cR!0EytyuHpccHQlRWj#w(cd2p zekgMMvq}1{`6>CG0lsO-FMk01^-D`*3%|`5cEx}_eBg%=8VfQQ3Q>*UAA5R9KV@rOE)F5m|@0mJq9v6E`~1#jc~{D4w*Uw`7DkYAw{ zYx}Q3g4f7T0E*4Yc%~x2nQi85u?=tdwR@MIz>_U3-P8M?IOjQX3K0Pe^@rIAzLVJz^VVw&7K!?oQxj`Q^TeN|#y`iewXsf(f7BmGJvw0|1b}AP%O#kxVZ)KzG(rA_CsF{- zE4&+iXVF_)qX3*fy!4Ol$(~xAS=g{}OMBPh8`a8m*CoDkK;uo*g9%Frh`r|&zvvO* zq-KJ@+s7=TxsmYjA6MHs0t!D5o0m1}Q`>|F9YdZfOmtGJCTBWlySy^{Rk9%ruE0Qo zCyviNe)y~UY#X*sPtVL?J>lrg%%Z$j^ze)F&`r&IwdS-pHwt9vf^`0yKf;f;kH`KO z{MZ*bkJe^9Ehj%D3{X%9hd`#V>#h_MtXYF{1-Xhkm8UwFT>(EEy&$9eN`3+m>jxJX z7LEOOE#VpY)bwLrPfbrxFSKvK&#fVD#y~0lK^^O#P4cY%)?b)6=dQ&1GriILq+fjB z9^9(&Gj70eEF!2-nTwgNs!dAJ0d!FDPe^5wAO0DBY6>C(AJFKBVX1$u0AanBg)RC#GaHzg&8>BMZR5y3R*P{ zd-{@nU_}25`Tgn2*pc5J9fyVd=z3SgPsfUGsEi4E{CspeFMGpCZ{_@~^;-V{O7OIc zNBL?g65?cFgR|h&1c4!pSOtDq=sW+-m9ry1^XFUm{XXe3dxB1_gr8YapsjmsLMzt% zy!}CzyFtve;T7}C;sd7RGcy+t&m4xKis2HRn%a@0dQS+E;x)3na%Ixsv-XSdMe*a5 zp}PHYcw~|RP-PuMUxQla0W`mWH$q6v0bD6R51$Nwj9y@)7oWH|HFas)%+gTBuuvQZ zKw?$kn%OPybUkgw?}j1a&)pP1K0dF?Pvc5#EEq@7R;4mJN)%*gBD4Ri?g=s74nkdseZF?46A6}j;pZB(W2e%Iu#Tv^6n4Wi#(Uj(1!hxkR7|Ii?8 zW{>cxY45A5cz}0eL(m==WrBIL4{(M2EI!gZa|Y&$5$@y+TrOfgtWRmf#a_NhC7l|V;%YV>~iL036Q^|_(i?ogASd9A3iic3138a?3HSxH~N4qyNKZMu)7*o zcU(%a)92*I09*+_s*l7-3dT!_qBRJSQsi?XvMJT$fX*%meGx>WPYdA{5KPDpPTq`}_6ktBLubTj zoN{6T>l?ravlXEclv*zqe#Ay|K6h=QG5PTy*lI78)+>I0-`%C;s6Qk?QT_uSMD!Q( z3l6FQAE7A7tww``L)Jy;Ohb~LTnaya6cBXqkTasN+aCfI-+QLfGVp_!5P0h2{P}mu zPTfgK@$*I`pC57A@lVZEefY^gUM>$MW;5!p-_T8K+DZ$$nPAV zaSJhe5XwBhRf5aStYFl6$(=4k~cWznC!;{G@#bE&<3Y+V2Bh9zk9*Qj2> zqDgbq6O`^qldDOCX4D)aL6~iU$(r-ZR_13;(9Aa}F(6jqS47YV&$}Kb(^Zqc6VuMwa4|nR5BiSx)@J!# zt2db`a@T$^1~!0Ou6v1?b`3u-HkQbh@G@B zv9t%!3{-A=;u@!9at8bp=5ez00)qOE6}Q$77_}Mv#+Ubilv+K7^Tk_{v|ldbSJNNQ zX#p0nV>`JkHfF&l^EKLvD5C&+__Fa|_D}j9+Tz@DmK|9J{EYF*w`=ZJwj35|oERhb zOse<~4EYW|`H9DtKVB6XM&0s@63h7&>AbUbvtQqhDdubkhy6v>MEq>{6|;)>=CDif zQ+~jiiGzsWSQ}Qb_e@IsEE-%XziNCn7pqf5&h}<xP3DRg2M7 z-CKoSN`K@d;}33I-8*Y+!ViTZUm2Uw0EM4#zqws?CK-)tDGcOi1`~(KnR|~t21e~BMiEj|UwZh1GYU#pQ1Zzg zUM0claBc(oLsO2hOYS44k&RY3S@c$yzgpDE2wQLM^D zodQ1&$|1uP5?ccr)Fd7$#(pmFvdfP!8Csg42*~-`vpH&^)$76qx46rb=do zpEVKW&kI6>9yOJfK4d?9e%Tjb(!#5qT>wxAbecLiCv{4;OvLFnnjX;=Q?7f#MWf4hQ5jnfr0*%1Fn|GKF!aaWQ7C`J3=;B0 zLgkHF!vBIF47dUTI)37X9lwLL}u*b65EDXba!o(XSVL^FV1y!8GZ!|c%JR* ze!2_CIn^M#XhhIEMxW1ZxQ|Fk4=V?am4?Rg1V6v;9>EBkD!P+PP80NQ0$Ib&ZKE#a z6=eZ+c@GrpQA%h1`v|YDOMZj!diu6(19!Ns(iyXd{HQ;;kg-X6Ux!VTiBy*jm}^P z^(5g-LnHWA8k@(3oBSD)&(AYI--;ccWQ98J6E0pI9%15$rBlog0HM%v zkDq^bl~=bTN4h%;Rhl`-Yly64lgUX3Ty4f^!xKfuk-046h(GT;i%XNKu0j( zhwzyK9B!>#ar#T#lRVB-NBZ4Kw$zn=yFz{roqadu|eTq4?{fiFCl=aEs{ zuoy{jnEw`NHYo$vAk+_6VfsOStsRxtv1ME%dm%S=u8<&a+NA)RF1W9K1?L4~^)Snm4ux8?&h`~)ERA%KCSX|0ScXZSgI!hS^r9XsYS{M-#oBpJ4@ zUh+F{TF21*GTZpaWb@7v)-z@0#~Npd>Q}4C5Ah4Y!GDY|i~jU=B6fjz0n*%b?v42k zB7TmYd%rzwUcICN_zitt**sfjsd+Ufb`pH+lL92cjQ;rg6~Q%B#wYQDmdrkq@I3lF ziFfPXUD&L*n|E#mm|`c#gzal6#YUe+7S`~T_U_`0Tu<&%;aiXUOh|C&Zu114tEX54 z-I5QAgc zo``p8`Q84Zj|BurcQaXjg3s{diSeuear7Q!19B+5ylkH4j4fZ8teK#_EuOuYo$8f; zKvCW>2;2Cia`JM3IXZbw$M0Sy18{Wr#Kc4aKYj(R?K~sj?)CXi{9w|+(_1pMPo4cP z1UE*nV0I#FB7~q#reF>z*oMah4RfFc)jYtSA~;$XTDATJ-@UgJ;7+iUB>GeGk=G~j z>n|AgXuooBM+ZB-V|mi@o8Uj+G}hP{ywFIDV7NS?EZM&aeP=RyGLLT31T^#piT#wu$Z&XtL?`)eEdh4Am%tq~OF=&+oEvUu;{L#q#LTH9JM{swJrG+2~Ks%J5vJLIlB1b)fwW_9Y9psmi3FnL6E6iqT$^ z_>!cU9~Yn{>A`BaV+GwTX zf_|eSfH&dqw07K1`~8&(Cq6~b>Q8kJ7MX&C&7)k zwkm$Ykb0vIyRufRgy%kEfGUq8-Mo+J2Hq(P4#0oG1Qx>S2})6yg1>Cdl?@(Qu84B-hrMKAz} zf(d-2dpKBr|DH~l3GrX0D+GwrI{G|8pj(&Z92wWlppFYMh{U zc5*c|Z|~^nk^wLH*h6^t-fPCb3FAFp3iQ{E>uG*4F*#$JAN~=R6%&m3Rq+QgJeKoG zCHLS6gD-WqRGnEA3JKC@7=9#Z;W0C$zh`z&_>mj_;c5OA4RiQUyWrT4Ya@8|D$c@4 zFy@z!LoS^9NMcG>nxg^GWUFlrJGC|HBRiF-KES&(=BEIvzZ|6gm_mLX!!bHl9xodE z^uBlAd50%V@k;_^c*NiWO#}XxI(CO{OCq8=To!}P;5NiXBUql_EKVDt) zQ_>v9T2qb$3khER1>hn5t@J0WKVBwC(yq!!a6qEq9j=Ynt5Ml_V9l~q_{IW!pFsMk z=I0Y6KL8B);lA)&#`>qo^}CH}364$XXwbkTKy}+0`(?EypxQ*A*|(LwBkZ9r;|@0i zAGfa79_^}<@G`~=bRj<{LE$$z7}&4R&%M-BGr_A@NzJ8S$n7TiDS)m!L9RW;&mni* zm~%(^>{MRw^A3<2|F25Ax-?0{PHiE}gZEle)d_%Jvn)K;Sm9ZO!^wYnB!q|3ZJ?*L7wOLeO!K2X3%^z@0@^f^ zBSA|r1rHF%*};e(%}RRXbw0@QwVhA7;tbzE4%=b4-2z;Q{40N^3}i9 zL-!AEyZdg8dYa)!Kl;&~caDIZNfN)P1sLg_@gKOUEWZ){h)^!U<+t9-fj2ohiPu3g z{M-b@0q}C_r7Eu?$Qm48Wez;s!W=Rz?9_)rhTp-tVvre|QQNzb?$}A~A$|0tzl7C$ z15dVGe~|^$e13e=Bkag;bo9;~4Nis^R;6D69un_8&>vS|Oox00+1@IAdHNIO+O{rC zjv0DQyx1@4Wq2KmYN!4?Mv1na^Nr;UV*Fb_De9l9bC&{d#6( zzfOPn!#_N+^XL&{(uf_uD^__bBdC0K8GZpki!Z^?k;;Qt*)jR@U%pky>?hy;wjfj3 zJ|pBF*x%E1;4=Y1>5!tg{jTkBBnkWFLr4DNgyM(0<5%bF53w~Lc}4(76Gr@&0*HSj zC`$56d4t9LJb(^g#Lux)=IhEGdnSLNFYmrZFZcG(fAV9cGR+OhkU&nh2YUL;_4oId z53r4spp1Zb-L)M_K7J{WU$f>XUunQkObh$~Fd~?c;5+ZU6_HcLVR?pGg`WlJ;q&=9 zSlT%EOjKd^(;s^>vwEYUl3H(1`QU;5P5TcbmAkup_w@{PgJ=Md-@xAionlCi8UG>r z!(b$DzgT|qOC}uuEI$IY1XVUeFbNNpaPdgh_-TMXKEuzj>(~KgMV9&VpL|;w5D`(t zN$N#&2lq9V%Dvs?rutI(z?M~|fl||fgE7DVOMrwY@*_XILlnd>Tz|$-hc)A0-a?Z5 zl&_bike>!fj4ELmjEwkQ@)Iu--~+#o9plSImif-xKLs<*>A-<~{Y^AXu}lpsv%zlC z>+8P1x3^qZ8mQm5zqhFy`Okg^$N2{Qo83)gQI4@hulS09fV$Gfa6BBbeU$-tL|zC@GV`QPmwh*j?)FE|tpVp5ES` zroP^N`}W-rmaCgSD*`lU#+LjbK#LFjh9iFTAC?~sSmdYNui=MZIgu35V*v#BcpA*| z+r#6O`Bt}I@H0PoD)$|Hy#15k@?$gIM-Scu4;(o7nWj>ysi|+E)Qdq)!`k25vp-~c z@IX^vsnpAKKN3)GM7F7?XJ2pcgP{wS5atur`88<$>7iK$$0agUv+dqNKym;2rg=7PG4}j6Z{e4Yf0y#anZ);Dvx7^h9z=5Vx(}M>r zPUarm*wY7d6?|yBZ(mQTu2hej?xuZPLViYo%6Qvozghjs)KtGc34m0f8vY!=T!56I z@gqLJ@jauI-smW0S}Q+UK@y)K{0h*4UqDX@?4dFoX-}!XuY_%PcT>642jlDpm(spI zN>Zi!n@ZRVd_BEAptpa2X#kR4jT$upn0clYZ4(gTX$ z))I={XvZHyFZJS^=;;H#p8fm8?cm(*LL$Il7=CSS8U5ADuNa^hvEnzr1J@X)@OJNB z89#oLIxX{Sf7|PZpH0IfJ`8&MF$DIN`UM{Vmiy|OdP;o*^`#O_6d?-I{?$!QO{@Cq z`Ud(+^{ZBu_DQXbm+&z>yLUC-$UDk>x3{&mVKG$u5B(@JhaVh>bj9j#NPYu5tw3$W z;HTgXW1R!^n1o<0`ZMIzc8A=y*A18T==p8|+S?Cn{Om($$uW%%m8q$IpsucdVBpZ9 zL-hlz5FsBpuzwY()%BGQ4ScSy9xPXv9wd1rhB|V7cR2}R{z8v`;MdUse&)dlvUtFq zuwVX5j?xo}$@D9bp-~1_JPOI-7tN_W!jq%`l3+D{idpa}{Cpj#9wp(S^ZljnGDG3M zL-nf}ju4>W>sdW;s18cQXXy|$*!vJ-#h$u)FzqAeiRIu~p<9fYSxV&%+gFDV75V!L0AV!3WDQ z*$;G=>q`TN`aU;MUtdyT3Hf1^BdNMWeTN2Mt#zgQ1x#;KoeX|;ed1^k3&NN1ltzEv zHzy&?rv)JF7u|I7BSE9TkRJes{M64BYk=ZZjsEO1xKo}Mpf%z&KP+IS$f-Kv_nRR! zQ({LYmEk4oS3^M55Fpmq50vU5DN$ZOJqbp>KHw{X7R;E=LM5nkb$3}cBxW4HPg}6Q zN=ksv|2hrwB`Gmr9Wtxim&cbPMfOn%g>OMd00GJ^f$y-`yo?xelAj(R)b%o-;(&i@ zhV~gS6uP_nV3qZd+rU6wA7*C*2&J(T9~k+-uCA}Xu4yBp6(nupW{iZN zuJ7wU_yFP;J^uMFL{?$$rU2X8Z2V^dc1S;sBtSa?di<;rgC7WzpK%%N1xyR}%gLP6A5;hlDuDROUWdpKbTvV4XT(p~$yGgG zaduBQ0EXnG#1Vhr#!_h&XR%lZfYu}^*3`UB4+CgeaQS{tP5fl|l^9L;Ha$oaHVRA_ zaKKMHVd2N#MEqJEKV`n^lK=sa$%CW_dKF%FVq)0o&$6q=PtD*G*mM=>l_57cR@mw4 z`a`8UJtec;IJISxil)B4Izoy7>b>2ifl|4?r?>o&@KYg-b0HGK{EyInB?zPu+s9%) zKd>_T6ES)O)empR1O=c6&17+zJMnii@&Y*rh#PRX;viFL+>miRY*0xZp=Yo z`joLOMJok{vk(bkesuR8kRW=a*{MxZe*~uVCj+47C-B4+$wVd3=kDvtTO*JLrag7G+V(@a;=aqh z`?$#U+4~>dcW|Ex10g^-Ey_@NklPacCaUU>EOq>>#xZ;veApVX`CEBOU6iL9sxP2s zezJrmGvIe3enO8Q2ljms!yh~?4AKFvQ{E04964AiQ#_>V@$eth}SqSF~i&>iL#RBI^a`|cz&<|<@8APl%9v|l+{3C#FzyjxE1sPF0Sp&v=|+YT-G>YJG0RG0s*Vul}HgXZHT!!JwFVbTE8 z@QnQUkbvKn>HwD;^Wnw(Jb3%@*rFcT5EYYNmR|y(o^agH0dRnG5sk4v0N9O(aqvy% z>B&O|AO}DRVg3&vUk-POfmw*sD|Aabr+Y-b@b&wUU&e+b3F4Fvsm{TtDDlY|EkI?) z9zRcbI;$P9M^0xCbmO@h{IB8XNytdaH(~Z(5?1LM?m%_}pX00;3a%e$T8(v6br=>P zIfd&*vv0%wO{HIi6qo09BvxPxjEZC^&{J@EKZv?4$P&io|ZjlVF4o%CnYBdV})( zjX7DZ5C!t&NqDSO?*M1{9l(?g(HfWJ8%4x?+A?#cnb8i11;8%NQ6g6cVfNJ5&cpyQ;4rafz3D=`~89`&=KEWavTaP4u&M zi~ooYt|QCuZQjlV_}wYSYfU)IPsJ?!E1DF)qES$T1U%1d_2PB#`_CF6^_QzaH2}u^ z4)orS2W$vjeEl_*S7S6I5kFCdrE=*X2|$TO7(p{?ff*ly60uw@0U#nl2(jOouEK|s zj$iazmVBL-pZ!Bj$4|?TQ5o$QncEInz16U*Nfw7AI6h1tOJk+Owl}d*=0-7k9 zwJ4SLHDOMRq|bGr{9u27sea$aa_^R&RptWH;((SO3l5*>K@$8lJZv04JV63GHNi^p P3zel81wBCVexm$;I2yv& literal 0 HcmV?d00001 diff --git a/16/xw__/modex/DEMO06.EXE b/16/xw__/modex/DEMO06.EXE new file mode 100755 index 0000000000000000000000000000000000000000..f1308e8a536aa9d3d4574566fd018d698d5ef784 GIT binary patch literal 10864 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 G@BaZ%)XT^K literal 0 HcmV?d00001 diff --git a/16/xw__/modex/DEMO06.PAS b/16/xw__/modex/DEMO06.PAS new file mode 100755 index 00000000..f26af067 --- /dev/null +++ b/16/xw__/modex/DEMO06.PAS @@ -0,0 +1,135 @@ +(* + DEMO06 - Magnifying glass + (c) 1994 Alessandro Scotti +*) +uses Crt, Modex; + +const + R = 40; (* Lens radius *) + K : real = 1.8; (* Magnifying factor, less makes a stronger lens *) +type + TLine = array[ 0..319 ] of byte; + PLine = ^TLine; + TScreen = array[ 0..239 ] of PLine; +var + VScreen: TScreen; (* Virtual screen *) + BallX : array[ 0..R, 0..R ] of integer; + BallY : array[ 0..R, 0..R ] of integer; + Sprite : array[ -R..R, -R..R ] of byte; + Page : word; + +(* Returns "lens-view" coordinates of X,Y *) +procedure GetCoords( var X, Y: integer ); +var + LR, Z, SinA, SinB, TgB, Q: real; +begin + LR := Sqrt( X*X + Y*Y ); + if( LR = 0 ) then Exit; + if( LR < R ) then begin + Z := Sqrt( R*R - LR*LR ); + SinA := LR / R; + SinB := SinA / K; + TgB := SinB / Sqrt( 1-SinB*SinB ); + Q := LR - TgB*Z; + X := Round( X * ( Q/LR ) ); + Y := Round( Y * ( Q/LR ) ); + end; +end; + +procedure Init; +var + F : file; + Palette: array[ 0..767 ] of record R, G, B: byte; end; + X, Y, + X2, Y2 : integer; +begin + (* Load background image *) + Assign( F, 'demo06.dat' ); + Reset( F, 1 ); + BlockRead( F, Palette, 768 ); + mxSetPalette( @Palette, 0, 256 ); + for Y:=0 to 239 do begin + New( VScreen[Y] ); + BlockRead( F, VScreen[Y]^, 320 ); + mxPutImage( VScreen[Y], 0, 480+Y, 320, 1, OP_MOVE ); + end; + Close( F ); + (* Build lens *) + for X:=0 to R do begin + for Y:=0 to R do begin + X2 := X; + Y2 := Y; + GetCoords( X2, Y2 ); + BallX[X, Y] := X2; + BallY[X, Y] := Y2; + end; + end; +end; + +procedure PutLens( OX, OY: integer ); +var + X, Y: integer; +begin + for X:=0 to R do begin + for Y:=0 to R do begin + Sprite[Y][X] := VScreen[ OY+BallY[X,Y] ]^[ OX+BallX[X,Y] ]; + Sprite[Y][-X] := VScreen[ OY+BallY[X,Y] ]^[ OX-BallX[X,Y] ]; + Sprite[-Y][X] := VScreen[ OY-BallY[X,Y] ]^[ OX+BallX[X,Y] ]; + Sprite[-Y][-X] := VScreen[ OY-BallY[X,Y] ]^[ OX-BallX[X,Y] ]; + end; + end; + (* Draw the sprite *) + mxPutImage( @Sprite, OX-R, OY-R+Page, 2*R+1, 2*R+1, OP_MOVE ); +end; + +function Delta: integer; +begin + Delta := Random(3)+2; +end; + +procedure Check( Cond: boolean; var Coord, DeltaC: integer; NewCoord, Sign: integer ); +begin + if( Cond ) then begin + Coord := NewCoord; + DeltaC := Sign*Delta; + end; +end; + +var + X, Y, DX, DY: integer; + C: char; +begin + mxInit; + mxSetMode( MX_320x240 ); + Init; + Page := 240; + X := R; + Y := R; + Randomize; + DX := Delta; + DY := Delta; + + (* Main loop *) + repeat + (* Update video *) + mxBitBlt( 0, 480, 320, 240, 0, Page ); + PutLens( X, Y ); + mxCircle( X, Page+Y, R, 0 ); + (* Update lens coordinates *) + Inc( X, DX ); + Check( X+R >= 319, X, DX, 319-R, -1 ); + Check( X <= R, X, DX, R, +1 ); + Inc( Y, DY ); + Check( Y+R >= 239, Y, DY, 239-R, -1 ); + Check( Y <= R, Y, DY, R, +1 ); + (* Flip pages: double buffering, avoid wait for display *) + case Page of + 0 : begin PortW[$3D4] := $000C; Page := 240; end; + 240: begin PortW[$3D4] := $4B0C; Page := 0; end; + end; + mxWaitRetrace; (* Wait for hidden page to show *) + until( KeyPressed ); + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw__/modex/DEMO07.EXE b/16/xw__/modex/DEMO07.EXE new file mode 100755 index 0000000000000000000000000000000000000000..8a401169bba312a0d668452c9df6086505c394a8 GIT binary patch literal 7440 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 639, X, DX, 319, -1 ); + Check( X < 0, X, DX, 0, +1 ); + Inc( Y, DY ); + Check( Y+200 >= 399, Y, DY, 199, -1 ); + Check( Y < 0, Y, DY, 0, +1 ); + mxPan( X, Y ); + mxWaitRetrace; + end; + + (* Shutdown *) + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw__/modex/MATH.INC b/16/xw__/modex/MATH.INC new file mode 100755 index 00000000..742af410 --- /dev/null +++ b/16/xw__/modex/MATH.INC @@ -0,0 +1,34 @@ +; +; MATH.INC - Include file for THREED.ASM +; + +; 3-dimensional point, coordinates in fixed format (16:16) +; +TPOINT STRUC + X DD ? + Y DD ? + Z DD ? +TPOINT ENDS + +; 2-dimensional point, coordinates in integer format +; +TIMAGEPOINT STRUC + IX DW ? + IY DW ? +TIMAGEPOINT ENDS + +; Fixed-point divide: EAX = EAX / arg +; +.xdiv MACRO arg + xor edx, edx + shld edx, eax, 16 + shl eax, 16 + idiv arg +ENDM + +; Fixed-point multiply: EAX = EAX * arg +; +.xmul MACRO arg + imul arg + shrd eax, edx, 16 +ENDM diff --git a/16/xw__/modex/PLASMA.PAS b/16/xw__/modex/PLASMA.PAS new file mode 100755 index 00000000..237e292a --- /dev/null +++ b/16/xw__/modex/PLASMA.PAS @@ -0,0 +1,103 @@ +unit Plasma; +interface + +const + PAL_RGB = 0; + PAL_CLOUDS = 1; + PAL_LANDSCAPE = 2; + +procedure MakePlasma( X, Y: integer; W, H: word; C1, C2, C3, C4: byte ); +procedure MakePlasmaPalette( var Palette; What: word ); + +implementation uses Modex; + +procedure NewColor( XA, YA, X, Y, XB, YB: integer ); +var + Color: longint; +begin + Color := Abs( XA-XB )+Abs( YA-YB ); + Color := Random( Color shl 1 )-Color; + Color := (Color+mxGetPixel( XA, YA )+mxGetPixel( XB, YB )+1) shr 1; + if( Color < 1 ) then Color := 1; + if( Color > 192 ) then Color := 192; + if( mxGetPixel( X, Y ) = 0 ) then + mxPutPixel( X, Y, Lo(Color) ); +end; + +procedure Divide( X1, Y1, X2, Y2: integer ); +var + X, Y, Color: integer; +begin + if not( (X2-X1<2)and(Y2-Y1<2) ) then begin + X := (X1+X2) shr 1; + Y := (Y1+Y2) shr 1; + NewColor( X1, Y1, X, Y1, X2, Y1 ); + NewColor( X2, Y1, X2, Y, X2, Y2 ); + NewColor( X1, Y2, X, Y2, X2, Y2 ); + NewColor( X1, Y1, X1, Y, X1, Y2 ); + Color := (mxGetPixel( X1, Y1 )+mxGetPixel( X2, Y1 )+ + mxGetPixel( X2, Y2 )+mxGetPixel( X1, Y2 )) shr 2; + mxPutPixel( X, Y, Color ); + Divide( X1, Y1, X, Y ); + Divide( X, Y1, X2, Y ); + Divide( X, Y, X2, Y2 ); + Divide( X1, Y, X, Y2 ); + end; +end; + +procedure MakePlasma; +begin + Dec( W ); + Dec( H ); + mxPutPixel( X, Y, C1 ); + mxPutPixel( X, Y+H, C2 ); + mxPutPixel( X+W, Y+H, C3 ); + mxPutPixel( X+W, Y, C4 ); + Divide( X, Y, X+W, Y+H ); +end; + +procedure MakePlasmaPalette; +type + TPal = array[ byte ] of record R, G, B: byte end; +var + I: word; +begin + FillChar( TPal(Palette)[1], 192*3, 0 ); + case What of + PAL_CLOUDS: + for I:=1 to 192 do begin + TPal(Palette)[I].R := Abs( I-96 )*63 div 96; + TPal(Palette)[I].G := Abs( I-96 )*63 div 96; + TPal(Palette)[I].B := 63; + end; + PAL_LANDSCAPE: + begin + for I:=0 to 31 do begin + TPal(Palette)[I+1].R := I; + TPal(Palette)[I+1].G := I; + TPal(Palette)[I+1].B := I + I shr 1+15; + end; + for I:=32 to 63 do begin + TPal(Palette)[I+1].R := 0; + TPal(Palette)[I+1].G := I; + TPal(Palette)[I+1].B := 0; + end; + for I:=64 to 191 do begin + TPal(Palette)[I+1].R := (I-64) div 3 + 15; + TPal(Palette)[I+1].G := (I-64) div 3 + 15; + TPal(Palette)[I+1].B := (I-64) div 3 + 15; + end; + end; + else + for I:=1 to 64 do begin + TPal(Palette)[I].G := I-1; + TPal(Palette)[I].B := 64-I; + TPal(Palette)[I+64].R := I-1; + TPal(Palette)[I+64].G := 64-I; + TPal(Palette)[I+128].B := I-1; + TPal(Palette)[I+128].R := 64-I; + end; + end; +end; + +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 index 0000000000000000000000000000000000000000..a10d7db5a0a62654c70c632d8ce6b078a520613c GIT binary patch literal 10336 zcmbVy3s_TEw(vTSoID5tMX9d_w3u4aR7pjJ@F+^O-bz#J1NEZq*xKpbnYI^CaBinU z9O@%E)H?0hnUZ!!WWE_Y+WW;0{cphDYcwb*je_>8JQNX74~7B?7ZB3qu6+V(ZR`F2 zpM3kAz1Lo^z4qE`@3jxh*S!ei!2l7km)-jpIRohcZz=(%006$=FqT&-fC4PyiF z6qYtD-88^C7N7x3HoH{V|fe95SC3Gz-=t+DBwFXRvITXa2_8pDXoOZ^fveybGb-FMZ0`K0}NZp6iB;hC?#A&)8=aPiOJ&1FO3Yye{DS#SS zcG@~~PN)ENoa>fUJjFFqaEfapk4xlnnLL`w;|i6EdYk9E%`O_uu0YW2iUG5z4Z32n zIRYZR1gZ$S(ngR-4=DtEE8yA?Y7)dz7EJ-yHiVKUDWk}hfgBH-@ECwQ4GX>j-&QQK zZmg$cA(|uph;`}8d~SOc4cr>nUNAesT>RJYebij{sEvb(E1P?3 z@RLcLH-+^2iPQT96Gsdx)C(pBWAcAgjxJLnD1vSB@arT_WvOnm+M0%PrFYt;UAKW6VLEW2L!zf zxn-Pp;f6~%UkkYvr1~{hlTEDG_{Y>%8rxrnrm~sT`@AVqc&L!VLj{J1fxF?syU^6< zU10h$gcfRL^VNr-%#$O%qZ_`sU}nljU{IIh&dj0fk3~y+h6&^ewyB2au;)>j; zD{|kXvgHpI5wDY$F|K^!llK8lF8ScykT8UPcSlF%pxgauPvJHiwk`be&be-#EtCGy zuz+lJHjEi1D`4*V73LqO*9n>QM{Cz7Unt<-UY>kB?-@b6;-@sU<=hiA_x!;5f%?M6 z;A{#C8{xiCH7fRQ>>>c+li&XoS1O0>Q9ovp!fous$IU)u+`osCl@A{``@pzY{*;Ec zoO^=)w{eG}FuGLWyZ_BO6r;}Zy}?VqAP`>&MXCq91n1x%u5Qdlzw6V1eN(#>eabaU~CZ~&Z?xp*SJf6$Bj9$95KDbhE( z^|?-v{Z1I%UbPyuxORqudHrNJeh@6W{e&nKo*(S>i@)?^h@&lSH~`9WP%sUpe^kzp zn2ov$ronryLBZ62uhkzk^^qYI_sI_6zSuYC?X(}N7TmEK?n?a6)$lRoYew5u*oU4? zqL~_1m=#~c<5qDv9@Xw0ZHg^;7$^?M;6qLr z#s4Zl0LNCKF^;XoM{$*cn5(pr^RYp$kt2e2johfgT+5~AN97JO*mSeFbD%J_k)tdZ z#1s9;8Y%4>G`Z^&WP1(yRH0@)5Y()|vJ%880Wu#%Uhzhho`XlNXgoNM?43XPs>U9z zevdYcDTxF@I~D}ZI1r+v!J5xed_;)?fhq*55vYMu0GpNun}!8jGzWGQx09Oy3GFeb z&(NUXPpUQdI2zog3MfTtlVWKpGB9yVOEvHd(1^Q(NWsEAR6K;1qI{F86g42*w0dbN z>S5yWh`O{i8j!V-vdGLDae2_-Mq-6T%&pO*+LifZ@#v#38H+WIR2v8ScrFss$#y_` zqDgx!X_G@zNYRb*(`O>V(61L#X-KZxHZFcJ{$l&H}@d z_@Vg0Z8UQcAppr&wuQ$J$Dhle%naxSEf72wp#@<}5PS#m&JB9*ct%;PB-W|-Go1Sa zhG7!Ji4S3CZ>j6(JyciM`*+W7In&rWm85%aS1f&smAO>yP8`gY={(0 z8X-$9tX7GZV8m}f0~^*nV9QePHU)NX_UlWO%pUiidViH^sFuPYaFRlU8=0*Wjlhq0 zw=nh=CsT2j>Bj!6r2isi-yBf2^N&P_4X1tKLW6|y zw`%%$2ThLpP>m-_VxlTjAQ-GN`C)%i){tvwwD-v{w`HPB1w}R9xw+FY+Ta>K3j47! z9;4Ns4MRn^PVlr=s$`HB&_4r`k~Ic*%@o=5vYoR3lvR%<%-0B}NMXaM`S(J^Zwo=V z^FHH#IFKoq-8Jp>V*K7@#V9zw)85JJ?BBHp%d z?s=y&V#gs+wM4x0XAq9ZSJ_Pc!l`%<22;D~_B(EieAl^M%{xs!2Pr;WUjh(cB`qjl z#6g;WLSMp$04xl=-Zzln&(u2=`eYPPkm*E~P~_Xj1h;R&L6%U{5RXd?fxa+(2^VT` zNZCJ--^UC(aa5@F+hI-|6>42TC%7dAEoxM6M{W>T`Zr{i3WEbz>aNuiG`YsV- z5{ljs@d(jFB-xD*$m$xAb^W2TM#x5_-MT03x`#wpT+os~eNfTJbRJY#hAX~ioND`x zp>Aimy{&sV1m=egZW6)o{VCJO!6R*WAMteP4I8QFXfyL$cBRZ3H3RYfg<4CmWA?Bc zWcH}p0NgQoOytL7_KbaR{D;xy*bbMcM&2A#H1^8)8@N#b@YE*yW#$j;&t?0#o$?;# zixG1p*N=I3?3$>AaWMYHXe*J1w<Y^Hdy!j!WCjK=WGDpnAn45z5Mrqiw3i}S zb4Iaf1hpXO%@NS6lVKeE9C?{Xc-7N4l%POR4}wCx>S@H9fuOwR&g`1yNc7}Q!+k@G1As5!gM<%; z<2{^`F$BxOYH;@+8fB`sb{X6yIxZAw>CkrkeVw=d4B2iN)%E{P$p^JlOWGNu_rUZaIA;ZuF;6Gj8rME#M`!GJ#qpHM-WzuPa`O&rYu7IT4t2< zDkGD};lzupK>Rb5DH4L>moj^0T)}}(?m#PNa38qL9r%_z(8Z-6xWw(@7Q?Y$g3kV^ zF6mKz7~ih;;76j79;h8SUp^lOZk39hRufaPfO1Wq?wuOrArv~RZWjbl7-wX2X(wYY z196Qk8#m9{uCZhO0pc>5YtESefX_ipmsy8qTB3DU%`TwOjmm)&XUWRO{v%eLF7u$$ zF*5Tg?l@WY5m24CC_bNn+dX}Rvfs9U9XL}4*1&{3x{NAq;cU@2x!sy89A3+D6dvT- z5ptdLn6<84dQZJI^%CwXvQu0aN5y2Hv!-@&V4*yu4P}%!n&-;E8|~|JZV(@3oQuQ> zjHqEcYysg?qOgP&9}9}V3htN8gi!~9_BEHJPn(QF0&SqByho9i2_+>_}(tB9uv87ThDmex^oJ302w32F}pPEccNl z?B6;jaF$NI#^oxL5^r!@8Sw;-hgk6o+J0gt*UkmpHR7kV{nSkE8mSW=OW1=wJR29G zwpw+q+?xunl^YrG5;jhLggxIv;O~vVNqwNks%hmEH6iN|Cc<-UTNH5yLlC{DMC1(T zMH#gABco6ro+~3R)$1X+8(G)orz*xm@`Wvv26~11_LmMa7KNI*{*v?mTwi4OT+gsq zUC%($_Lt)P*I%l!rhbbvryz6Y1fF(MHT%ECIY*$%Z5f-;?v2K`YParNPStKf2Na_M zsFODFWC2^1NjooAWwKUycZU^hnd+h(O;u*(t4z`Iv8OWUKn&Vu1l9Ft=IAz7sM)@a zK5~&)A?4>6UC**Yy)AQG(eh|p&V-`nlWfbU6fM`{;U4K$37zDqF05jgEz=1Wg|2d& z+R!BFr4j!*SWbaa!9RteWR8*L7e8a1%s+0V_{WSKKi@csHyOkE=Zvwr=aL)w8r^Pc zk@!bQZq9QHy}mEQns}E}A?^ZatoU2N+BW#7)|b#@A=J`#Tci(0#Vzq6)Z zMkluu20oRT1-dFKT(xKsDrO)TFbbV5N0lQDGO@CN)d|ZLx+j(^+9ncZt*Omu*D#%3 zCQgARtph$r{20V<{027?NDpVYNP|=L!t*Q86>}jQ7x_#a)NItmZf{C3&;Np8;~0Ys3? zcKSH`jl+jp{qmTNXpq%wR&m})dCtZS9;m=5*I2|Y0K>Q9;c#(32$ixZ!0TnP=sa@* zb6U)28IA?aXGlW4ETP>s>PB8qZ7M&3=}iX(59a;1@7z=fNVS!;G}qBWTN{<~5m&QQ5< zGr9*WM%Y9ZW*{H0x88_&;ggToTCeq3zw6;O>DF^SBW<2aKkzJg(D7&(F0ACT3va}1 zulf+I{)JnZW5M8>vX$PcLZ>w=n#x|kcHM@JIWh8cu3A7;43^cfcD+xI`=#Nup-HmL zaA^Xb?!!EM3Z~y-ZvM$VZe6H0Io`ANk%9UYh};rc5s6pq%<){gE}2t6E~hIQ2fjL? zy2ul+T>yo?NSo#+{i8pcN#sE&Vf=RxL&6;X6}U=$pjkFu9U{D5w|P9 zZ`0}8ljG4+#H2kXPeB-$2>cUApQXi_P?7**0vugWi&`j2#61$6Nw{4jmN*ZNzDSF5 zf>QRZcdFhlSGjpkTmXxFy`Cd4W6u#4E>Itv(B6NGor7PXAlqK)G21Ie3bM@@x_Uh01*cqFih@HD|fnnCdgxHKXa)0^K>n|JJ zyD-y)paE+&4D8vSkYnAorDjwY--5%FE%ZxOpdjKJ`Fj#OXlVXf2oq z8SWq~#j*?weoNc&a`PQSFZ%`dfVJQV__!mqk3PaW8m?iKe|K}haXCNWux}3jDL2BR zx89*Goa1u6qe1j(dChOsq^@t^k{CxryHD+CZn)d(_!~GHt~&HhdL4G2b~FrrK~L+f z{q`=ux9XhCw949c{MEAl+FHV!rH_9BadHd+GDmZVk8xaXa5UVu-eLJC4l-|r_#AiC zR}+T#Y(DO27^)R(#e|bQcD6X0@A&50TWUM4?Nq`w34~-*B=PN%;C@puoevw)b0vck zn(qkLay&mA?(cG0%M{P4Je&o`Rb{_asu9}ziSJM0>6zh}Y zgAeUN5NY(C(b2PXeO^CidKM+i_jNP8^2dgEFXw%%`Xt+ao-wFx4d4%$X#h*q# z4INm8wvd9MxgA28Lm`NL^YEWO$c?nrUXcMC6 z4>|fx!%w4S8+s%)j{9CD?*^P8>}&YWnl&8ZXm}l~e(UDpUa8u&+Aqyai}d`C%yn}I zUhhJ|@9wgxd)>c9No=`Hl6b`wA|c5ARW#2@!lbdHAB5s z7Ik44y`4Q=zEi%=FSyfq9ejn0md}tU$mh$mnSW+pWS(a$*$Va;`?yRmOOOrw&8s*z8^mu~(bKS(b9mBXLU|Tgg9S%Zm4=|SIquT^*w5E-~M;L+2Fq3)6`~@H>8!1gVul`pPm+x zlEzfbiE@Hv_R8$!N+)HR?r3V0oS+LA8F5*%KvCZ`hamrxljda=2~kewz;e8+HYz>1 z-MXHdUXIt%-*~5{w+;&zai5*2aMJh+S2!&g^-B5_`qHNrCH?qXr0~vf^Ul*7l{MxB z)W#WmegE~??7Iojatz0E@4UnerBBv?PsjcYWq<87Zn5&$@|f(KWcb4eQ~1@RT-L5# zyWX0LRQyCCdZ`kR5;q0yGUfI*=wTWK%~ECI)d)PFjIXGMgREstg%|L;MpbbZ4n|s- zigWOO$2)`CliFvMj=g(hJTH_iQ`+mTZEowZ8xxELYWdE}IJvrBU;42kr9sY{Q!dN- ze@bb3k~gK)Kf*6gx%3F1mQo+XC#779;pe5)&*#HaF3sl^j;2=eZ$V#_e!Ko-Mes?{ z5fmQ>1QLs0PEEyOr79ITC~*vdT6K$+-#Hp|8OrsT_DQo%a7t2@pF$=-=2J-LCw~eo zA1y8LE)Q8)85kN!bjB6s!C9Y{aN6E!ziw@}%JS2!XRYQHFFbEJ{k(9=Yh3>%e%!89 z)p+N1)f9HBBv2Xw(QDVQ%N7Qw2McEBr{zt;RAj3CTJ2Tq*HCx?3eQ8XrmnT_MqMMG zf(%WD^ECmtrOV}ojwJ)$d8rvn{7A1)mwV@HQB^cB*xlxR*z^1& zxTwxO9`oE@>`3ak*Edw-P3_!^k1q1KO&)#ZF|@a)!f>7>K$QiG#FJZDJo_JVIWHb^ zS>X^?4;^|plRs31usdOgT>B`5m205)Q2BEZcHW{qoK&61+N;|XhtX!t-&+S0+<%Y3 zWEYdX$^sS1qA>+w@r@reGS&FTbR<(VnwVs&&ZwZ`$VH!`;`56>rs5wLN#GzERVJN+ zDcIPQ&o80_I4|;eYh{GZ;EP+q;Z4VMSVvf_qLCS4s5%-6;yB7_$HW-jstN#WTWcpqf%%dJHOY=_6jU?hxnW{|uph0p%tl>XM`MU1IH=Ne(!mJA^(vd_I6b8LQ#6E!+huq49+~>7Wd&|G3E0Wk&0^ zIlwF5T{Q=3*4bpPe+jGDN0F0p2>D6jQ5P)sPVGNob-76w`TqsWIEmcCi1FZZj1owB zFs8t^RnfNP6Kpw?sxqgvgjHo~k)M z$CV_Uzzji5fe+A2%VVMcl+~iDYpXjSsBY~|a9ghz)QGX*HU61P4)@OIQnC6+Zhp9T z-gn-G4c?R*40_MC1WQu!qhUG-)p+&1CA{t``OzIr9diL$wJ{gyUi=T6Ho8}aA6w5u zX)4C&bnwXDDVv4qktWo{TZW=WTsA874UXJ__>%{=$eCNrovi1+>-~#=Pa}G`G>Z!C z#jBbntiSi~xIm7XK`SpeE91}Abr{_K-b2zSpOM|@d#@llpZ?$fMWzGnNB4IDUIzaU DJ^3nG literal 0 HcmV?d00001 diff --git a/16/xw__/modex/QIX2.PAS b/16/xw__/modex/QIX2.PAS new file mode 100755 index 00000000..d1b59791 --- /dev/null +++ b/16/xw__/modex/QIX2.PAS @@ -0,0 +1,210 @@ +{$E-,N+} +uses Crt, Modex; + +const + DEFVERT = 12; (* Vertex count *) + DEFREPL = 3; (* Repetition count *) + DEFQIXS = 2; (* Qixs *) + FADESPEED = 48; +type + TPoint = record + X, Y : integer; + end; + TRGB = record + R, G, B: byte; + end; + TQix = record + Color: integer; + Vert : array[ 0..DEFVERT-1, 0..DEFREPL-1 ] of TPoint; + Delta: array[ 0..DEFVERT-1 ] of TPoint; + end; +var + Page : integer; + MaxX, + MaxY : word; + Qix : array[ 0..DEFQIXS-1 ] of TQix; + Pal : array[ byte ] of TRGB; + +type + TReal = double; + TRPoint = record + X, Y: TReal; + end; + TMatrix = array[ 0..3, 0..3 ] of TReal; +var + M: TMatrix; + G: array[ 0..DEFVERT-1 ] of TRPoint; + C: array[ 0..DEFVERT-1 ] of TRPoint; + +procedure BumpPal( Idx, DR, DG, DB, Steps: integer ); +var + I: integer; +begin + for I:=1 to Steps do begin + Pal[Idx+1].R := Pal[Idx].R + DR; + Pal[Idx+1].G := Pal[Idx].G + DG; + Pal[Idx+1].B := Pal[Idx].B + DB; + Inc( Idx ); + end; +end; + +procedure InitPalette; +begin + with Pal[0] do begin R:=0; G:=0; B:=0; end; + with Pal[1] do begin R:=0; G:=0; B:=62; end; + BumpPal( 1, 0, 2, -2, 31 ); + BumpPal( 32, 2, -2, 0, 31 ); + BumpPal( 63, -2, 2, 2, 31 ); + BumpPal( 94, 2, 0, -2, 31 ); + BumpPal( 125, -2, -2, 2, 31 ); +end; + +procedure Init( var Qix: TQix; Color: integer ); +var + I: integer; +begin + FillChar( Qix.Vert, SizeOf(Qix.Vert), 0 ); + for I:=0 to DEFVERT-1 do begin + Qix.Vert[I, DEFREPL-1].X := Random( MaxX ); + Qix.Vert[I, DEFREPL-1].Y := Random( MaxY ); + Qix.Delta[I].X := Random(5)+1; + Qix.Delta[I].Y := Random(5)+1; + end; + Qix.Color := Color; + + (* Initialize matrix (Catmull-Rom) *) + M[0,0] := -1/2; M[0,1] := 3/2; M[0,2] := -3/2; M[0,3] := 1/2; + M[1,0] := 1; M[1,1] := -5/2; M[1,2] := 2; M[1,3] := -1/2; + M[2,0] := -1/2; M[2,1] := 0; M[2,2] := 1/2; M[2,3] := 0; + M[3,0] := 0; M[3,1] := 1; M[3,2] := 0; M[3,3] := 0; +end; + +procedure mxBezier( var Qix: TQix; I0, Idx, N: integer ); +var + I, J: integer; + T, T2, T3: TReal; + X0, Y0, X, Y: TReal; + Delta: TReal; +begin + (* Compute coefficients *) + for I:=0 to 3 do begin + C[I].X := 0; + for J:=0 to 3 do C[I].X := C[I].X + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].X; + C[I].Y := 0; + for J:=0 to 3 do C[I].Y := C[I].Y + M[I,J]*Qix.Vert[(I0+J) mod DEFVERT,Idx].Y; + end; + X0 := C[3].X; + Y0 := C[3].Y; + Delta := 1 / N; + T := 0; + for I:=1 to N do begin + T := T + Delta; + T2 := T*T; + T3 := T*T2; + X := C[0].X*T3 + C[1].X*T2 + C[2].X*T + C[3].X; + Y := C[0].Y*T3 + C[1].Y*T2 + C[2].Y*T + C[3].Y; + mxLine( Round(X0), Page+Round(Y0), Round(X), Page+Round(Y), Qix.Color, OP_SET ); + X0 := X; + Y0 := Y; + end; +end; + +procedure Plot( var Qix: TQix; Idx: integer ); +var + I, J: integer; +begin + for I:=0 to DEFVERT-1 do begin + mxBezier( Qix, I, Idx, 12 ); + end; +end; + +procedure Update( var Qix: TQix; Idx: integer ); +var + I: integer; +begin + for I:=0 to DEFVERT-1 do with Qix do begin + Inc( Vert[I,Idx].X, Delta[I].X ); + if( Vert[I,Idx].X < 0 ) then begin + Vert[I,Idx].X := 0; + Delta[I].X := Random( 5 )+1; + end; + if( Vert[I,Idx].X > MaxX ) then begin + Vert[I,Idx].X := MaxX; + Delta[I].X := -Random( 5 )-1; + end; + Inc( Vert[I,Idx].Y, Delta[I].Y ); + if( Vert[I,Idx].Y < 0 ) then begin + Vert[I,Idx].Y := 0; + Delta[I].Y := Random( 5 )+1; + end; + if( Vert[I,Idx].Y > MaxY ) then begin + Vert[I,Idx].Y := MaxY; + Delta[I].Y := -Random( 5 )-1; + end; + end; +end; + +procedure Copy( var Qix: TQix; Dest, Src: integer ); +var + I: integer; +begin + for I:=0 to DEFVERT-1 do with Qix do begin + Vert[I,Dest].X := Vert[I,Src].X; + Vert[I,Dest].Y := Vert[I,Src].Y; + end; +end; + +procedure AnimateQix; +var + Q, Idx, I, J, P, Count: integer; +begin + Count := 0; + P := DEFREPL-1; + I := 0; + J := 1; + repeat + mxSetClipRegion( 0, Page, MaxX+1, MaxY+1 ); + mxSetClip( TRUE ); + mxFillBox( 0, Page, MaxX+1, MaxY+1, 0, OP_SET ); + for Q:=0 to DEFQIXS-1 do begin + Copy( Qix[Q], I, P ); + Update( Qix[Q], I ); + for Idx:=0 to DEFREPL-1 do begin + Plot( Qix[Q], Idx ); + end; + end; + I := (I+1) mod DEFREPL; + J := (J+1) mod DEFREPL; + P := (P+1) mod DEFREPL; + Inc( Count ); + mxStartLine( Page ); + if( Count >= FADESPEED ) then begin + for Q:=0 to DEFQIXS-1 do begin + Inc( Qix[Q].Color ); + if( Qix[Q].Color > 156 ) then + Qix[Q].Color := 1; + end; + Count := 0; + end; + Page := 240-Page; + until( KeyPressed ); +end; + +var + I: integer; +begin + Randomize; + mxInit; + mxSetMode( MX_320x240 ); + mxGetScreenSize( MaxX, MaxY ); + for I:=0 to DEFQIXS-1 do + Init( Qix[I], (I*(155 div DEFQIXS)) mod 155 + 1 ); + InitPalette; + mxSetPalette( @Pal, 0, 157 ); + Page := 240; + Dec( MaxX ); + Dec( MaxY ); + AnimateQix; + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw__/modex/README.TXT b/16/xw__/modex/README.TXT new file mode 100755 index 00000000..306e8b9a --- /dev/null +++ b/16/xw__/modex/README.TXT @@ -0,0 +1,8 @@ +ModeX - A graphical library for DOS programs +Copyright (c) 1993-1994 Alessandro Scotti +http://www.ascotti.org/ + +Please look at the above site in the "Art of..." and +then in the "Old programs" section for more information. + + diff --git a/16/xw__/modex/SINCOS.INC b/16/xw__/modex/SINCOS.INC new file mode 100755 index 00000000..6986eeeb --- /dev/null +++ b/16/xw__/modex/SINCOS.INC @@ -0,0 +1,518 @@ +; +; SINCOS.INC - Sin/cos tables for THREED.ASM +; + +tblSin LABEL DWORD + DD 0 + DD 411733 + DD 823219 + DD 1234209 + DD 1644455 + DD 2053710 + DD 2461729 + DD 2868265 + DD 3273072 + DD 3675909 + DD 4076531 + DD 4474698 + DD 4870169 + DD 5262706 + DD 5652074 + DD 6038037 + DD 6420363 + DD 6798821 + DD 7173184 + DD 7543226 + DD 7908725 + DD 8269459 + DD 8625213 + DD 8975771 + DD 9320922 + DD 9660458 + DD 9994176 + DD 10321873 + DD 10643353 + DD 10958422 + DD 11266890 + DD 11568571 + DD 11863283 + DD 12150850 + DD 12431097 + DD 12703856 + DD 12968963 + DD 13226258 + DD 13475586 + DD 13716797 + DD 13949745 + DD 14174291 + DD 14390298 + DD 14597637 + DD 14796184 + DD 14985817 + DD 15166424 + DD 15337895 + DD 15500126 + DD 15653022 + DD 15796488 + DD 15930439 + DD 16054795 + DD 16169479 + DD 16274424 + DD 16369565 + DD 16454846 + DD 16530216 + DD 16595628 + DD 16651044 + DD 16696429 + DD 16731757 + DD 16757007 + DD 16772163 + DD 16777216 + DD 16772163 + DD 16757007 + DD 16731757 + DD 16696429 + DD 16651044 + DD 16595628 + DD 16530216 + DD 16454846 + DD 16369565 + DD 16274424 + DD 16169479 + DD 16054795 + DD 15930439 + DD 15796488 + DD 15653022 + DD 15500126 + DD 15337895 + DD 15166424 + DD 14985817 + DD 14796184 + DD 14597637 + DD 14390298 + DD 14174291 + DD 13949745 + DD 13716797 + DD 13475586 + DD 13226258 + DD 12968963 + DD 12703856 + DD 12431097 + DD 12150850 + DD 11863283 + DD 11568571 + DD 11266890 + DD 10958422 + DD 10643353 + DD 10321873 + DD 9994176 + DD 9660458 + DD 9320922 + DD 8975771 + DD 8625213 + DD 8269459 + DD 7908725 + DD 7543226 + DD 7173184 + DD 6798821 + DD 6420363 + DD 6038037 + DD 5652074 + DD 5262706 + DD 4870169 + DD 4474698 + DD 4076531 + DD 3675909 + DD 3273072 + DD 2868265 + DD 2461729 + DD 2053710 + DD 1644455 + DD 1234209 + DD 823219 + DD 411733 + DD 0 + DD -411733 + DD -823219 + DD -1234209 + DD -1644455 + DD -2053710 + DD -2461729 + DD -2868265 + DD -3273072 + DD -3675909 + DD -4076531 + DD -4474698 + DD -4870169 + DD -5262706 + DD -5652074 + DD -6038037 + DD -6420363 + DD -6798821 + DD -7173184 + DD -7543226 + DD -7908725 + DD -8269459 + DD -8625213 + DD -8975771 + DD -9320922 + DD -9660458 + DD -9994176 + DD -10321873 + DD -10643353 + DD -10958422 + DD -11266890 + DD -11568571 + DD -11863283 + DD -12150850 + DD -12431097 + DD -12703856 + DD -12968963 + DD -13226258 + DD -13475586 + DD -13716797 + DD -13949745 + DD -14174291 + DD -14390298 + DD -14597637 + DD -14796184 + DD -14985817 + DD -15166424 + DD -15337895 + DD -15500126 + DD -15653022 + DD -15796488 + DD -15930439 + DD -16054795 + DD -16169479 + DD -16274424 + DD -16369565 + DD -16454846 + DD -16530216 + DD -16595628 + DD -16651044 + DD -16696429 + DD -16731757 + DD -16757007 + DD -16772163 + DD -16777216 + DD -16772163 + DD -16757007 + DD -16731757 + DD -16696429 + DD -16651044 + DD -16595628 + DD -16530216 + DD -16454846 + DD -16369565 + DD -16274424 + DD -16169479 + DD -16054795 + DD -15930439 + DD -15796488 + DD -15653022 + DD -15500126 + DD -15337895 + DD -15166424 + DD -14985817 + DD -14796184 + DD -14597637 + DD -14390298 + DD -14174291 + DD -13949745 + DD -13716797 + DD -13475586 + DD -13226258 + DD -12968963 + DD -12703856 + DD -12431097 + DD -12150850 + DD -11863283 + DD -11568571 + DD -11266890 + DD -10958422 + DD -10643353 + DD -10321873 + DD -9994176 + DD -9660458 + DD -9320922 + DD -8975771 + DD -8625213 + DD -8269459 + DD -7908725 + DD -7543226 + DD -7173184 + DD -6798821 + DD -6420363 + DD -6038037 + DD -5652074 + DD -5262706 + DD -4870169 + DD -4474698 + DD -4076531 + DD -3675909 + DD -3273072 + DD -2868265 + DD -2461729 + DD -2053710 + DD -1644455 + DD -1234209 + DD -823219 + DD -411733 +tblCos LABEL DWORD + DD 16777216 + DD 16772163 + DD 16757007 + DD 16731757 + DD 16696429 + DD 16651044 + DD 16595628 + DD 16530216 + DD 16454846 + DD 16369565 + DD 16274424 + DD 16169479 + DD 16054795 + DD 15930439 + DD 15796488 + DD 15653022 + DD 15500126 + DD 15337895 + DD 15166424 + DD 14985817 + DD 14796184 + DD 14597637 + DD 14390298 + DD 14174291 + DD 13949745 + DD 13716797 + DD 13475586 + DD 13226258 + DD 12968963 + DD 12703856 + DD 12431097 + DD 12150850 + DD 11863283 + DD 11568571 + DD 11266890 + DD 10958422 + DD 10643353 + DD 10321873 + DD 9994176 + DD 9660458 + DD 9320922 + DD 8975771 + DD 8625213 + DD 8269459 + DD 7908725 + DD 7543226 + DD 7173184 + DD 6798821 + DD 6420363 + DD 6038037 + DD 5652074 + DD 5262706 + DD 4870169 + DD 4474698 + DD 4076531 + DD 3675909 + DD 3273072 + DD 2868265 + DD 2461729 + DD 2053710 + DD 1644455 + DD 1234209 + DD 823219 + DD 411733 + DD 0 + DD -411733 + DD -823219 + DD -1234209 + DD -1644455 + DD -2053710 + DD -2461729 + DD -2868265 + DD -3273072 + DD -3675909 + DD -4076531 + DD -4474698 + DD -4870169 + DD -5262706 + DD -5652074 + DD -6038037 + DD -6420363 + DD -6798821 + DD -7173184 + DD -7543226 + DD -7908725 + DD -8269459 + DD -8625213 + DD -8975771 + DD -9320922 + DD -9660458 + DD -9994176 + DD -10321873 + DD -10643353 + DD -10958422 + DD -11266890 + DD -11568571 + DD -11863283 + DD -12150850 + DD -12431097 + DD -12703856 + DD -12968963 + DD -13226258 + DD -13475586 + DD -13716797 + DD -13949745 + DD -14174291 + DD -14390298 + DD -14597637 + DD -14796184 + DD -14985817 + DD -15166424 + DD -15337895 + DD -15500126 + DD -15653022 + DD -15796488 + DD -15930439 + DD -16054795 + DD -16169479 + DD -16274424 + DD -16369565 + DD -16454846 + DD -16530216 + DD -16595628 + DD -16651044 + DD -16696429 + DD -16731757 + DD -16757007 + DD -16772163 + DD -16777216 + DD -16772163 + DD -16757007 + DD -16731757 + DD -16696429 + DD -16651044 + DD -16595628 + DD -16530216 + DD -16454846 + DD -16369565 + DD -16274424 + DD -16169479 + DD -16054795 + DD -15930439 + DD -15796488 + DD -15653022 + DD -15500126 + DD -15337895 + DD -15166424 + DD -14985817 + DD -14796184 + DD -14597637 + DD -14390298 + DD -14174291 + DD -13949745 + DD -13716797 + DD -13475586 + DD -13226258 + DD -12968963 + DD -12703856 + DD -12431097 + DD -12150850 + DD -11863283 + DD -11568571 + DD -11266890 + DD -10958422 + DD -10643353 + DD -10321873 + DD -9994176 + DD -9660458 + DD -9320922 + DD -8975771 + DD -8625213 + DD -8269459 + DD -7908725 + DD -7543226 + DD -7173184 + DD -6798821 + DD -6420363 + DD -6038037 + DD -5652074 + DD -5262706 + DD -4870169 + DD -4474698 + DD -4076531 + DD -3675909 + DD -3273072 + DD -2868265 + DD -2461729 + DD -2053710 + DD -1644455 + DD -1234209 + DD -823219 + DD -411733 + DD 0 + DD 411733 + DD 823219 + DD 1234209 + DD 1644455 + DD 2053710 + DD 2461729 + DD 2868265 + DD 3273072 + DD 3675909 + DD 4076531 + DD 4474698 + DD 4870169 + DD 5262706 + DD 5652074 + DD 6038037 + DD 6420363 + DD 6798821 + DD 7173184 + DD 7543226 + DD 7908725 + DD 8269459 + DD 8625213 + DD 8975771 + DD 9320922 + DD 9660458 + DD 9994176 + DD 10321873 + DD 10643353 + DD 10958422 + DD 11266890 + DD 11568571 + DD 11863283 + DD 12150850 + DD 12431097 + DD 12703856 + DD 12968963 + DD 13226258 + DD 13475586 + DD 13716797 + DD 13949745 + DD 14174291 + DD 14390298 + DD 14597637 + DD 14796184 + DD 14985817 + DD 15166424 + DD 15337895 + DD 15500126 + DD 15653022 + DD 15796488 + DD 15930439 + DD 16054795 + DD 16169479 + DD 16274424 + DD 16369565 + DD 16454846 + DD 16530216 + DD 16595628 + DD 16651044 + DD 16696429 + DD 16731757 + DD 16757007 + DD 16772163 diff --git a/16/xw__/modex/THREED.ASM b/16/xw__/modex/THREED.ASM new file mode 100755 index 00000000..5ecd3ba3 --- /dev/null +++ b/16/xw__/modex/THREED.ASM @@ -0,0 +1,872 @@ +COMMENT / + Fixed-point math functions and 3D transforms + Copyright (c) 1993,94 by Alessandro Scotti +/ +WARN PRO +P386 +JUMPS +LOCALS + +INCLUDE MATH.INC + +PUBLIC tdFixedMul +PUBLIC tdGetNormal +PUBLIC tdRotate +PUBLIC tdGetSurfaceLight +PUBLIC tdSetLight +PUBLIC tdSetRotation +PUBLIC tdSetTranslation +PUBLIC tdTransform +PUBLIC tdTransformToImage +PUBLIC tdTransformLight +PUBLIC tdBackPlaneCull +PUBLIC tdSetPerspective + +;----------------------------------------------------------- +; +; Data segment +; +MATH_DATA SEGMENT USE16 PARA PUBLIC 'DATA' + ASSUME ds:MATH_DATA + +INCLUDE SINCOS.INC ; Fixed 8:24 sin/cos table + +XRotation TPOINT <> ; 3x3 rotation matrix +YRotation TPOINT <> +ZRotation TPOINT <> + +Translation TPOINT <> ; Translation vector + +Light TPOINT <> ; Light vector +AmbientLight DW 00 ; Ambient light + +XScale DD 10000h ; Scaling factor for X coordinate +YScale DD 10000h ; Scaling factor for Y coordinate +PerspectiveDistance DD 20000000h + +MATH_DATA ENDS + +;----------------------------------------------------------- +; +; Code segment +; +MATH_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MATH_TEXT, es:NOTHING, fs:NOTHING + +tdSetPerspective PROC PASCAL FAR + ARG Perspective:DWORD, \ + ScaleX:DWORD, \ + ScaleY:DWORD + USES ds + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + mov eax, [Perspective] + mov [PerspectiveDistance], eax + mov eax, [ScaleX] + mov [XScale], eax + mov eax, [ScaleY] + mov [YScale], eax + + ret +tdSetPerspective ENDP + + +;----------------------------------------------------------- +; +; Sets the rotation matrix. +; +; Input: +; RX = X-axis rotation angle +; RY = X-axis rotation angle +; RZ = X-axis rotation angle +; Output: +; none +; +tdSetRotation PROC PASCAL FAR + ARG RX:WORD, \ + RY:WORD, \ + RZ:WORD + USES ds, si, di + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + mov bx, [RZ] + mov si, [RY] + mov di, [RX] + shl bx, 2 + shl si, 2 + shl di, 2 + + push ebp ; We use EBP as a scratch register + +; Set X rotation + mov eax, tblCos[bx] + imul tblCos[si] + mov [XRotation.X], edx + + mov eax, tblSin[bx] + imul tblCos[si] + mov [XRotation.Y], edx + + mov eax, tblSin[si] + sar eax, 8 ; Convert fixed 8:24 to fixed 16:16 + mov [XRotation.Z], eax + +; Set Y rotation + mov eax, tblCos[bx] + imul tblSin[si] ; EDX:EAX = fixed 16:48 + shrd eax, edx, 24 ; EAX = fixed 8:24 + imul tblSin[di] ; EDX:EAX = fixed 16:48 + mov ebp, eax + mov ecx, edx + mov eax, tblSin[bx] + imul tblCos[di] + add eax, ebp + adc edx, ecx ; EDX:EAX = fixed 16:48 + neg edx + mov [YRotation.X], edx + + mov eax, tblSin[bx] + imul tblSin[si] + shrd eax, edx, 24 + imul tblSin[di] + mov ebp, eax + mov ecx, edx + mov eax, tblCos[bx] + imul tblCos[di] + sub eax, ebp + sbb edx, ecx + mov [YRotation.Y], edx + + mov eax, tblCos[si] + imul tblSin[di] + mov [YRotation.Z], edx + +; Set Z rotation + mov eax, tblCos[bx] + imul tblSin[si] + shrd eax, edx, 24 + imul tblCos[di] + mov ebp, eax + mov ecx, edx + mov eax, tblSin[bx] + imul tblSin[di] + sub eax, ebp + sbb edx, ecx + mov [ZRotation.X], edx + + mov eax, tblSin[bx] + imul tblSin[si] + shrd eax, edx, 24 + imul tblCos[di] + mov ebp, eax + mov ecx, edx + mov eax, tblCos[bx] + imul tblSin[di] + add eax, ebp + add edx, ecx + neg edx + mov [ZRotation.Y], edx + + mov eax, tblCos[si] + imul tblCos[di] + mov [ZRotation.Z], edx + + pop ebp ; Restore EBP + + ret +tdSetRotation ENDP + +;----------------------------------------------------------- +; +; Sets the translation vector. +; +; Input: +; TV = pointer to translation vector +; Output: +; none +; +tdSetTranslation PROC PASCAL FAR + ARG TV:DWORD + USES ds, es, di + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + les di, [TV] + mov eax, es:[di].X + mov [Translation.X], eax + mov eax, es:[di].Y + mov [Translation.Y], eax + mov eax, es:[di].Z + mov [Translation.Z], eax + + ret +tdSetTranslation ENDP + +;----------------------------------------------------------- +; +; Transforms an array of TPOINT. +; +; Input: +; Source = pointer to source array of TPOINT +; Dest = pointer to destination array of TPOINT +; Count = number of entries to transform +; Output: +; none +; +tdTransform PROC PASCAL FAR + ARG Source:DWORD, \ + Dest:DWORD, \ + Count:WORD + LOCAL Adjust:DWORD + USES ds, si, es, di, fs + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + lfs si, [Source] + les di, [Dest] + + ALIGN DWORD +@@Loop: +; Transform Z coordinate + mov eax, fs:[si].X + imul [ZRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [ZRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [ZRotation.Z] + add eax, ecx + adc edx, ebx + mov ebx, eax + shrd eax, edx, 16 + add eax, [Translation.Z] ; EAX = new Z coord (fixed 16:16) + mov es:[di].Z, eax +; Get perspective factor + mov ebx, [PerspectiveDistance] + sub eax, ebx + neg eax ; EAX = PD - Z + xor edx, edx + shld edx, eax, 16 + shl eax, 16 + idiv ebx ; EAX = fixed 16:16 result + mov [Adjust], eax + +; Transform X coordinate + mov eax, fs:[si].X + imul [XRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [XRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [XRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + add eax, [Translation.X] + imul [Adjust] + shrd eax, edx, 16 + mov es:[di].X, eax + +; Transform Y coordinate + mov eax, fs:[si].X + imul [YRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [YRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [YRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + add eax, [Translation.Y] + imul [Adjust] + shrd eax, edx, 16 + mov es:[di].Y, eax + + add si, SIZE TPOINT + add di, SIZE TPOINT + dec [Count] + jnz @@Loop + + ret +tdTransform ENDP + +;----------------------------------------------------------- +; +; Transforms an array of TPOINT into an array of TIMAGEPOINT. +; +; Input: +; Source = pointer to source array of TPOINT +; Dest = pointer to destination array of TIMAGEPOINT +; Count = number of entries to transform +; DeltaX = translation distance for the X coordinate +; DeltaY = translation distance for the Y coordinate +; Output: +; the maximum Z value +; +tdTransformToImage PROC PASCAL FAR + ARG Source:DWORD, \ + Dest:DWORD, \ + Count:WORD, \ + DeltaX:WORD, \ + DeltaY:WORD + LOCAL Adjust:DWORD, \ + Max:DWORD + USES ds, si, es, di, fs + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + lfs si, [Source] + les di, [Dest] + mov [Max], 80000000h + +@@Loop: +; Check max Z + mov eax, fs:[si].Z + cmp eax, [Max] + jle @@1 + mov [Max], eax +@@1: + +; Transform X coordinate + mov ax, WORD PTR fs:[si].X[2] + add ax, [DeltaX] + mov es:[di].IX, ax + +; Transform Y coordinate + mov ax, WORD PTR fs:[si].Y[2] + add ax, [DeltaY] + mov es:[di].IY, ax + + add si, SIZE TPOINT + add di, SIZE TIMAGEPOINT + dec [Count] + jnz @@Loop + + mov eax, [Max] + shld edx, eax, 16 + ret +tdTransformToImage ENDP + +;----------------------------------------------------------- +; +; Sets the light source. +; +; Input: +; Light = pointer to light vector +; Output: +; none +; +tdSetLight PROC PASCAL FAR + ARG L:DWORD + USES ds, es, di + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + les di, [L] + mov eax, es:[di].X + mov [Light.X], eax + mov eax, es:[di].Y + mov [Light.Y], eax + mov eax, es:[di].Z + mov [Light.Z], eax + + ret +tdSetLight ENDP + +;----------------------------------------------------------- +; +; Computes light intensity for an array of surfaces. +; +; Input: +; Normals = pointer to an array of surface normals +; Lights = pointer to an array of integer to be filled with +; light intensity +; Count = number of elements to transform +; Output: +; none +; +tdTransformLight PROC PASCAL FAR + ARG Normals:DWORD, \ + Lights:DWORD, \ + Count:WORD + USES ds, si, es, di, fs + + mov ax, SEG MATH_DATA + mov fs, ax + ASSUME fs:MATH_DATA + + lds si, [Normals] + les di, [Lights] + ASSUME ds:NOTHING + +; Intensity is given by the dot product between the Light vector and +; the surface normal +@@Loop: + mov eax, ds:[si].Z + imul [Light.Z] + mov ebx, eax + mov ecx, edx + mov eax, ds:[si].Y + imul [Light.Y] + add ebx, eax + adc ecx, edx + mov eax, ds:[si].X + imul [Light.X] + add eax, ebx + adc edx, ecx ; EDX:EAX = fixed 32:32 intensity + add dx, [AmbientLight] + test dx, dx + jg @@1 + xor dx, dx ; Return 0 for no light +@@1: + mov es:[di], dx + inc di + inc di + add si, SIZE TPOINT + dec [Count] + jnz @@Loop + + ASSUME fs:NOTHING + ret +tdTransformLight ENDP + +;----------------------------------------------------------- +; +; Returns the light value given the normal to a surface. +; +; Input: +; Normal = pointer to TPOINT surface normal vector +; Output: +; AX = light intensity (>=0) +; Notes: +; the normal is rotated according to the current setting. +; +tdGetSurfaceLight PROC PASCAL FAR + ARG Normal:DWORD + USES ds, esi, es, di + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + les di, [Normal] + +; Transform Z coordinate + mov eax, es:[di].X + imul [ZRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, es:[di].Y + imul [ZRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, es:[di].Z + imul [ZRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + imul [Light.Z] + shrd eax, edx, 16 + mov esi, eax + +; Transform X coordinate + mov eax, es:[di].X + imul [XRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, es:[di].Y + imul [XRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, es:[di].Z + imul [XRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + imul [Light.X] + shrd eax, edx, 16 + add esi, eax + +; Transform Y coordinate + mov eax, es:[di].X + imul [YRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, es:[di].Y + imul [YRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, es:[di].Z + imul [YRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + imul [Light.X] + shrd eax, edx, 16 + add eax, esi + shr eax, 16 + +; Add ambient light + add ax, [AmbientLight] + test ax, ax + jge @@Exit + xor ax, ax + +@@Exit: + ret +tdGetSurfaceLight ENDP + +;----------------------------------------------------------- +; +; Rotates an array of TPOINT. +; +; Input: +; Source = pointer to source array of TPOINT +; Dest = pointer to destination array of TPOINT +; Count = number of entries to transform +; Output: +; none +; +tdRotate PROC PASCAL FAR + ARG Source:DWORD, \ + Dest:DWORD, \ + Count:WORD + USES ds, si, es, di, fs + + mov ax, SEG MATH_DATA + mov ds, ax + ASSUME ds:MATH_DATA + + lfs si, [Source] + les di, [Dest] + +@@Loop: +; Transform Z coordinate + mov eax, fs:[si].X + imul [ZRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [ZRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [ZRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + mov es:[di].Z, eax + +; Transform X coordinate + mov eax, fs:[si].X + imul [XRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [XRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [XRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + mov es:[di].X, eax + +; Transform Y coordinate + mov eax, fs:[si].X + imul [YRotation.X] + mov ecx, eax + mov ebx, edx + mov eax, fs:[si].Y + imul [YRotation.Y] + add ecx, eax + adc ebx, edx + mov eax, fs:[si].Z + imul [YRotation.Z] + add eax, ecx + adc edx, ebx + shrd eax, edx, 16 + mov es:[di].Y, eax + + add si, SIZE TPOINT + add di, SIZE TPOINT + dec [Count] + jnz @@Loop + + ret +tdRotate ENDP + +tdFixedMul PROC PASCAL FAR + ARG F1:DWORD, \ + F2:DWORD + + mov eax, [F1] + imul [F2] + shr eax, 16 + + ret +tdFixedMul ENDP + +;----------------------------------------------------------- +; +; Returns in EAX the square root of EDX:EAX. +; +subSqrt PROC NEAR + push esi + push edi + + add eax, eax + adc edx, 0 + mov eax, edx ; Just discard the low bits + + mov esi, eax + xor edi, edi + shld edi, esi, 16 + shl esi, 16 +@@Loop: + mov ebx, eax + mul eax + add eax, esi + adc edx, edi + shrd eax, edx, 1 + shr edx, 1 + div ebx + cmp eax, ebx + jne @@Loop + +; Adjust EAX + shl eax, 8 + + pop edi + pop esi + ret +subSqrt ENDP + +;----------------------------------------------------------- +; +; Finds the unitary normal to a given surface. +; +; Input: +; Dest = pointer to TPOINT (vector) result +; P1, P2, P3 = pointer to TPOINT points on surface +; Output: +; none +; Notes: +; the normal is given by the cross-product between (P3-P1) and +; (P2-P1), so its orientation depends on the parameters order. +; +tdGetNormal PROC PASCAL FAR + ARG Dest:DWORD, \ + P1:DWORD, \ + P2:DWORD, \ + P3:DWORD + LOCAL V1:TPOINT, \ + V2:TPOINT, \ + N:TPOINT + USES ds, si, es, di + +; Get vector V1 + lds si, [P1] + les di, [P3] + mov eax, es:[di].X + sub eax, ds:[si].X + mov [V1.X], eax + mov eax, es:[di].Y + sub eax, ds:[si].Y + mov [V1.Y], eax + mov eax, es:[di].Z + sub eax, ds:[si].Z + mov [V1.Z], eax + +; Get vector V2 + les di, [P2] + mov eax, es:[di].X + sub eax, ds:[si].X + mov [V2.X], eax + mov eax, es:[di].Y + sub eax, ds:[si].Y + mov [V2.Y], eax + mov eax, es:[di].Z + sub eax, ds:[si].Z + mov [V2.Z], eax + +; Get normal vector (V1 x V2) + mov eax, [V1.Z] + imul [V2.Y] + mov ebx, eax + mov ecx, edx + mov eax, [V1.Y] + imul [V2.Z] + sub eax, ebx + sbb edx, ecx + shrd eax, edx, 16 + mov [N.X], eax + + mov eax, [V1.X] + imul [V2.Z] + mov ebx, eax + mov ecx, edx + mov eax, [V1.Z] + imul [V2.X] + sub eax, ebx + sbb edx, ecx + shrd eax, edx, 16 + mov [N.Y], eax + + mov eax, [V1.Y] + imul [V2.X] + mov ebx, eax + mov ecx, edx + mov eax, [V1.X] + imul [V2.Y] + sub eax, ebx + sbb edx, ecx + shrd eax, edx, 16 + mov [N.Z], eax + +; Get normal length + mov eax, [N.X] + imul eax + mov ebx, eax + mov ecx, edx + mov eax, [N.Y] + imul eax + add ebx, eax + adc ecx, edx + mov eax, [N.Z] + imul eax + add eax, ebx + adc edx, ecx ; EDX:EAX = N.X*N.X + N.Y*N.Y + N.Z*N.Z + call subSqrt ; EAX = normal length + mov ebx, eax + +; Adjust vector and save it + les di, [Dest] + mov eax, [N.X] + cdq + shld edx, eax, 16 + shl eax, 16 + idiv ebx + mov es:[di].X, eax + mov eax, [N.Y] + cdq + shld edx, eax, 16 + shl eax, 16 + idiv ebx + mov es:[di].Y, eax + mov eax, [N.Z] + cdq + shld edx, eax, 16 + shl eax, 16 + idiv ebx + mov es:[di].Z, eax + + ret +tdGetNormal ENDP + +TPOLY STRUC + Vtx DW 4 DUP(?) +TPOLY ENDS + +;----------------------------------------------------------- +; +; Performs surface removal on an array of polygons. +; +; Input: +; Poly = pointer to an array of TPOLY +; Vertex = pointer to an array of TPOINT +; Dest = pointer to an array of integer +; Count = number of polygons to check +; Step = size of TPOLY structure +; Output: +; if the n-th polygon is invisible the n-th entry of the +; Dest array is set to -1, other entries are not modified +; (so it's possible to use the Light array for Dest, because +; the light intensity is always >= 0) +; +tdBackPlaneCull PROC PASCAL FAR + ARG Step:WORD, \ + Poly:DWORD, \ + Vertex:DWORD, \ + Dest:DWORD, \ + Count:WORD + USES ds, si, es, di, fs + ASSUME ds:NOTHING + + mov ds, WORD PTR Vertex[2] + les di, [Poly] + mov fs, WORD PTR Dest[2] + +@@Loop: + mov ax, es:[di].Vtx[2] ; Index of 2nd vertex + shl ax, 2 + mov bx, ax + shl ax, 1 + add bx, ax ; BX = index*SIZE TPOINT + add bx, WORD PTR [Vertex] ; BX = offset of 2nd vertex + mov ax, es:[di].Vtx[4] ; Index of 3rd vertex + shl ax, 2 + mov si, ax + shl ax, 1 + add si, ax + add si, WORD PTR [Vertex] ; SI = offset of 3rd vertex + mov ecx, ds:[si].X + sub ecx, ds:[bx].X ; ECX = V3.X-V2.X + mov edx, ds:[si].Y + sub edx, ds:[bx].Y ; EDX = V3.Y-V2.Y + mov ax, es:[di].Vtx[0] ; Index of 1st vertex + shl ax, 2 + mov si, ax + shl ax, 1 + add si, ax + add si, WORD PTR [Vertex] ; SI = offset of 1st vertex + mov eax, ds:[si].X + sub eax, ds:[bx].X ; EAX = V1.X-V2.X + mov esi, ds:[si].Y + sub esi, ds:[bx].Y ; ESI = V1.Y-V2.Y + imul edx + mov ebx, eax + xchg ecx, edx ; ECX:EBX = (V1.X-V2.X)*(V3.Y-V2.Y) + mov eax, esi + imul edx ; EDX:EAX = (V1.Y-V2.Y)*(V3.X-V2.X) + sub eax, ebx + sbb edx, ecx + jl @@Next ; Polygon is visible + mov bx, WORD PTR [Dest] ; FS:BX -> current Dest entry + mov WORD PTR fs:[bx], -1 ; Remove polygon +@@Next: + add WORD PTR [Dest], 2 ; Next entry for dest + add di, [Step] ; Next polygon + dec [Count] + jnz @@Loop + + ret +tdBackPlaneCull ENDP + +MATH_TEXT ENDS +END diff --git a/16/xw__/modex/THREED.H b/16/xw__/modex/THREED.H new file mode 100755 index 00000000..b993ef86 --- /dev/null +++ b/16/xw__/modex/THREED.H @@ -0,0 +1,32 @@ +typedef struct { + long x, y, z; +} TVECTOR; + +#define PVECTOR TVECTOR far * + +#define TPOINT TVECTOR +#define PPOINT PVECTOR + +#define VPTR void far * + +#ifdef __cplusplus +extern "C" { +#endif + +long far pascal tdFixedMul( long, long ); +int far pascal tdGetSurfaceLight( PPOINT ); +long far pascal tdTransformToImage( VPTR, VPTR, short, short, short ); + +void far pascal tdBackPlaneCull( VPTR, VPTR, VPTR, short, short ); +void far pascal tdGetNormal( VPTR, PPOINT, PPOINT, PPOINT ); +void far pascal tdRotate( VPTR, VPTR, short ); +void far pascal tdSetLight( PVECTOR ); +void far pascal tdSetRotation( short, short, short ); +void far pascal tdSetTranslation( PVECTOR ); +void far pascal tdSetPerspective( long, long, long ); +void far pascal tdTransform( VPTR, VPTR, short ); +void far pascal tdTransformLight( VPTR, VPTR, short ); + +#ifdef __cplusplus +} +#endif diff --git a/16/xw__/modex/THREED.PAS b/16/xw__/modex/THREED.PAS new file mode 100755 index 00000000..8b712c9d --- /dev/null +++ b/16/xw__/modex/THREED.PAS @@ -0,0 +1,40 @@ +unit ThreeD; +interface + +type + TVector = record + X, Y, Z : longint; + end; + TPoint = TVector; + +function tdFixedMul( F1, F2: longint ): longint; +function tdGetSurfaceLight( var Normal: TPoint ): integer; +function tdTransformToImage( var Source, Dest; Count, DeltaX, DeltaY: integer ): longint; + +procedure tdBackPlaneCull( var Poly, Vertex, Dest; Count, Step: word ); +procedure tdGetNormal( var Dest, P1, P2, P3: TVector ); +procedure tdRotate( var Source, Dest; Count: word ); +procedure tdSetLight( var Light: TVector ); +procedure tdSetRotation( RX, RY, RZ: word ); +procedure tdSetTranslation( var TV: TVector ); +procedure tdSetPerspective( PD, XF, YF: longint ); +procedure tdTransform( var Source, Dest; Count: word ); +procedure tdTransformLight( var Source, Dest; Count: word ); + +implementation + +function tdGetSurfaceLight; external; +procedure tdSetRotation( RX, RY, RZ: word ); external; +procedure tdGetNormal; external; +procedure tdSetTranslation( var TV: TVector ); external; +procedure tdTransform( var Source, Dest; Count: word ); external; +procedure tdRotate; external; +function tdTransformToImage; external; +procedure tdSetLight( var Light: TVector ); external; +procedure tdSetPerspective; external; +procedure tdTransformLight; external; +function tdFixedMul( F1, F2: longint ): longint; external; +procedure tdBackPlaneCull; external; +{$L THREED} + +end. diff --git a/16/xw__/modex/demo01.c b/16/xw__/modex/demo01.c new file mode 100755 index 00000000..0908fdf4 --- /dev/null +++ b/16/xw__/modex/demo01.c @@ -0,0 +1,125 @@ +/* + DEMO01 - Sprites, page flipping and palette rotation + Copyright (c) 1994 Alessandro Scotti +*/ +uses Crt, Modex; + +#DEFINE MAX_SPRITE 100 +type + (* Sprite structure *) + TSprite = record + X, Y : integer; (* Sprite coordinates *) + DX,DY: integer; (* Deltas for sprite movement *) + W, H : integer; (* Sprite width and height *) + Image: array[ 1..16, 1..16 ] of byte; (* Sprite image data *) + end; + (* RGB color structure *) + TRgb = record + R, G, B: byte; + end; +var + S : array[ 1..MAX_SPRITE ] of TSprite; (* An array of sprites *) + Palette: array[ byte ] of TRgb; (* Palette *) + Page : word; (* Page offset *) + I : word; + +(* Initializes a sprite structure *) +procedure sxInit( var S: TSprite ); +var + I: word; +begin + S.X := Random( 320 ); (* Initialize position with random values *) + S.Y := Random( 240 ); + S.DX := Random( 7 )-3; (* Initialize speed with random values *) + S.DY := Random( 7 )-3; + S.W := 16; (* Size is fixed in this program *) + S.H := 16; + (* The image is a square with a hole inside *) + FillChar( S.Image, SizeOf(S.Image), Random(15)+1 ); + for I:=5 to 12 do FillChar( S.Image[ I, 5 ], 8, 0 ); +end; + +(* Moves a sprite *) +procedure sxMove( var S: TSprite ); +begin + Inc( S.X, S.DX ); (* Get new position *) + Inc( S.Y, S.DY ); + (* Check sprite position, change delta if needed *) + if( S.X > 320 ) then begin + S.X := 320; + S.DX := -S.DX; + end; + if( S.X < -16 ) then begin + S.X := -16; + S.DX := -S.DX; + end; + if( S.Y > 240 ) then begin + S.Y := 240; + S.DY := -S.DY; + end; + if( S.Y < -16 ) then begin + S.Y := -16; + S.DY := -S.DY; + end; + (* Draw the sprite, note the Page offset added to the *) + (* Y coordinate of the image *) + mxPutImage( @S.Image, S.X, Page+S.Y, S.W, S.H, OP_TRANS ); +end; + +begin + (* Initialize library *) + mxInit; + + (* Enter graphics mode *) + mxSetMode( MX_320x240 ); + + (* Print initialization message *) + mxSetTextColor( 15, OP_TRANS ); + mxOutStr( 4, 4, 'Initializing...' ); + + (* Initialize sprites *) + for I:=1 to MAX_SPRITE do sxInit( S[I] ); + + (* Draw background *) + for I:=1 to 192 do begin + mxCircle( 160, 480+120, I, I+63 ); + mxCircle( 161, 480+120, I, I+63 ); + end; + + (* Compute and set palette *) + for I:=1 to 192 do with Palette[I+63] do begin + R := 0; + G := 0; + B := 0; + if( I < 64 ) then + R := I shr 1+31 + else if( I < 128 ) then + G := (I-64) shr 1+31 + else + B := (I-128) shr 1+31; + end; + mxSetPalette( @Palette[64], 64, 192 ); + + (* Main loop *) + Page := 240; + while( not KeyPressed ) do begin + (* Set clip region to current page *) + mxSetClipRegion( 0, Page, 320, 240 ); + mxSetClip( TRUE ); + (* Restore background *) + mxBitBlt( 0, 480, 320, 240, 0, Page ); + (* Draw sprites *) + for I:=1 to MAX_SPRITE do sxMove( S[I] ); + (* Print message *) + mxOutStr( 4, Page+4, 'Some sprites moving...' ); + (* Flip page *) + mxStartLine( Page ); + Page := 240-Page; + (* Animate palette *) + mxSetPalette( @Palette[64], 64, 192 ); + mxRotatePalette( @Palette[64], 192, 3 ); + end; + + mxSetMode( MX_TEXT ); + mxTerm; +end. diff --git a/16/xw__/mxbb.asm b/16/xw__/mxbb.asm new file mode 100755 index 00000000..a403c631 --- /dev/null +++ b/16/xw__/mxbb.asm @@ -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 index 00000000..f59177f8 --- /dev/null +++ b/16/xw__/mxcc.asm @@ -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 index 00000000..72cd3abf --- /dev/null +++ b/16/xw__/mxcg.asm @@ -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 index 00000000..1f5af641 --- /dev/null +++ b/16/xw__/mxcl.asm @@ -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 index 00000000..254269f4 --- /dev/null +++ b/16/xw__/mxcr.asm @@ -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 index 00000000..e69de29b diff --git a/16/xw__/mxfb.asm b/16/xw__/mxfb.asm new file mode 100755 index 00000000..d0993a13 --- /dev/null +++ b/16/xw__/mxfb.asm @@ -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 index 00000000..45900b0b --- /dev/null +++ b/16/xw__/mxfp.asm @@ -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 index 00000000..5b128d22 --- /dev/null +++ b/16/xw__/mxgc.asm @@ -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 index 00000000..36fe7087 --- /dev/null +++ b/16/xw__/mxgi.asm @@ -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 index 00000000..0c97985d --- /dev/null +++ b/16/xw__/mxgm.asm @@ -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 index 00000000..19a10ccc --- /dev/null +++ b/16/xw__/mxgp.asm @@ -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 index 00000000..bbe19c95 --- /dev/null +++ b/16/xw__/mxgv.asm @@ -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 index 00000000..159e5c99 --- /dev/null +++ b/16/xw__/mxhl.asm @@ -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 index 00000000..4f68fddd --- /dev/null +++ b/16/xw__/mxit.asm @@ -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 index 00000000..94e5b2cd --- /dev/null +++ b/16/xw__/mxll.asm @@ -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 index 00000000..b488734b --- /dev/null +++ b/16/xw__/mxln.asm @@ -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 index 00000000..7bd60113 --- /dev/null +++ b/16/xw__/mxot.asm @@ -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 index 00000000..e431b138 --- /dev/null +++ b/16/xw__/mxot_.asm @@ -0,0 +1,333 @@ +;----------------------------------------------------------- +; +; MXOT.ASM - Text functions +; Copyright (c) 1994 by Alessandro Scotti +; +;----------------------------------------------------------- +;WARN PRO +;NOWARN RES ; We use the reserved name 'WIDTH' +INCLUDE MODEX.DEF + +PUBLIC mxOutChar +PUBLIC mxOutText +PUBLIC mxSetFont +PUBLIC mxSetTextColor +PUBLIC mxGetTextStep +PUBLIC mxSetTextStep + +MAX_WIDTH EQU 16 ; Must be <= 16 +MAX_HEIGHT EQU 32 + +MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE' + ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING + +EXTRN mx_CodeSegment : WORD +EXTRN mxPutImage : FAR + +; 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 OP_MOVE ; Raster op +mx_DeltaX DW 8 ; Horizontal step +mx_DeltaY DW 0 ; Vertical step + +;----------------------------------------------------------- +; +; Sets the current font. +; +; Input: +; Font = pointer to font data +; Width = width of font character in pixels +; Height = height of font character in pixels +; Output: +; AX = 0 on success, else invalid parameters +; +; Note: when the high word of Font (i.e. the segment) is zero, the low +; word is used to select one of the system fonts. +; +mxSetFont PROC FAR + push bp + mov bp,sp + sub sp,0 + push ds + .enter 0 + .push ds + + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, WORD PTR Font[2] ; Get font segment + test ax, ax ; Null segment? + jnz @@UserFont ; No, install user font + +; Install system font + mov ax, WORD PTR Font[0] ; Get font number + cmp ax, MX_MAXSYSFONT ; Check range + jb @@SystemFont + xor ax, ax ; Out of range, use default font +@@SystemFont: + shl ax, 1 + shl ax, 1 + mov bx, ax + mov ax, tbl_SystemFont[bx] ; Get font offset + mov WORD PTR mx_FontPtr[0], ax + mov WORD PTR mx_FontPtr[2], cs + mov al, BYTE PTR tbl_SystemFont[bx+2] + xor ah, ah + mov [mx_FontWidth], ax + mov [mx_DeltaX], ax + mov dl, BYTE PTR tbl_SystemFont[bx+3] + xor dh, dh + mov [mx_FontHeight], dx + mul dx + mov [mx_FontCharSize], ax + mov [mx_DeltaX], ax + xor ax, ax + mov [mx_DeltaY], ax + jmp @@Exit + +; Install user font +@@UserFont: + mov ax, -1 ; Assume an error + mov bx, [bp+8] + cmp bx, MAX_WIDTH + ja @@Exit ; Invalid character width + mov dx, [bp+4] + cmp dx, MAX_HEIGHT + ja @@Exit ; Invalid character height + mov [mx_FontWidth], bx + mov [mx_FontHeight], dx + mov ax, bx + add ax, 7 + shr ax, 1 + shr ax, 1 + shr ax, 1 + mul dx + mov [mx_FontCharSize], ax + mov ax, WORD PTR Font[0] + mov WORD PTR mx_FontPtr[0], ax + mov ax, WORD PTR Font[2] + mov WORD PTR mx_FontPtr[2], ax + xor ax, ax + +@@Exit: + .pop ds + ASSUME ds:NOTHING + ;.leave ARG_SIZE +mxSetFont ENDP + +;----------------------------------------------------------- +; +; Sets the text color and raster op. +; +; Input: +; Color = text color (foreground + background*256) +; Op = raster op +; Output: +; none +; +mxSetTextColor PROC FAR + ARG Op:WORD, \ + Color:WORD = ARG_SIZE + .enter 0 + .push ds + + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, [Color] + mov [mx_FontColor], ax + mov ax, [Op] + mov [mx_FontOp], ax + + xor ax, ax + .pop ds + ASSUME ds:NOTHING + .leave ARG_SIZE +mxSetTextColor ENDP + +;----------------------------------------------------------- +; +; Writes a character using the current font and attributes. +; +; Input: +; X, Y = video coordinates +; C = character to print +; Output: +; none +; +mxOutChar PROC FAR + ARG C:BYTE:2, \ + Y:WORD, \ + X:WORD = ARG_SIZE + LOCAL Image:BYTE:MAX_WIDTH*MAX_HEIGHT, \ + Count:WORD = AUTO_SIZE + .enter AUTO_SIZE + .push ds, si, es, di + ASSUME ds:NOTHING + +; Gets the pointer to font data for the selected character + lds si, DWORD PTR [mx_FontPtr] + mov al, [C] + xor ah, ah + mul [mx_FontCharSize] ; Offset into font + add si, ax ; DS:SI -> font data for character + +; Converts font data into a 256-color linear image + mov ax, ss + mov es, ax + lea di, [Image] + mov dx, [mx_FontColor] + mov ax, [mx_FontHeight] + mov [Count], ax +@@HeightLoop: + mov cx, [mx_FontWidth] + mov bh, ds:[si] + inc si ; Get a byte from font data + cmp cx, 8 + jbe @@WidthLoop ; Ok for width <= 8 + mov bl, ds:[si] ; Get another byte + inc si +@@WidthLoop: + mov al, dl ; Assume foreground color + shl bx, 1 ; Is font bit set? + jc @@1 ; Yes, foreground is just great + mov al, dh ; Get background color +@@1: + mov es:[di], al ; Put pixel into image + inc di + dec cx + jnz @@WidthLoop + dec [Count] + jnz @@HeightLoop + +; Now pass image to mx_PutImage + lea ax, [Image] + push es + push ax ; Pointer to image + push [X] + push [Y] ; Image coordinates + push [mx_FontWidth] + push [mx_FontHeight] ; Image size + push [mx_FontOp] ; Raster op + call mxPutImage ; Write character + + xor ax, ax + .pop ds, si, es, di + .leave ARG_SIZE +mxOutChar ENDP + +;----------------------------------------------------------- +; +; Writes a string at the coordinates specified. +; +; Input: +; X, Y = text coordinates +; S = pointer to ASCIIZ string +; Output: +; none +; +mxOutText PROC FAR + ARG S:DWORD, \ + Y:WORD, \ + X:WORD = ARG_SIZE + .enter 0 + .push ds, si + ASSUME ds:NOTHING + + lds si, [S] +@@Loop: + mov al, ds:[si] + test al, al ; End of string? + jz @@Exit ; Yes, exit + inc si + push [X] ; Display character + push [Y] + push ax + call mxOutChar + mov ax, [mx_DeltaX] + add [X], ax ; Bump X coordinate + mov ax, [mx_DeltaY] + add [Y], ax ; Bump Y coordinate + dec [Count] + jnz @@Loop + +@@Exit: + xor ax, ax + .pop ds, si + .leave ARG_SIZE + ret +mxOutText ENDP + +;----------------------------------------------------------- +; +; Sets the distance between characters. +; +; Input: +; DeltaX = horizontal distance in pixels +; DeltaY = vertical distance in pixels +; Output: +; none +; +; Note: this function may be used to set the text direction. +; +mxSetTextStep PROC FAR + ARG DeltaY:WORD, \ + DeltaX:WORD = ARG_SIZE + .enter 0 + .push ds + + mov ds, [mx_CodeSegment] + ASSUME ds:MX_TEXT + + mov ax, [DeltaX] + mov [mx_DeltaX], ax + mov ax, [DeltaY] + mov [mx_DeltaY], ax + + .pop ds + .leave ARG_SIZE +mxSetTextStep ENDP + +;----------------------------------------------------------- +; +; Gets the current distance between characters. +; +; Input: +; DeltaX = pointer to horizontal distance in pixels (integer) +; DeltaY = pointer to vertical distance in pixels (integer) +; Output: +; none +; +mxGetTextStep PROC FAR + ARG DeltaY:DWORD, \ + DeltaX:DWORD = ARG_SIZE + .enter 0 + .push ds, si + ASSUME ds:NOTHING + + mov ax, [mx_DeltaX] + lds si, [DeltaX] + mov ds:[si], ax + mov ax, [mx_DeltaY] + lds si, [DeltaY] + mov ds:[si], ax + + .pop ds, si + .leave ARG_SIZE +mxGetTextStep ENDP + +MX_TEXT ENDS +END diff --git a/16/xw__/mxpb.asm b/16/xw__/mxpb.asm new file mode 100755 index 00000000..36ed3527 --- /dev/null +++ b/16/xw__/mxpb.asm @@ -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 index 00000000..3777fe5e --- /dev/null +++ b/16/xw__/mxpf.asm @@ -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 index 00000000..7318f079 --- /dev/null +++ b/16/xw__/mxpg.asm @@ -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 index 00000000..3484a58d --- /dev/null +++ b/16/xw__/mxpi.asm @@ -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 index 00000000..7b60449d --- /dev/null +++ b/16/xw__/mxpn.asm @@ -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 index 00000000..d15387eb --- /dev/null +++ b/16/xw__/mxpp.asm @@ -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 index 00000000..539f4ee7 --- /dev/null +++ b/16/xw__/mxra.asm @@ -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 index 00000000..be508c59 --- /dev/null +++ b/16/xw__/mxrp.asm @@ -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 index 00000000..8504fa95 --- /dev/null +++ b/16/xw__/mxsa.asm @@ -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 index 00000000..e65d8460 --- /dev/null +++ b/16/xw__/mxsc.asm @@ -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 index 00000000..a9179a88 --- /dev/null +++ b/16/xw__/mxsi.asm @@ -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 index 00000000..2b25844a --- /dev/null +++ b/16/xw__/mxsl.asm @@ -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 index 00000000..ccad79ec --- /dev/null +++ b/16/xw__/mxsm.asm @@ -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 index 00000000..7ed046f6 --- /dev/null +++ b/16/xw__/mxsp.asm @@ -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 index 00000000..aba7db99 --- /dev/null +++ b/16/xw__/mxss.asm @@ -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 index 00000000..e93aedf6 --- /dev/null +++ b/16/xw__/mxtl.asm @@ -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 index 00000000..feafb66a --- /dev/null +++ b/16/xw__/mxvs.asm @@ -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 index 00000000..7f491f39 --- /dev/null +++ b/16/xw__/mxwd.asm @@ -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 index 00000000..271eebad --- /dev/null +++ b/16/xw__/mxwm.asm @@ -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 index 00000000..45e32f37 --- /dev/null +++ b/16/xw__/mxwp.asm @@ -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 index 00000000..5fccb47d --- /dev/null +++ b/16/xw__/mxwr.asm @@ -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 index 00000000..306e8b9a --- /dev/null +++ b/16/xw__/readme.txt @@ -0,0 +1,8 @@ +ModeX - A graphical library for DOS programs +Copyright (c) 1993-1994 Alessandro Scotti +http://www.ascotti.org/ + +Please look at the above site in the "Art of..." and +then in the "Old programs" section for more information. + + diff --git a/16/xw__/xw.bat b/16/xw__/xw.bat new file mode 100755 index 00000000..1fd24399 --- /dev/null +++ b/16/xw__/xw.bat @@ -0,0 +1,39 @@ +@echo off +wdis -a MXBB.OBJ > mxbb.asm +wdis -a MXCC.OBJ > mxcc.asm +wdis -a MXCG.OBJ > mxcg.asm +wdis -a MXCL.OBJ > mxcl.asm +wdis -a MXCR.OBJ > mxcl.asm +wdis -a MXFB.OBJ > mxfb.asm +wdis -a MXFP.OBJ > mxfp.asm +wdis -a MXGC.OBJ > mxgc.asm +wdis -a MXGI.OBJ > mxgi.asm +wdis -a MXGM.OBJ > mxgm.asm +wdis -a MXGP.OBJ > mxgp.asm +wdis -a MXGV.OBJ > mxgv.asm +wdis -a MXHL.OBJ > mxhl.asm +wdis -a MXIT.OBJ > mxit.asm +wdis -a MXLL.OBJ > mxll.asm +wdis -a MXLN.OBJ > mxln.asm +wdis -a MXOT.OBJ > mxot.asm +wdis -a MXPB.OBJ > mxpb.asm +wdis -a MXPF.OBJ > mxpf.asm +wdis -a MXPG.OBJ > mxpg.asm +wdis -a MXPI.OBJ > mxpi.asm +wdis -a MXPN.OBJ > mxpn.asm +wdis -a MXPP.OBJ > mxpp.asm +wdis -a MXRA.OBJ > mxra.asm +wdis -a MXRP.OBJ > mxrp.asm +wdis -a MXSA.OBJ > mxsa.asm +wdis -a MXSC.OBJ > mxsc.asm +wdis -a MXSI.OBJ > mxsi.asm +wdis -a MXSL.OBJ > mxsl.asm +wdis -a MXSM.OBJ > mxsm.asm +wdis -a MXSP.OBJ > mxsp.asm +wdis -a MXSS.OBJ > mxss.asm +wdis -a MXTL.OBJ > mxtl.asm +wdis -a MXVS.OBJ > mxvs.asm +wdis -a MXWD.OBJ > mxwd.asm +wdis -a MXWM.OBJ > mxwm.asm +wdis -a MXWP.OBJ > mxwp.asm +wdis -a MXWR.OBJ > mxwr.asm diff --git a/awoo.sh b/awoo.sh index 5073f2bf..f5b766ec 100755 --- 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" ] diff --git a/bakapi.exe b/bakapi.exe index 12a74beaa89c65432d15a945a513b52f8aaa10e3..fee866d459ea0db41a0293ec699420ee03b387b9 100755 GIT binary patch literal 77981 zcmW)mWmwY<7smhVv5mp#W`J~qG$=Vx1ScR}qmdN0fub-{#()P~!9r}o2b7+YQX)zy zjxK|CA`T?B_qpEl;aunQ`EZ~3-7dbzfj|HRfPpdz9`Cl;f5rbp=D&;t?xUO5{99N} z^ewrkb+p1>7z`+8!4T-;w*B7^_jG8nLW0RZF8y1D#bV*|2(dQ;0P`p9WdBK`w*o%| z!sjDe0yqBTaERjrl4}B1r$N9QUTUh9av0y4Gbu0>;J}L~hbQ6nwea-@U_+mSaS2$S zF`k@&Pol*0@FaY4Xi|7MCq9`(Rj!e$3D<4a!=I+CMU!=G5*&aK(ryeXF&eK_rE_#& zNAIAHzTpfE6`hQa+b4yE<3rB05)w&CF=u!OGov%}vPUy_b2CrjBRu0`p~?P7Ih160 z!!dl|ZXoJdbZCel*qnoRBpxG97zP5oAkc9z5t0SvdBA9Je#9X@o{iu#u2N`5n5QNJ zi2e|Ri@#h@P`xHr)?@(Use;uYc&H}qVq%G1tcV?4*IG_qSfWoM-0rx;NjmQvu`v}W zg#o-xgtwcgSN19|xN$&)S&e8;fEBYExp<%lzK(<@Y#_k^uY!%NSVcC1c7ejNie*&# zBC<5>(v)$j?Tkg^Jp>cJ3+VTi{)>4-?<^i?qV(JBD(P}>kid1Bwir3dz$j6zs&M|T z!tsiGN-wP%OnWhCaYzX`4{9rkh14|8uXiH=oz)_0izKy4h@U3`&?P`xPQ@LD!PuwSK`k>FCgc;n6H zYNJE;p`c?xiWqjk(G4J$cF*W!zl9b>aCd?NeFI$jf8M7DuF^YPH~I54`SH|O8!^rB zON)NXF{O&rGW7KI9&twCwfXOU?2x#xrVSkQb}93ZSZ-S#X`9~8GxlUE z?s7_(>vQ?o!%Hc=(H~8?Tt#FLuPbnoXHpy(?;7}h6mkC@@Le0SCINf)5d*?Zm0BQ( zaZ>!3-@ro@zXXZ695<{6hs2c&#mOKi3g8tnX-imM#;qc;Bc;+IjPx9ie_V03fPZO> z_G!|Fzu%d486QdGdgP|yz_jL6UwPzinQCY=5QIe9z|m0zI{9p7M&Dsx&*j?ajR^$IOA%6b)-c(iR>Qw+2M^~ z^064EU_y$)`S^sm1id*g6(9}pAcY9Fo=P~A3^>Jzi}-4OiC0TMnFtW{4VEDKEqZ_} zC2n2BHpYEL%nTfET5obXdCHSu{1R-`f6!1wKHkpa`^6BW@y*}Z@ zBjm4_2l(y!`TBT�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 JY}>CW{~vDVP#gdN delta 44860 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�pyA;*1WZzWIj2vc-T+Sr&|+@8i4cC>~SM1Z@ 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 delta 30986 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Ξ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 diff --git a/fmemtest.exe b/fmemtest.exe index c88212abf6af8315621abd78613afc60175f8178..f7f7ff4deca7d685618cf173f82597c8555d3d46 100755 GIT binary patch literal 60555 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

J^>fV=TA4}M*&mJ$@yT4 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 UqN2UsD(ZzJ75wEcrrpTusu$mx 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 qrn1tin`hE!akg%E-51@zl-*pRwZr delta 32872 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 diff --git a/fontgfx.exe b/fontgfx.exe index 577a02f48eff05042a7423c322a9f57059a60f73..ed49d78ab4ec2e9c0176f5aa640d4a85dcc7ca9f 100755 GIT binary patch literal 71333 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 V(2c#!*j8`aTUJuF(6iSW^IwyZT<8D* delta 39039 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

a{4^o2Aa0FLftni8vjt=AxJ$9 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 BYMlT8 diff --git a/fonttest.exe b/fonttest.exe index c59b86a554e7326206db41e5dc13539591fe8c4c..882c4d8f93d5736f633507d0ff7a58b043764c14 100755 GIT binary patch literal 61949 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 a{G29=GOA%$9c=JK<@sf18+J@Y=>Gsr7!H5{ delta 31290 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%0Asddtztrut&OTth0C-DQxCsYw`Eo+> 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

  • 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 diff --git a/palettec.exe b/palettec.exe index a357fa6f0a4318911858789e69243c6bb63f8361..42f7a095fda1df04589e3701133dbf379debcf1e 100755 GIT binary patch literal 70705 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 MwJWq?{R1NZ1$AgTI{*Lx delta 37512 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 N6q9^#9$hAg{~sKxv(*3q diff --git a/palettel.exe b/palettel.exe index 1ced8d499687a00d410417764ff3919ba3548bef..bd3308a941f45872965469e17b3d01dc10f035b5 100755 GIT binary patch literal 70932 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 delta 39363 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 delta 18 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 delta 18 acmew}k@@Q<#tGT1HK!ODer_yatpos8>Ihc= diff --git a/planrpcx.exe b/planrpcx.exe index 89919c9898dda5122619240f022119b022243ce3..2a242c93835d2922ff3c022e62f6182a5d8bf9f2 100755 GIT binary patch literal 53349 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 delta 31425 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

    RuOR|xlwa%V{n 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 F{{R{PXgUA@ literal 0 HcmV?d00001 diff --git a/src/lib/modex/packing.lst b/src/lib/modex/packing.lst new file mode 100755 index 00000000..88f817ca --- /dev/null +++ b/src/lib/modex/packing.lst @@ -0,0 +1,87 @@ + +PACKING LIST FOR MODEX104 + +DIRECTORY: \ - The Mode X Library versoon 1.04 + +ASM BAT 26 05-14-93 6:00p - Batch File to Assemble MODEX.ASM +MODE-X TXT 2135 05-14-93 6:00p - File Describing MODE X Routines +MODEX ASM 117039 05-14-93 6:00p - Assembly source to Mode X Library +MODEX BI 3238 05-14-93 6:00p - Include File for BASIC/PDS +MODEX H 2943 05-14-93 6:00p - Include File for C/C++ +MODEX OBJ 5208 05-14-93 6:00p - The Mode X Library +README DOC 3259 05-14-93 6:00p - Information on this Product +PACKING LST 4767 05-14-93 6:00p - This File + +DIRECTORY: \DEMOS - Mode X Demos + +CHARDEMO EXE 13066 05-14-93 6:00p - Demo of Multiple Fonts & Color Cycling +TEST6 EXE 19990 05-14-93 6:00p - Main Mode X Demo +ROM_8X8 FNT 1024 05-14-93 6:00p - Font for CHARDEMO.EXE +SPACEAGE FNT 1024 05-14-93 6:00p - Font for CHARDEMO.EXE +SYSTEM FNT 1024 05-14-93 6:00p - Font for CHARDEMO.EXE + +DIRECTORY: \DEMOS\BASIC7 - Demo Sources for Microsoft BASIC 7.1 (PDS) + +MAKE-LIB BAT 166 05-14-93 6:00p - Batch File to make MODEX.LIB/.QLB +MODEX BI 3238 05-14-93 6:00p - Include File for MODE X Library +MODEX LIB 7189 05-14-93 6:00p - Mode X & Utility Libraries for QBX +MODEX OBJ 5208 05-14-93 6:00p - Mode X Library - Object File +MODEX QLB 11141 05-14-93 6:00p - Mode X & Utility Quick Library +TEST6 BAS 12733 05-14-93 6:00p - Main Demo Source Code (TEST6.EXE) +UASM-BC7 BAT 43 05-14-93 6:00p - Batch file to Make UTILS.OBJ for QBX +UTILS ASM 8506 05-14-93 6:00p - Basic Utilities - Assembler source +UTILS BI 2028 05-14-93 6:00p - Basic Utilities - Basic Includes +UTILS OBJ 681 05-14-93 6:00p - Basic Utilities - Object File +CHARDEMO BAS 3431 05-14-93 6:00p - Source to CHARDEMO.EXE + +DIRECTORY: \DEMOS\C - Demo Sources for Borland C/C++ + +C_UTILS ASM 8782 05-14-93 6:00p - C Utilities - Assembler source +C_UTILS H 2623 05-14-93 6:00p - C Utilities - C Includes +C_UTILS OBJ 648 05-14-93 6:00p - C Utilities - Object File +MODEX H 2943 05-14-93 6:00p - Mode X Library C Incldues +MODEX OBJ 5208 05-14-93 6:00p - Mode X Library +UTLS-ASM BAT 36 05-14-93 6:00p - Batch File to Make C_UTILS.OBJ +X-DEMO C 15085 05-14-93 6:00p - Source to Main Demo (TEST6) in C +X-DEMO EXE 41090 05-14-93 6:00p - C Version of Main Demo +X-DEMO PRJ 5188 05-14-93 6:00p - Borland C Project file + +DIRECTORY: \DEMOS\PASCAL - Demo Sources for Turbo Pascal + +TEST5 PAS 15873 05-14-93 6:00p - Source for a TP Version of TEST6.EXE + +DIRECTORY: \DEMOS\QB45 - Demo Sources for Microsoft QuickBASIC 4.5 + +MAKE-LIB BAT 164 05-14-93 6:00p - Batch File to make MODEX.LIB/.QLB +MODEX BI 3238 05-14-93 6:00p - Include File for MODE X Library +MODEX LIB 7189 05-14-93 6:00p - Mode X & Utility Libraries for QB45 +MODEX OBJ 5208 05-14-93 6:00p - Mode X Library - Object File +MODEX QLB 9739 05-14-93 6:00p - Mode X & Utility Quick Library/QB45 +TEST6A BAS 12743 05-14-93 6:00p - Main Demo Source Code (TEST6.EXE) +TEST6A EXE 40544 05-14-93 6:00p - QB45 Version of Main Demo +UASM-QB4 BAT 30 05-14-93 6:00p - Batch file to Make UTILS.OBJ for QB45 +UTILS ASM 8506 05-14-93 6:00p - Basic Utilities - Assembler source +UTILS BI 2028 05-14-93 6:00p - Basic Utilities - Basic Includes +UTILS OBJ 628 05-14-93 6:00p - Basic Utilities - Object File + +DIRECTORY: \FONTEDIT - Font Editor + +CSEDIT EXE 39242 05-14-93 6:00p - Font Editor Program +CSEDIT DOC 8629 05-14-93 6:00p - Font Editor Documentation +CHARSETS CS 2144 05-14-93 6:00p - Internal Fonts for Editor +MOUSEIMG CS 128 05-14-93 6:00p - Mouse Pointers for Editor +PALETTE CS 768 05-14-93 6:00p - Palette for Editor +INVERSE FNT 1024 05-14-93 6:00p - Sample Font +ROM_8X8 FNT 1024 05-14-93 6:00p - Sample Font +SPACEAGE FNT 1024 05-14-93 6:00p - Sample Font +SYSTEM FNT 1024 05-14-93 6:00p - Sample Font + +DIRECTORY: \PALEDIT - Palette Editor + +PALEDIT EXE 31954 05-14-93 6:00p - Palette Editor Program +PALEDIT DOC 6688 05-14-93 6:00p - Palette Editor Documentation +CHARSETS CS 2144 05-14-93 6:00p - Internal Fonts for Editor +MOUSEIMG CS 128 05-14-93 6:00p - Mouse Pointers for Editor +GAMECOLR PAL 768 05-14-93 6:00p - Sample Palette +PRIME PAL 768 05-14-93 6:00p - Sample Palette +RGB PAL 768 05-14-93 6:00p - Sample Palette diff --git a/src/lib/modex/paledit/bakapi.pal b/src/lib/modex/paledit/bakapi.pal new file mode 100755 index 0000000000000000000000000000000000000000..d4d4a6a097bb4a8dd05fbaf5509f700be81b1b52 GIT binary patch literal 768 zcmZvaK??#Q5Jta4k>xhchKAID9Tti}mO5g7U!dKIx>8Wj~Y(D_9fe^$) zq~HZ4*hm{H+YdxCl6aCpB84F2g+^&ZW&6Q7IXMYV&Q7Fo78k^wqz#qr2Y^>#10KL! z7#N1J;x<&aAB^Fh;lVH&<^r)9*zC9smF)*>d9b{fazkYW)cg-{{Pq!F&fRpE+dlJCu4ehhhcyPv){@Bht-sFQSU z?`Ur=rF3mP9s`G~&wl*=$?EXx>WcWGqImeQw?g*Kn|B$j<8L9yRdu}o^5y<<<={3R zJ91BVemh_^&-b1i&-V^qIlB4L%_JF3?W2uH8ylZp>f!4Cv;EZ}DLZpBtEjiQ;#L-W z6c4L7u75%mXAG#CsbTFza*OjM2!4p3-Wj(2t#=j~I%LJ8fw*LYP9bC>57Rj1{9ZA7Mt z6KS4Onx_vgng8 z5ChN7E_A{E#u-DcG5iJBS|ct9q$P*ET4SFcHJ_hw-p*IT;K*e|=JU&VGnr1~~8H#+(P@Jm%Ot$eFuBJd>w6;$lt( zZ_xR{Vt$gPB+U&6Ju11bu*7}I%|Ck}`V-5W(=w<`MO-ZROI!i+W5yLm>$%e<4W%p) z7`$kjGQ>J~AGk9ZCWI)&)d=%cYd-+8T!t)QpYs5Kexkqot2Z4Fs z`R41b%`e0!UwyeH{!fS&ZY*{lZ@m|a$Iauzf)uuYju0V`tBS9351aLIx zKoYE`puPCvqHV#G^>wrnw9VmR)6&9HxV5`0DPT3nNkt;8{TC0{5AmfyPur=6UpQ=s zxYo!wnILk%u4}5ni%GGJ-#Ow4ghL)og!7>;E{stKtVwWvI2Xw*@hE4KQLFRa)0hVH z{}+J}BY08(?-3mP)Jab%MT$7DR|L0b_`tuYN6S;-uczYEpKvZ!rX1M!Z2JyuC%E7IvA=GDa(`>QD+soN|ACXgvqk-8t6F z`g+b`2YrteKAa~bA0JsVwj+xV5RCQLr_l%|@VE1Ph*N`Wpk_V#vYyv-u06L(E9KAY zn$Pj}eir>RM^&{1s#<$J!mwX3n@lF#&_nC>86X2k^*$bR_5;^75OWrqIpVS%j_3Kj zU$BjM*bnsZ?9kg;v}e&js#Nd~5GEQhM;P#a24hIyzo+2B|8*@NyU3c zKhoDl(t4iF`zI7CEZbYo-&2HyY)=?K#(E3@obyW5K^Oq{Pa2IdqU?;31F1O*Ao42S zpH^MH76I4}Zg!5~0c~&l{;AHgn)NV{g3yP^a9{fpdzW07LSf8BB*6Q(VGO|>EaR=u c@7}+=v9)<$+}Yd`AAF4Uy(KWY!FGSkU-|#d0ssI2 literal 0 HcmV?d00001 diff --git a/src/lib/modex/paledit/diagonal.pal b/src/lib/modex/paledit/diagonal.pal new file mode 100755 index 0000000000000000000000000000000000000000..5dee1969fc3e9dfe5bee855460c512ba3a850e69 GIT binary patch literal 768 zcmWO4fugA}007W2rBcR}O4&6{OBqvI%Gm$^)qCd~4gg>dt%dE`E^_?PL#dC+Ix03v zg)s=;JrU8Lq&#;GQ)M~QO6RqSZwB9WAV;TF@YMk&t+()|8fhN>SZXNw zlH!w9V#CCj>_H=5QV=V{ZZuhLc}5w0$MS6i*`%&nsp;R@Bdai@dcK(N!vFYzrI<7GXD-dFIX2(s-WZI;c#O)}jL4N_^8 zTcu8u)7UF|4Pgnx;^Wefi<_1%Ep1+!vLNT!Y}jtu?JDGc&+$l%HZrbP=9$}#$AjmS z*Na+Q6g63GQa8zs>ZAOi5HxtjUZd00DYeRtim4rL!)D8N$Ihm-XMf}viC>HtuD_TQ zw{IT5c@|#g$5NW2HtQqFP3lMas4(adbn^P@b#;~O(dtj5s{bLtd&Hga3vnS?g@jJX YqmSBdQG+6i^ro%x_>On~3fi#v3oGhTWdHyG literal 0 HcmV?d00001 diff --git a/src/lib/modex/paledit/mouseimg.cs b/src/lib/modex/paledit/mouseimg.cs new file mode 100755 index 0000000000000000000000000000000000000000..101e2084b44a2da8647ea004e20ffc599897dc29 GIT binary patch literal 128 zcmXwwyA6Xt5JVqBG8vc(jsUrhb3`33!65-+x3nvTG6*aUE5LfeXnx8{>eQ%KC5%j> xL+EL0E7_Ch82ppy6n|(>dLPTn2m0He)d4^WFp&TN literal 0 HcmV?d00001 diff --git a/src/lib/modex/paledit/paledit.doc b/src/lib/modex/paledit/paledit.doc new file mode 100755 index 00000000..61d0b2ee --- /dev/null +++ b/src/lib/modex/paledit/paledit.doc @@ -0,0 +1,166 @@ + +PALEDIT - A Simple VGA 256 Color Palette Editor + + +PALEDIT is distributed with MODEXnnn.ZIP, the general purpose MODE X +Library for VGA Graphics. + +WHAT YOU NEED TO RUN PALEDIT: + + * A Vga Monitor + * A Microsoft Compatible Mouse + + A Mouse is most definitely required, as the keyboard is used for + nothing except entering file names. + +FILES NEEDED IN THE CURRENT DIRECTORY: + + PALEDIT.EXE - The Palette Editor Program + CHARSETS.CS - The Palette Editor's Internal Fonts + MOUSEIMG.CS - The Palette Editor's Mouse Pointer + +SAMPLE PALETTE FILE THAT SHOULD BE INCLUDED: + + RGB.PAL - A Simple Palette with Reds, Greens, and Blues + PRIME.PAL - A Simple Palette + GAMECOLR.PAL - A Bright Palette from a Game of mine. + +WHAT IT EDITS: + + The VGA DAC Registers, all 256 of them. + +HOW IT WORKS/FEATURES: + + PALEDIT allows the user to see the entire VGA Palette of 256 colors + and select and modify the RED, GREEN, and BLUE values of any individual + color (DAC) register. The entire group of 256 colors can be saved to + a disk file for later retrieval. + + Individual "SLIDERS" show the current RED, GREEN, and BLUE color + components of the current color and allow them to be changed. + + The Following operations can be performed. + + * Raise, Lower, and set the RED, GREEN, or BLUE components. + * Copy the current RGB values to another Color (DAC) Register + * Brighten the selected color + * Darken and selected color + * Reset the selected color to its original state + * Blend an entire range of colors, creating a smooth + Transition from one color to another + * Optionally Lock out the first 16 colors to prevent + Accidental Modification + +DESCRIPTION OF OBJECTS/FEATURES FROM THE TOP DOWN: + + COLOR SLIDERS: In the upper left of the screen there are + Three Rectangular Boxes: One for each primary color: + RED, GREEN, and BLUE. Each Box has an arrow at each + end, and a scale bar in the middle, connecting the two + arrows. The scale bar is much like a thermometer, + indicating how much of that color is in the selected + color. To the right of each Box, the name of the color + is indicated, along with the content color in the form + of a number from 0 to 63; where 0 means none of that + color goes into making the selected color, and 63 means + that the selected color is saturated with that color. + + Clicking the mouse on the slider's left arrow box will + decrease the amount of that primary color in the selected + color. Holding the mouse button down will reduce the + color value all the way to 0. + + Clicking the mouse on the slider's right arrow box will + increase the amount of that primary color in the selected + color. Holding the mouse button down will increase the + color value all the way to 63. + + Clicking the mouse on the scale bar will set the amount + of that primary color to the value the represents that + position on the slider. + + LOCK Button: Clicking the button toggles the lockout of the + first 16 colors. When they are locked out, they can not + be modified, and when selected the word "LOCKED" will + appear below the color # on the Color Information Display. + + LOAD Button: Clicking this button will load the Palette file + that is named in the Palette File name box. If no name is + given or no such file exists, then nothing will be loaded. + + SAVE Button: Clicking this button will save the current Palette + in a file using the name given in the Palette File Name Box. + If a Valid name is not provided, nothing will be saved. + + QUIT Button: Clicking this button will return you to DOS. + Nothing is saved, and no confirmation is given. + + + Color Information Display: This Box is on the left side of the + Screen, below the Color Sliders. It shows the number of the + currently selected color (from 0 to 255) and indicates if + that color is locked. To the right of this box is a big + square showing the current color. + + LIGHTER Button: Clicking this button will make the selected + color brighter. + + DARKER Button: Clicking this button will make the selected + color darker. + + RESET Button: Clicking this button will restore the selected + color to the value it had when it was first selected. + + BLEND Button: Clicking this button will let you Blend a range + of colors together. One end of the range of colors is the + currently selected color. After Clicking the BLEND button. + You must click on the color at the other end of the range + in the Palette Display Box. All of the colors in between + those two colors will be changed to represent a gradual + transition from the color at one end to the color at the + other end. + + PALETTE FILE NAME BOX: This Text Box is used to enter the name + of a Palette file to load or the name to save the current + Palette as. Just click on the Box, and it will change color + and a flashing cursor will appear. Now you type in a filename + or edit the existing filename. Press or click + outside the text box to end editing. + + PALETTE DISPLAY BOX: This Box shows all 256 colors in an array + of 32 by 8 color blocks. The Currently Selected Color will + have a Box around it. Clicking on a color with the Left + Mouse button will make that color the new currently selected + color. Clicking on a color with the Right Mouse Button will + copy the color value from the old selected color to it, before + it is made the new selected color. + + Message Bar: At the very bottom of the screen, this Bar will display + information and messages for various functions. + +PALETTE FILE FORMAT: + + BINARY image, in order of VGA DAC (Color) Number. 3 Bytes Per + Color, 256 Colors. 768 Bytes total. The Files will be exactly + 768 bytes in size. + + COLOR: + RED: 1 BYTE + GREEN: 1 BYTE + BLUE: 1 BYTE + + PALETTE: Array (0 to 255) of COLOR + +COMMENTS, QUESTIONS, BUG REPORTS, etc: + + Send the to the Author: Matt Pritchard + + Through the 80xxx Fidonet Echo or + + Matt Pritchard + P.O. Box 140264 + Irving, TX 75014 + +CREDITS: + + This Palette Editor was written in QuickBASIC 4.5 diff --git a/src/lib/modex/paledit/paledit.exe b/src/lib/modex/paledit/paledit.exe new file mode 100755 index 0000000000000000000000000000000000000000..f69e172d05b32a8aa903c3857db0b199c84a91de GIT binary patch literal 70230 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℞6Tu?4W+slD)hB_fLLp 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 LZQpnAec3!FlnS+^wcg+JrM`4b~t%&As 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 JvY09JKLIz`z5M_H literal 0 HcmV?d00001 diff --git a/src/lib/modex/x_demo.c b/src/lib/modex/x_demo.c new file mode 100755 index 00000000..dfe9a3e0 --- /dev/null +++ b/src/lib/modex/x_demo.c @@ -0,0 +1,786 @@ +/* X-DEMO.C - a Mode "X" Demo */ +/* By Matt Pritchard, 14 Apr, 1993 */ + +#include +#include + +#include "modex.h" +#include "c_utils.h" + +#define MAX_SHAPES 32 +#define MAX_SPRITES 64 + + /* routines in this file */ + +void demo_res (int, int, int); +int get_key (void); +void error_out (char*); +void load_shapes (void); +int int_sqrt (int, int); +void page_demo (void); + + /* Structures for Sprites */ + +struct Shape +{ + unsigned char Image[512]; + int X_Width; + int Y_Width; +} Img [MAX_SHAPES]; + +struct Sprite +{ + int X_pos; + int Y_pos; + int X_Dir; + int Y_Dir; + int Shape; + int Last_X [2]; + int Last_Y [2]; +} Obj [MAX_SPRITES]; + + + /* MAIN */ + + +int main(int argc, char *argv[]) +{ + + /* if (argc > 0) + { + while (argc > 0) + { + dos_print ("Unknown Argument: "); + dos_print (makefp argv[argc]); + argc--; + } + return (0); + + } + */ + + init_random (); + + load_shapes (); + + demo_res ( Mode_320x200, 320, 200 ); + demo_res ( Mode_320x400, 320, 400 ); + + demo_res ( Mode_360x200, 360, 200 ); + demo_res ( Mode_360x400, 360, 400 ); + + demo_res ( Mode_320x240, 320, 240 ); + demo_res ( Mode_320x480, 320, 480 ); + + demo_res ( Mode_360x240, 360, 240 ); + demo_res ( Mode_360x480, 360, 480 ); + + page_demo (); + + set_video_mode (3); + dos_print ("This Mode X Demo is Finished"); + return (0); + +} + + + /* Demonstrate a given resolution */ + + +void demo_res (int Screen_Mode, int X_max, int Y_max) +{ + +char *Error1 = "Failure while calling SET_MODEX"; +char *Error2 = "Failure during READ_PIXEL test"; + +char *Abort_Msg = "Demo aborted by User"; + +char *Demo_Msg = " This is a MODE X demo "; +char *Scrn_Msg = "Screen Resolution is by "; +char *Cont_Msg = "Press to Continue"; + +char *Line_Msg = "LINE TEST"; +char *Fill_Msg = "FILL TEST"; +char *Pixel_Msg = "PIXEL TEST"; + +char Text[10]; + +int x1, y1, x2, y2 = 0; +int x, y, z = 0; +int X_Center, gap = 0; + + + if (set_modex (Screen_Mode) == 0) + { + error_out (Error1); + } + + X_Center = X_max / 2; + + x1 = 10; + y1 = 10; + x2 = X_max - 1; + y2 = Y_max - 1; + + for (z = 0; z <= 3; z++) + { + y = 31 - z -z; + draw_line (x1+z, y1+z, x2-z, y1+z, y); + draw_line (x1+z, y1+z, x1+z, y2-z, y); + draw_line (x1+z, y2-z, x2-z, y2-z, y); + draw_line (x2-z, y1+z, x2-z, y2-z, y); + } + + for (x = 0; x < (X_max / 10); x++) + { + tgprintc (48 + ((x+1) % 10), x*10+1, 1, 9 + ((x/8) % 7) ); + draw_line (x*10+9, 0, x*10+9, 3, c_bWHITE); + } + + for (y = 0; y < (Y_max / 10); y++) + { + tgprintc (48 + ((y+1) % 10), 1, y*10+1, 9 + ((y/10) % 7) ); + draw_line (0, y*10+9, 3, y*10+9, c_bWHITE); + } + + for (x = 0; x <= 63; x++) + { + z = 15 + (x * 3 / 4); + set_dac_register (64+x, z, z, z); + set_dac_register (128+x, 0, z, z); + + draw_line (103-x, 60, 40+x, 123, 64+x); + draw_line (40, 60+x, 103, 123-x, 128+x); + + } + + tprint_str (Line_Msg, 9, 37, 130, c_BLUE); + + y = 60; + gap = 0; + for (x = 0; x <= 9; x++) + { + fill_block (120, y, 120+x, y+gap, 64+x); + fill_block (140 - (15-x), y, 150+x, y+gap, 230+x); + fill_block (170 - (15-x), y, 170, y+gap, 128+x); + y = y + gap + 2; + gap++; + } + + tprint_str (Fill_Msg, 9, 110, 46, c_GREEN); + + for (x = 190; x <= 250; x+=2) + { + for (y = 60; y <= 122; y+=2) + { + z = (x+x+y+y) & 0xff; + set_point (x, y, z); + } + } + + tprint_str (Pixel_Msg, 10, 182, 130, c_RED); + + for (x = 190; x <= 250; x+=2) + { + for (y = 60; y <= 122; y+=2) + { + z = (x+x+y+y) & 0xff; + if (read_point(x, y) != z) + { + error_out (Error2); + } + } + } + + print_str (Demo_Msg, 23, X_Center - 92, 20, c_bRED, c_BLUE); + + x = X_Center - 124; + print_str (Scrn_Msg, 28, x, 30, c_bGREEN, c_BLACK); + + sprintf (Text, "%3d", X_max); + print_str (Text, 3, x+168, 30, c_bPURPLE, c_BLACK); + + sprintf (Text, "%3d", Y_max); + print_str (Text, 3, x + 224, 30, c_bWHITE, c_BLACK); + + for (x = 0; x <= 15; x++) + { + set_dac_register (230+x, 63-x*4, 0, 15+x*3); + draw_line (30+x, Y_max-6-x, X_max-20-x, Y_max-6-x, 230+x); + } + + tprint_str (Cont_Msg, 27, X_Center - 103, Y_max-18, c_YELLOW); + + if (get_key () == Ky_ESC) + { + error_out (Abort_Msg); + } + + return ; + +} + + + /* Wait for a Keystroke */ + + +int get_key(void) +{ + +int c = 0; + + while (c == 0) + { + c = scan_keyboard (); + } + + return (c); + +} + + + /* Error Handling Routine */ + + +void error_out (char * text) +{ + + set_video_mode (3); + dos_print (text); + exit (EXIT_SUCCESS); + +} + + + /* Routine to generate random sprites */ + + +void load_shapes () +{ + +unsigned char Grid[33][33]; + +char *Error1 = "Bad Shape Selected Error"; + +int Shape; +int x, y, z; +int Style, Color; +int X_Width, Y_Width, Center, S_Width; +int Hollow_X, Hollow_Y; + + for (Shape = 0; Shape < MAX_SHAPES; Shape++) + { + for (y = 0; y <= 32; y++) + { + for (x = 0; x <= 32; x++) + { + Grid[x][y] = c_BLACK; + } + } + + Style = random_int (6); + Color = 1 + random_int (15); + + switch (Style) + + { + /* SOLID BOXES */ + + case 0: + + { + do + { + X_Width = 3 + random_int(30); + Y_Width = 3 + random_int(30); + + } while ( (X_Width * Y_Width) >= 512); + + for (x = 1; x <= X_Width; x++) + { + for (y = 1; y <= Y_Width; y++) + { + Grid[x][y] = Color; + } + } + + break; + + } + /* HOLLOW BOXES */ + + case 1: + + { + do { + X_Width = 6 + random_int(27); + Y_Width = 6 + random_int(27); + } while ( (X_Width * Y_Width) >= 512); + + for (y = 1; y <= Y_Width; y++) + { + for (x = 1; x <= X_Width; x++) + { + Grid[x][y] = Color; + } + } + + Hollow_X = 1 + random_int ((X_Width / 2) -1); + Hollow_Y = 1 + random_int ((Y_Width / 2) -1); + + for (y = Hollow_Y+1; y <= Y_Width-Hollow_Y; y++) + { + for (x = Hollow_X+1; x <= X_Width-Hollow_X; x++) + { + Grid[x][y] = c_BLACK; + } + } + + break; + + } + + /* SOLID DIAMOND */ + + case 2: + + { + + X_Width = 3 + 2 * random_int(10); + Y_Width = X_Width; + Center = X_Width / 2; + + for (y = 0; y <= Center; y++) + { + for (x = 0; x <= y; x++) + { + Grid [Center-x+1][y+1] = Color; + Grid [Center+x+1][y+1] = Color; + Grid [Center-x+1][Y_Width-y] = Color; + Grid [Center+x+1][Y_Width-y] = Color; + } + } + + break; + + } + + /* HOLLOW DIAMOND */ + + case 3: + + { + + X_Width = 3 + 2 * random_int(10); + Y_Width = X_Width; + Center = X_Width / 2; + S_Width = random_int (Center); + + for (y = 0; y <= Center; y++) + { + for (x = 0; x <= y; x++) + { + if ( x+(Center-y) >= S_Width ) + { + Grid [Center-x+1][y+1] = Color; + Grid [Center+x+1][y+1] = Color; + Grid [Center-x+1][Y_Width-y] = Color; + Grid [Center+x+1][Y_Width-y] = Color; + } + } + } + + break; + + } + + /* BALL */ + + case 4: + + { + + X_Width = 7 + 2 * random_int (8); + Y_Width = X_Width; + Center = 1 + X_Width / 2; + + for (y = 1; y <= Y_Width; y++) + { + for (x = 1; x <= X_Width; x++) + { + z = int_sqrt(Center-x, Center-y); + if (z < Center) + { + Grid[x][y] = 150 + Color * 2 + z * 3; + } + } + } + + break; + } + + /* HOLLOW BALLS */ + + case 5: + + { + X_Width = 7 + 2 * random_int (8); + Y_Width = X_Width; + Center = 1 + X_Width / 2; + S_Width = random_int (X_Width); + + for (y = 1; y <= Y_Width; y++) + { + for (x = 1; x <= X_Width; x++) + { + z = int_sqrt(Center-x, Center-y); + if ( (z < Center) && (z >= S_Width) ) + { + Grid[x][y] = 150 + Color * 2 + z * 3; + } + } + } + + + break; + } + + default: + + { + error_out (Error1); + break; + + } + + } + + z = 0; + for (y = 1; y <= Y_Width; y++) + { + for (x = 1; x <= X_Width; x++) + { + Img[Shape].Image[z] = Grid[x][y]; + z++; + } + } + + Img[Shape].X_Width = X_Width; + Img[Shape].Y_Width = Y_Width; + + } + + return; +} + + + /* Quickie Psuedo Integer Square Root Routine */ + + +int int_sqrt ( int x, int y ) +{ + +int Sqr_Table[12] = {1, 4, 9, 6, 25, 36, 49, 64, 81, 100, 121, 144}; + +int r, d; + + d = (x * x) + (y * y); + r = 0; + + while ( d >= Sqr_Table[r] ) + { + r++; + } + + return (r); + +} + + + /* The Bit Sprite Demo */ + + +void page_demo () +{ + +char *Error1 = "Failure during SET_VGA_MODEX (0, 320, 200, 2) call"; + +int Last_Objects[2], Visible_Objects; + +int Screen_X = 384; +int Screen_Y = 224; + +int x, y, z; +int c, dc; +int x1, y1, x2, y2; + +int Sprite_X, Sprite_Y; +int Current_Page; +int New_X, New_Y; + +int View_X, View_Y, View_Max, View_Cnt, View_XD, View_YD; +int Set_Color, Prev_Color, S_Dir, P_Dir; + +int Demo_Running = True; +int redo, code; + +int pee; +pee = set_vga_modex(Mode_320x200, Screen_X, Screen_Y, 3); + if ( pee > 0) + { + set_video_mode (3); + dos_print (Error1); + fprintf(stdout, "return value is %d\n", pee); + //error_out (Error1); + exit (EXIT_SUCCESS); + } + + set_active_page (0); + clear_vga_screen (c_BLACK); + + print_str ("This is a Test of the Following Functions:", 99, 10, 9, c_bWHITE, c_BLACK); + + draw_line (10, 18, 350, 18, c_YELLOW); + print_str ("SET_ACTIVE_PAGE", 99, 10, 20, c_bBLUE, c_BLACK); + print_str ("SET_DISPLAY_PAGE", 99, 10, 30, c_GREEN, c_BLACK); + print_str ("SET_DAC_REGISTER", 99, 10, 40, c_RED, c_BLACK); + print_str ("CLEAR_VGA_SCREEN", 99, 10, 50, c_CYAN, c_BLACK); + + print_str ("TDRAW_BITMAP", 99, 10, 60, c_PURPLE, c_BLACK); + print_str ("COPY_PAGE", 99, 10, 70, c_GREEN, c_BLACK); + print_str ("COPY_BITMAP", 99, 10, 80, c_CYAN, c_BLACK); + + print_str ("GPRINTC", 99, 10, 90, c_BLUE, c_BLACK); + print_str ("TGPRINTC", 99, 10, 100, c_GREEN, c_BLACK); + print_str ("SET_WINDOW", 99, 10, 110, c_RED, c_BLACK); + + print_str ("VIRTUAL SCREEN SIZES", 20, 190, 20, c_bBLUE, c_BLACK); + print_str (" SMOOTH SCROLLING", 20, 190, 30, c_GREEN, c_BLACK); + print_str (" SPRITE ANIMATION", 20, 190, 40, c_CYAN, c_BLACK); + print_str (" PAGE FLIPPING", 20, 190, 50, c_RED, c_BLACK); + print_str (" COLOR CYCLING", 20, 190, 60, c_PURPLE, c_BLACK); + + for (x = 0; x <=60; x++) + { + set_dac_register (50 + x, 3 + x, 0, 60 - x); + set_dac_register (150 + x, 3 + x, 0, 60 - x); + } + + c = 0; + dc = 1; + for (x = 0; x <= (Screen_X / 2); x++) + { + draw_line (Screen_X / 2 - 1, Screen_Y / 4, x, Screen_Y - 1, c + 50); + draw_line (Screen_X / 2, Screen_Y / 4, Screen_X - x - 1, Screen_Y - 1, c + 50); + c+= dc; + if ((c == 0) || (c == 60) ) { dc = -dc;} + } + + tprint_str ("Press to Continue", 99, 72, 190, c_bWHITE); + tprint_str ("< > = Faster < > = Slower", 99, 72, 204, c_bGREEN); + tprint_str ("< > = Fewer Shapes < > = More Shapes", 99, 32, 218, c_bCYAN); + + tgprintc (43, 80, 204, c_YELLOW); + tgprintc (45, 200, 204, c_YELLOW); + + tgprintc (25, 40, 218, c_YELLOW); + tgprintc (24, 200, 218, c_YELLOW); + + copy_page (0, 1); + copy_page (0, 2); + + for (x = 0; x < MAX_SPRITES; x++) + { + do { + Obj[x].X_Dir = random_int(7) - 3; + Obj[x].Y_Dir = random_int(7) - 3; + } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) ); + + Obj[x].Shape = x % MAX_SHAPES; + + Sprite_X = Img[Obj[x].Shape].X_Width; + Sprite_Y = Img[Obj[x].Shape].Y_Width; + + Obj[x].X_pos = 1 + random_int(Screen_X - Sprite_X - 2); + Obj[x].Y_pos = 1 + random_int(Screen_Y - Sprite_Y - 2); + + Obj[x].Last_X[0] = Obj[x].X_pos; + Obj[x].Last_X[1] = Obj[x].X_pos; + Obj[x].Last_Y[0] = Obj[x].Y_pos; + Obj[x].Last_Y[1] = Obj[x].Y_pos; + + } + + Current_Page = 0; + + View_X = 0; + View_Y = 0; + View_Max = 3; + View_Cnt = 0; + View_XD = 1; + View_YD = 1; + + Set_Color = 3; + S_Dir = 1; + Prev_Color = 0; + P_Dir = 1; + + Visible_Objects = MAX_SPRITES / 2; + Last_Objects[0] = 0; + Last_Objects[1] = 0; + + while (Demo_Running) + { + + set_active_page (Current_Page); + + /* Erase Old Images */ + + for (x = 0; x <= Last_Objects[Current_Page]; x++) + { + z = 2; + y = Obj[x].Shape; + x1 = Obj[x].Last_X[Current_Page]; + y1 = Obj[x].Last_Y[Current_Page]; + x2 = x1 + Img[y].X_Width -1; + y2 = y1 + Img[y].Y_Width -1; + + x1 = x1 & 0xfffc; + x2 = x2 | 0x0003; + + copy_bitmap (z, x1, y1, x2, y2, Current_Page, x1, y1); + } + + /* Draw new images */ + + for (x = 0; x <= Visible_Objects; x++) + { + Sprite_X = Img[Obj[x].Shape].X_Width; + Sprite_Y = Img[Obj[x].Shape].Y_Width; + + /* Move Sprite */ + + do + { + redo = False; + New_X = Obj[x].X_pos + Obj[x].X_Dir; + + if (( New_X < 0 ) || (New_X + Sprite_X > Screen_X) ) + { + Obj[x].X_Dir = -Obj[x].X_Dir; + if (random_int(20) == 1) + { + do + { + Obj[x].X_Dir = random_int(7) - 3; + Obj[x].Y_Dir = random_int(7) - 3; + } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) ); + redo = True; + } + } + } while (redo); + Obj[x].X_pos = Obj[x].X_pos + Obj[x].X_Dir; + + + do + { + redo = False; + New_Y = Obj[x].Y_pos + Obj[x].Y_Dir; + + if ( (New_Y < 0) || (New_Y + Sprite_Y > Screen_Y) ) + { + Obj[x].Y_Dir = -Obj[x].Y_Dir; + if (random_int(20) == 1) + { + do + { + Obj[x].X_Dir = random_int(7) - 3; + Obj[x].Y_Dir = random_int(7) - 3; + } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) ); + redo = True; + } + } + } while (redo); + + Obj[x].Y_pos = Obj[x].Y_pos + Obj[x].Y_Dir; + + /* Draw Sprite */ + + tdraw_bitmap ((char far*) &Img[Obj[x].Shape], Obj[x].X_pos, Obj[x].Y_pos, Sprite_X, Sprite_Y); + + Obj[x].Last_X[Current_Page] = Obj[x].X_pos; + Obj[x].Last_Y[Current_Page] = Obj[x].Y_pos; + + } + + Last_Objects[Current_Page] = Visible_Objects; + + + /* Pan Screen Back & Forth */ + + View_Cnt++; + if (View_Cnt >= View_Max) + { + View_X+= View_XD; + if ( (View_X == 0) || (View_X == 39) ) {View_XD = -View_XD;} + if (View_XD < 0) + { + View_Y+= View_YD; + if ( (View_Y == 0) || (View_Y == 39) ) {View_YD = -View_YD;} + } + + set_window (Current_Page, View_X, View_Y); + + View_Cnt = 0; + } + else + { + set_display_page (Current_Page); + } + + /* Cycle Colors */ + + set_dac_register (50 + Prev_Color, 3 + Prev_Color, 0, 60 - Prev_Color); + set_dac_register (50 + Set_Color, Set_Color, 10, 63 - Set_Color); + + set_dac_register (150 + Prev_Color, 3 + Prev_Color, 0, 60 - Prev_Color); + set_dac_register (150 + Set_Color, 63, 63, Set_Color); + + Set_Color+= S_Dir; + if ( (Set_Color == 60) || (Set_Color == 0) ) {S_Dir = -S_Dir;} + + Prev_Color+= P_Dir; + if ( (Prev_Color == 60) || (Prev_Color == 0) ) {P_Dir = -P_Dir;} + + /* Check for Keystroke */ + + Current_Page = Current_Page ^ 0x01; + + code = scan_keyboard (); + + if (code == Ky_ESC) {Demo_Running = False;} + + if (code == Ky_Plus) + { + if (View_Max < 12) {View_Max++;} + } + + if (code == Ky_Minus) + { + if (View_Max > 1) {View_Max--;} + if (View_Cnt >= View_Max) {View_Cnt = 0;} + } + + if (code == Ky_Up) + { + if (Visible_Objects < MAX_SPRITES-1) {Visible_Objects++;} + } + + if (code == Ky_Down) + { + if (Visible_Objects > 0) {Visible_Objects--;} + } + + } + +} diff --git a/src/lib/modex/x_demo.dsk b/src/lib/modex/x_demo.dsk new file mode 100755 index 0000000000000000000000000000000000000000..5573e71a90522ffd46c36a16b5c9ba8abd65ca3e GIT binary patch literal 195 zcmWG3ElSE)a8_{6&nro-C{b|B%t=*{VqoMI5@(cRVBq@7IGX`T8!-UE2HDAKJ5*pa z6Ho-Z3gyjI;~eAX Z@8{_2YG9z}91y_3NB}Z0{Qu9u001}XCCdN+ literal 0 HcmV?d00001 diff --git a/src/lib/modex/x_demo.exe b/src/lib/modex/x_demo.exe new file mode 100755 index 0000000000000000000000000000000000000000..75369abaeac5b4ea65201db3e49bc84a54e7aca8 GIT binary patch literal 58447 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 b<+f4w;SoHPfq$oq^=;Y`S;let_E_xSH)f$o literal 0 HcmV?d00001 diff --git a/src/lib/modex/x_demo.prj b/src/lib/modex/x_demo.prj new file mode 100755 index 0000000000000000000000000000000000000000..b3f307e5c005eb0b7ef8346090f3cdce82a31210 GIT binary patch literal 4936 zcmeI$`BNKZ7zgm@O#-A~Db}Nfw(zQ}_80=Bauknk*rZIHEXjm)%vh?^ge_7F!4T>l z@OE_UwDlkGZoTpR$>V2jsg6f4{|Q@fTN|J6hQZWn+>pdFF zGM12<3?&mgjCe|J8s2Hh1`>;xE))D#<)*OnGqRDO&sm~_W_-wW#%wuk`cVx&{n+#q z(@$AJUzwR-n|{OE=?J@#jXgMD=X4+Bn?8h^^o@5Cd^A2n?_t41qfs8UdpqfwsF4 zjU$>svH+T@$G?)Za;34oZc!Z%x5j_STNA(HtB&tt=r@=E| z57-O#foFlEj;R2Zpb9uav+(i`mR?+9ioD$eJ;89m)92L&{C!$rv)5Pp!1EZPXA;q- zg7_Js=gBMv2vu>#TxPH7%pCl%eN zuWoa9t&vJ!u>TfMNGhRlP!C0CK{vD*$ zV6l^&zn|iZ`uaTjg}vUNe<>xk&dhBgKTK@r=ZL%qA*IGRqom2s?fhTa!owL6P8;Ki ziDcZ6T4H1@|1O5LbGM+>no{loOI=Wr{lDP)*+HjvdQHlcJ?)+Zc)#6Z&hcCcu6&+Ce?(xLp9X6no_$}sdi8; j|AzcU&}^xtPP&3>Ff}z%Bdwy9w1SpXJvFd%1!v2jT`({0 literal 0 HcmV?d00001 diff --git a/test.exe b/test.exe index 218959c44d87e24559deef90d2c1e9b427f5cf06..78e4ac3298fcc36b279628ea872371fd48d53ce2 100755 GIT binary patch literal 49370 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 J`)jjO{{@0O{S^QJ delta 26308 zcmW)mcRbbq_rUMI*Io8r*G{(Vk*y@MiL9h#$Gyn9xRL9kTfXf@QW}b~Z?du*NRmrt zy4OWkmyG-VeICE_$Ln#<>+jd&b&Z4T#|GznAwJiuKz?vTtSL?(tOns7fD&LD@OVc%n`#j|NgYs{ys(6V%5^)dW6;k~ z3;?r+Ie1flxdDy&AUvx=l@9oM`1n$mh*V&V0RvI{_4)w(Vb)hwYG*NXoc5LmAanbO zP<9Fg$ZaG2>v0?d1E8Xy&yDV&!j+-Iel_Oj>o%!m;5wb!Lmj0$ZjDfVMun3^t~aXe zQg^9qnEHtlc>s2k&ZtB-EoWnBhgX^*AkhH=b!GB~5ud=80Am#)6{FWC$VCg%8`Z{} zu?u;Zwu+MS)_VXv^Ipe^-XMNGj zL*&B~LL7cU(=CRCh5zvV$wS2*uk@v(4k_K5`MstRdT5V=Brv3maZDBZSuv*naOf$~ zKkD4##;g|5jfN9$TIPavDk}^D(8ie0xQ#hrD1X=TzE;z)M0e+eh0#6QR2^VI9U$o` zwvHbJ6$gz2ZZvok0i;DBVkR131XB#TLBUPaTxIV{Z(~-1Zm%`g`sV1{EB;J9;DY~5 zF`afLh2}aKlc2|a$8T|su5nDzR%h9f3t8W$1}zQDv$R&~4^6|Fiz2hpkcBs!1FP$a zhKEvA<>_$~1WG1%2A&~Re3+FbJf*X32?cc|+v0(tIc?x67F@(W#bhYwlDA`4Z#N$5 zSB_Dm4%I8q=T9z_l&>l?P@rPp+sg9R0CJzgBc!_lRrc2}HEtxe$(>myLf%d_LUC{O zeJoF$O1-?KHOrLuR2C*@7SY*(fE1m{N0iMo=dmyCJ96F(9HKk^V%^!4@1vB6-s6v9 zTzsF)P6b*g7dcn1S^OX?p&nYSXstFn&nYp>(H8rxA4>F+wv2{OQ)?jn!u*Jm^rAuR zy4{Z|C4*)_Y2ZS|fNIsYP#lrVhFk*f-BgMhq}vQ{mtar}tAf8I@|Y?7VvRA{ZuNZX zU$~SHFzhGY#ySUBgZYS3jIgpu9m-DIkM(ZQ{K{)TIvprFOWp|%@(*;G8~}li1D+9Q ziJ${9DS*1A${9Y89kD9m>ZnTCGiC~e6#L+KI7h}qQQqyGeQdzH^Gyk=&EgKRKQ|IU zo(=EA!inY=AJ~Tvn(1g0J;UN0LgN#e$D;(|8j|&6}1Ab-$FP$S?6@&!4?#)SJ+1rVdoswRQlm6t&${Fxw^5zw+T z=$LG5Ht5KxonPIPs@KtzAe)ghyC5r&IVi#Z!e~4>sxGqXd_>f_vq?75ryFkQfGV_o z_CT5-4Ui&60JJ9z5(M#sP%ZX&H+S(~FK@`pZ8?OSn@B6>4GP$64goD4oNs;=y0EpA z@5sZDsqNUTmHb}jN`Zg{FikvVF+&P({GQ48ehv+uTK`8d=|M7&HHuibij*br(Zs&S zllh8MV7bFYan#{Kbm}A;kb5a47r_5fCpoHml+gSXSfMWY`61<{F9z-h1o)ry`%+Bk zL5%2*`oBFR<;q_IpKa{P#-O(ME3=5Y%4FtU-FZpt_fkU(Lqj)Rs2fD3xYEqXHY&2~ zXg#Xj31CM8>}YUfdkSA3f~9su><$@@@Pf22>GerW3LiRW-nXJ!027$ZM`kdXIPj#j z>O!h8S2Z7&c>ZPdcG3-COkSZe!5lI@xk}_2HJ-&31no@Wb%BD*Oc40h-b_~J9@58R zDGV5sz&ctoK3TpA-s7^50Lr^NW+bueFBo&A!twin{Lkm(Sq9*C<1ayE5Jin5eUDgU z5m~~6tS}-iZ1xkbTKFdyQMiyWJ$L2i+zX@URk;LqWT8xwnxs~>yyD6W_X*wKC%^l& z>Ur@(6M8LDlRsE9^>(Y}@^)Wj#kyBXP|&v}YX{!}cQr#Pnt|UnzUXXF|HV>!W0`vjzmV9Ag$%QCXFs3-M1>GnZK$0h+yO06W;(lO3 zF&FsC&@SGFr~jeWFGg!>N(-i!5Bm%Ut<*WJwjR=P~KK~QJH9GQR-(yalXA>(0*aIvG*%?Fyy zx*gxOKQd=H3_%T~_*Vws>Q+>?)0-g~{w=lq+-Wj5Nz#&BhidZt3Q7jL+KqG&oyU-X zu2%GVa)t$%0l6uCS*7_BQadTcH0`|1CH%Uh(E0V{^|BI|M5+I(m?WRVY}lirHwRa* zXSdH$V>TD0PYidUhY|rMQHHXMN}@rrjIJc^=7p`fDo@l^*vpM5!O@6v%}Z~jJBm(| zwYLaSo2nnubVZ}2aidl1Al8+SvWB;J zYNQy|>*_0~eCf#@C+(gwd5uW+)AHgolo@AfbG4+<9}Ike(V>en>zCKVjc9=1#p7bb z>n8hB)~@0gkJik*;CbDepL@bgk9&!Rk~z&%SUm8j^sE~8m84NLt@9UNvowVdohllui0Trs7*GC+K(3(?4^XaXs`IGaW;W|A5Gi1JAy zpAdCYEJ-#nLipU*V`H68j5bzRv!qjF#o;!F_|#GXQh7CB62dT`$;Fz}@CzotI7;#l zjf@i!$BM?thcdu>a>QV)3jq~bFmt_5x076j-6cI)ojWJ67rNJ=HpO z6Fy#KdE=*=q$C5CUfi)P8Lf_dCci(fO5?B6^Z2O2Uv*qw&8%K7O{C2$z>--l;njrb zuwzTm2PeJ82@UEs5*c0{_dQi_cuh&p%QA#Qo?W~wp-_V7#z`>HWG^A{Rtb8DR}hPi zfL4n=yR9eg(T%h|-Wigc9pA|MBtDqS%Jn$h0&F#oJ^Bf(w1=A!&qx;X@PZS65f1c@Y;o%nJ7 zc3|aD^87(d#53){)G|L2;~)Ma$xd)FMrSSfYtHngSUxYvA7OhDOK_^IxR!2P;xXf@ zBL+;6n)f!gH?xFjP7AR|Vm(Swz<)U(3nL~V}>N-*BD@(c5o6uvHv+u~P8D84G z%X*1Yl+K3o-)omeX|8f1N2c;A03_jAzcIY|GZ@si8yv@;NCtl7tw{ECVy}k5MSHqx zB)+_On{!tIvjwK?K#=Jy5QPW*0Rl(C9@r{k$(f@Q0-JD>WQh78;=vYF)UN)$EMnQ{ z7l=Z@JAOBr6FIkKXNXC>AmQGM??%cn_!(f+J`q2fGn)aYxu> zj&Q>N+{lnD-$}T$$o2SXjvDy;g_uif=*Hv<7eE zg>c`-^WZxv!OCg%#ZzdFtJy+k5)jKb$y3};@Hj~qW<)aj-E(SiXWAw+`AFmCAJUhCfVSGRMVWN*4UH|*a8aua%XkAwT3e^NuF6|4?XWs{oNF9-k5g3l zr}jECH{Bj7agSw@oed({g%OZ_`}@{z1YR={WjfI_iE*P&%C4|-TC8XU@g^``=Hj3X zD@RKA@JhVP#D`Il2eXa~V^)J#?)Mo9GC%u&Og82hWE5&{Ex~`- z%8pv%W|R3!2ESK|!HvJOue^dQ3CpapxB_*i_%r8B2L$-r1^UPgNXlCQexW)fUdr*| zJ;z}wALUOWBj#3ThgXJtMpQbA1g1WsQHQ(j zi)S4)7H`?rTUt4xOQ$zFP*?lL4hwKm-+?Yi0V^YZ9f^rXc#pOw01PB>SsVQHHgB4p zze;D@jV0D}6j?*KO*8x(x8lEhUzS4el9nYsW2{Y{mC2842=e9s)W+a*;ctUV`GVgm z2Lk-4Z156>zs+#;^>ozCEvb6ydW!ZucdK z*>&KvK^L9zDvykPPeetV;@hev2TYXk*4ff4ZFuskPe zN%bgfANZQSG{!LAapDAF0{XVfVB(0P=~B}XRh*4-Y@E;7lFBda(aSN;5dzv@D>hm z#G2{ggS!N*_3AF>r~3r8oyPt0@x>`}K+i$ns*c`elS$0+FzFTh8A|5%`B0CO;NCGz zPz^>;={>cof+gK<6Q0#}Ho~j%B;p)lyx=q3Iw$l?R41E~C7b3tt9LQ8!;`WI!6`o* z{a^f`dxY9p!m^5ZTmEXnXK7Zt{ZQtS!iDWaCHU<6FE)6^$v=WThQVx+lFc$X|5D{r zoGUA9i34m9nbgQ;?l(GL;85P_CvzH6F9hP+tVV|R53=Mf6#=(L zfdWrur_dqp$fn0=y211F;z_J$W$3HmwscTd82bvk1axN8WWMjm@Hupe>|w%?k-H^K zUtNwEDNrSI5S=>#RS_;8A(IboTgLHjyx$hnUC`)yQ-fwA__^AO@bhJ-4lW33ae?H6 zA{}^da~fJOr%S4>C+QjA(_`2uhX7Lj&x0yi)IC__2mA=#+R_gUap@>%1GHfY9nPs>Nu ztix4;`E>>uAw#B_JP9FP5zyrex$*0IyWETv#Zeu2g*t!4!N|};{MN^UNNwfTTg|Yr zw8l2@ob*$5*0|T_(^U&2g0t=@$#)Vj`B@YcO2zO}DBe~J?h`ybpDRt6$T7sjdm%PV>W2j@+pNSmLrqG>-iFk%jUi8y4)z1UKVf} zp>Xjs0;^kW9Typ3`(Te1jG!O=)v=y?eD&V?KO2N9{)tz6AjdGJr`&DGHb{4%{cXMy z_xx`n`JRFq=enyBdRe3neo)Cx@!+e#cy%TNXAL+u3g>dKdo^O7@9X4O>|tS3MZ?K6 zq;;<8Kmt=x%KF@e3-FUOm0fFwl7Oullr?f4e%X+g15eq79sSBYB4nVRceT2D(;kLozyr7XQv14~x%V7Vrl{IZw8BPxJu zSngH>ET$b8jC-pnDT2dE7KFa9>_2khGR%*?N`}!NU@gIXfqY|nZCL*QR4J2>00JdK zjytM!>@@}LLRagCn!f5BqT1cvOU;98!0m!x!O6a8)33Z_1Zm#1J*jw^Tst6c z_>+})pxyb7$ZH2hR}EaYtQ8uZFMa(^y!Ktub+;2Uc?H;CSN%=F98beBx=K?2`*gieP6Bgs3>6WoeH6o%+Ck-leK2ohKrKkCEOMNTR4~)WPH+JcyP8T^WFD{ z3gL&^_P2(dDF0wWdjKB%o}om`Y-+Z8m7WZ*uN+SEuHQs)Q-P&ZxKz+??|a6#gOe)t zhcZD7^go%O*eqwivrT6dC0;JbAV8|PQGIW(HFh_T;x32d1eSnHu}kE*;vmT8*A?H8 z0(r#mHSXoxp!&;3q64f&VPaG;2p_v!>}xGKvOLI?IikQVCGlaqiwuRWGVs>2_TE);yrqUHHSk#&GP*Rv*P$ z`1-D4EY{=UTu}AS{12%ame=)@&f{kA<**ds&P-!SQ2dQh;QPK+gatN61Oi-I99u^x z{b!*I#m)e*0rL-uG8!L7<=kFa`E8AvBZ?lp%SG)*A!Sm@M2P$p%)fD6EwRV9RR-%x z3=Nx&BAifp3!IIPOI84F{Q$O@lpi2yCuM&KMEfDvG-dar0Dm6_$bX%KejO-r`*jV| zwz4&Q72(~Y0`2u1hYby^%J=@fa4+K$|9GnIa2 zZx>LLADF5|d?ezh^PHzeih1}`7Ps^|@C@mWNB(UiUmu0jKH00Tc(M9>d)U3bMlQ?) zce#-1!=qigF5RHxuMN5>eIgzRk0tnq62sznUgm5?RmG#6(MfS65eG z`yhx+aP>ZZoDd_ESg#R#gc+-Srat^=*cjwYnY}-DQXr00Z%2?|#`s=r09}j)&EUxB z-E^Rxq46J9@c6UlR#mBT;ytQ`yK=W+&<@csCNLDmF zgaWi_^qLPP;Bd-~A4uxK6wL;-2yOhw&>XlZ?iqs_XnjL_99pzdTXs^1qA^yxbL^8s z;gs>0)@*6E3jpXZ?^P2vUd6pyIy!QYk8$>s;wAD@D&&gLr+lRnfzLF`TTzAhXRz|-7l^8puP?QZ z9$NOMEioHuGH;3ax&T=~-pTNZbk83tx*MlxT)E<~d&D~Ji9_oWc;mGnaoe0W*60^^ z^xX?7&w%E_{V&B+&6m~dr7iz8NXYyDrLFJ1)JZ4p()K@V^gGpBzY>v~p{X}r4kly# zPP>cU%b&VN#JQD<746ijbcuaGDq-Ws2yNz1Qe)!C!&H+(G({53(}OSzZ$VgjiHkQ8lamNxHnQ!n7(|9V?&;om^L) z>~qMG)sj!r>SO_#yY&;}@LOEUIA{Qgk$Ws+!IG77YR8Bg@bjZeqV!o#Q3~z1JU4`g$(uOp$`}R}&6QqKVn2#l6yEQs*)CoM7je0(SY-N^Q?jP{3 z@VN@mR-jDbz63#r!@h4mb~6uqVm^%|ZCyCu_?lsSHSNVz`TOC2bjB=>zqsdx zh~`x%%(8l6&p26fw2Tfj1-cVdNC@-8#j~&kS>=GRYd=omu77Wp25-~E{x=O1T+e*p znN3FglmMN|{v)6Y=X`S;`^UO*U8(sAA|yyh?6e4n%1HTx1rJ$Im?i79jFn=@1#h$*kyM!c>+YZGR9qx-Ubw zI3i_4^T=D^QFZ_l+*0Khm*~WRY0I-*TDL(F7qzZSxnjOBbQow!)e0|egleRovde2^ z9Bl7482#d=f#4u0o?VNKuY;y$=d|@HJye$*9OI048Ngz`eLt!~i;3*NI_v{9m$b`@ zkkv&VdUS$Qo>6nSEb*c=y*}+b5RqP3{~1Go%jpop(~dJCGU}&Id=#8J$iF9>oRgPo z8E9KwX<#c=tF}%$RjvNdlO0fx0js5M>tr=wP?a*ap-WF4DN^m9JwQG*a_;Tj>aDaO zr&SB#)Ff8!)>ZIQ+?I$+*~zH!lWV4AOJK`!47IA4BWr}|mMK4ATt#-B&@&v z@{%`|BDzJRxDKvXBcaPG=TLVVP?exPN+udi!kYIc*=FQ!Oh|q=6tv82Wpb;@OUS49 zdbnXK;#}GhNbzotq%ik_ePt%=8JBLCeiVJD%5I5E?JS|Upg0UH*Evm;tl%3UiberB z6PuFs^cchcfZqh8^tpcw0vbr=O5Rbdn68WC&g24Z8Iw*HfRrR3h%?Bpp%AOFEwQpR z>mfb#XosckG%-qbwpqmL4BBD+WuS@dovvdN^JLA|+lV{QPE4IleZ zbL3m=O5sz=>VpgP0OaoE5!B!*iA0S@&UnTsbNukBwRA{%WPUmb%QQT^Wx%^&GV zuefZ_GQ1&Nj5?cjc3ZXJp`yydP`=EAn7K`bQ{TA4mGFU`M|q3_+%&cMhisR<@xSc? znSx@2od~!g9wRL4xMucjv*v`TmJYAhupbqFsnbxws^V+?XdQL_Z~I8!bMy+An=Z~D zX+2XeVU6(@A){QkwmF^NDm=%fj;#xGl%KQo25qhEP`k~gbW0mhx=xxuh|Gb)3A})S z|Gwfy+CS@$z~a|G+#gv$yTI24Xg6i}nDHOvPs(@Di1~Mhg?T64s}>PXrnCQgeQm@^?>xwjLA z>@MU>erNC!FL+XSEVCa*-Nn|9b?x>pHET5*Q^sFJ$hK&+=%&WGG`@ae1WB_MZu-MEAP?Ig!1XWw90nTLq|k(?;`6 z$qVloP+w+&lIz6>;9SWUB$M(7oCS99M@!+Q2^Y@+3- zb^}0)JT@lt7A1CPn95r|_}3Cut%sd?#D9KM>h5-{+n~mdu-p{)bD!)5<`hxT ztc|K#8sg(GEL3;NdCki4<*Y^Wm~YnT?b|DHAi>}+&g`N^f^V0wdT-h(i%>qYTn@*h zI!Q*aO(}Fhtg@2qq{|Khjam>zD|hu&)V;p5lqGniqnuC+jfxjXT_-IZpcvdv12_oD zd2YIQi~*LcF$-VA!Uto1AC8+RnpyC|63Z-3liGSbVR`|lhLf$VIXy1vw1`O&hMf3ixm4QF|AOGs=mnVXUzOUvS zopRgbLl)Q^Y7(u^+A9}RuNMLHm|Q7H1iC_*gt9)QG!>uq(fOO_@xlMG(FDUMRgSRi zoz-pDw%p9OSe*}O*g$l~Ns;&~!gg7k`or6-;MMXvc)I}ggVb6cIV@cC5aRfuLC2IX z-RDy=vSAt>sP0$4LZxyZ*nqdwI*RI-RH;a5n8eKVuRom~MLp&3L8DnFn)V%e%{aFn zM*6m3Sh;875GoI1-hukp0%k*jDLpVzs!{QrnOG-QKyrpCBv#MJlHdNtYg9P3HILP5 zV~uNbmM(qUjF2O@SB;0hy^cU39ix4J;?#@2&g3c(baFo8LbS)D z6d}p3!p|$W_aE&LgBdVB+{LaHILcBts1x}ulTJi*k!8kTb5tsGc3MQ?G(cl$;v$rU zv*wHz!SJJ9{O?Q~Ve|vop*LD?lJziNMpd(H#~$vA!BTNB9Ffr|4DDSbI~2(N zpA>nRI3oOZ*h^mOj0{K7{KJ@W(4OPf&07MB|C=l<+|@O+E*W{C#CjqccRWYnT7+@C z;4F2S?)PUWL)eGb;^Nzl{27^b4s0z|<2L=a<=JL|ys@Azz^V(0aQp1&)WNBIn+l-yZ}tDBoMKc2+X0zNf5y_wOUTa zYG#Sf$VVJ9wtbtTva4lWzSIQzTen1TR*08|L2OgGG`Q~g+Pt#m!Gp^Oia@9v6NTn% zJxUw@T+)BrI$~+8m_U)*4?`=dDs4G(&wp=|aB(tS7Wr^{op~e}lwJX&m?!9w3vVT5 z9u!9^opYkSK!&JD9A>kQRgu{1wL9sdcT@gyK9uVSz=+3@2Tfx-Us&4AF1S0EO6Lu= z?pc1~;23*hk9N9g$i%cf`D7RpYNqtehj7@6?E~ye;;$mFa>Aa`mMl4?X{r~~I@)qx zWOuX(uuXtT1fd5GYfRDtE|9sp-g?wCHQlh3!79339JW1|4V7$RzfZ*$L7DH+cC z4aDAKVSxm4M^D|;-yT8{W54z^Xjc~}963FvjuMM0oMu?xJL(t2qx#EOtb)wB--Mbn zuNdJwi(6+ucc)5Y{SC5%C}uY_mN>r-i%`1MD8EG%)>)#z=}3N(E9TZAt&K5BdWI`| z0d(TJimvA&>#?zRDg)H6y7WiUC<7IIyxRQ8hF38lqu73|<*0#|K=yqf+ z@ZxLTx|}6vL1>G6NT2f6+tT#2GLyQgpd%+bH!*kx*cB)(h?o9J`ZK@v*o#4M?xRTW zL2?(Y%3d~iAqcTIM*Zjd=a)dTzXW(VZ3hIB(663=w5I|;h{sB8N8v1bPN{XHgbSr*&bM-2MH z$u}z=2S;PEgr=r;2vA4r&>U(_VK^v~nf+iS`t+jsVActLk9Ltfq#j0__?BM+*_-#W z<1cSc%HXE--{0V>S4@ii>|IGtAxKZ>?>r$9dwOnu;3V#YBXu-I)^SkS;OCO%&^sw$ zT18-oRvh$_?)|)`S!*Qfn?u9>`Ig#62(4a!-t z8=H%80DHu)Ar05~8HRXb5Bx5sy|G6r%7p=jd=#U5r^wx!_$Y zbx`c{Dw#7RkY;UgRt(8*cv!`^7r% zeolz9v!rV^_uqQl+>yZSIU39>pf@Pc~jt6ubp)o0={7wfRj+3fGx+&gs+Mi35<8^2Rgvc(RmZeO;%RI*YpV zR-^PH%bch8xLWCi=@nV(>awFyyj^VQ0R+8mfEY8Ioz3L|fHc%yjTZZz4~ca)^bDXl zTe}cFAG_zS$;rhD;0co7$`o6UBm5B(-=`HBOTK^T0=qO%4~;uV)b3;S9tt92N`cr|6q%kRx@*hMFb z6=X4lD4nYa&Z=3RMncSipDsb1^*`CX;r}S`o2|MTNr`jG7qhatvr1z6FNKY=D(1ONtyq1Nq%KVk%J`ViN9k z8ag6ABIWf#5XBV%f043LdqnQ}@p3-_kwnpJ?vRBI^$$sME~QgxuB$~p9W1emZV%-_ zls^+i4ys&dL0=U&F7h8A%waCE&d0YwYnlJvdr{gUaFt`+p&4Z!bQ;`#HYao2#x`r_ zy-;tn0e;*BgZKjKIIeOhHxuz8bJOCuiTM1iepeGh4Y=-=7YD6HuW|Y`E(buIO?eXuKScIcA+yNqP z@SmlaYT5QEY`-$939=SZTH}I(10AzAHJL3XQyHZ_mF_3??CFu3FSjHFyhQzfLRuBs zQ%uk$W&p&zT<3y?qFBIq(s}jeq@*2q$KH3YBFTB7ZAI#@lA4a?l;2iqTBMv&9vS-M zyR0_;2^cu1z-fK!#c5h$KLu%eJoz9L$?^_saCwENCURebeEhV4te-s2rXEwd%E)Qt z!Mg@xC{5#_pnZ_|kf@lPI@dZ@wC?An3j#u|On&&f_6Z0x6!;qWSy!Z-hY#Tz{1$wf zo|J;L;43z%1}>N;20xj~X8(*Kf6!T0%}2s(@eVE~+ncI|!H`=Aas#7HNsZ3H6NxaC zMeV6A0>81=WyRVdCAH`o)htW6!EH3ys8I(N>3G|4_3Yj~lgOcc%iXIgdEtTT`dt=c9irns} zj`g^t9>C!TK)D~b3ws$5Z0=#DNqSkVnpI)W*oA)i2EOV^36nNFN9MOmL-nA1JbOao z{Yzs*9}ZeY!2@2=vrHafleFsEQcuwzXYif~&`$3I1&~{hNZ8nw@uJb z@>S`Di+&Wo%@bW35FVt>*ggLzX1oena`Rb%mLu+0yca=`%NiI+ND@X5ta>P~*b5=D z2vdEy(Z`estH(Ov59El#ROi0G@{iMc0Qpf?9HGj6=#oDolQ8D<{*=)sipp>Hy65$? zu6Xf^OVodFsy5uee-Zdr8VOPt{A^drC+l9`zgu}5w$b9w zWVvm_V*VeVN>i^iB(ak0I%jRR zA}sk{TfWD8-kef+D#K@6mVs;-_oA(3j5X9q3l^2#EtS^pyVPA~bME%#x8ucB@#x{p zr8k-vZY+vVSL;?`{IVeGMxiPpCTA=Sh^MMSomxu_G9Gl?fd*vgzIgR5dNNf4`$blM z92D|tYwsYvzO%)TP`i6T3x4DIfMD=))?wF5w1DAvF;BqlBM0H@(MQ$E; zXx=C?EfDe7bSTNa#e&i;@Typ3z=f*5+Y2~gEtTREPU-;Q&s6bZqapGXz)wwwMA<~f z*h3<3oVgZxO69xIzj}!vGdJE}Qp$1VqXE7mKD0efrRiW2LQweSHVHXTtqX(9lLOIU)^71 z>rbE6R!?Bfli!P=%#WbJFn`#B5c&%mjXvC!`(T(|YNRP5r}GoiU~~Z#cL+jGewes` ze|1Yg`XWAtVBMC4_=dL3jOg}z-J(uTbF0U3wi|M6^*=f|`gf?TWmwg;=b6C4w4NH6YzTkg>0F>iy%i)- zjuWf<%8HfA2AJ3+!Ifh7{9W?}NhZX9IsFa6E2<)y{Pj2Oln|9dwotyt%NGn7`8TSB zT-4RripqTbh^O_WVYgNl3QGD-;fM>35p$esr379#Hk~tWC&asAh})&bqSRU}Sq>z2 zANI^GueWp?=k2BlSz>yneD474O}Aj`+oB#?ziK6-RqWGXuz_hFYW#fh?y%Lr-O%+f5_O^i13=fddl7p&ATLCc z2X58K1A&N`)Y`MQ-83*Ew{NS^Nw!fEvfM9vZBfS-=8o=i8mLBQ0VZxf$yu&$x^zvkLV=;zV|I}tlEX3e!x?o1Y`t>k9fo=$C_|q# zBWP!FKvIygPFk(~Pp-qeWb421=J^7BdWs#q_|qFZvcM_|N|}X-tzm`n0Hzcf`g@|M zuF=P;b5A~2UsdDH^LH|DL16OM&}l)Cag_p{t878-!063fIRVZ3yiNGeCX?Ye?d;>T z`l0wzHVXU{+zfdsu%y)Wp3Y1tyF=uKp{)~9WYSne@~%~a{zwWV9NtF%3wtksjxE*7lMJuo@s+%yKYfRC2Qm|P?OWxwJfKcnGu zm&T2+rzfIJPTXu7=7Ckte}cPEfDs*p8)`c%`N3~5n$e;o?^#m2T9?T5IMENrK^lJs z=WuZI@KO!6vXl`8;H2b>&ATb2r~H-07Br8`HG5KO)1djEUfZu3E6ud6X*Id+_!iWDWW->yz%?c#?flUvEj54Jh(A(BjoiNKLm7rbSKk&7h68Q(QuGJ7wEpd zdtXn!2MGd6T#K)a8AsMETQ|b^0aKc@5vmC|Eo-tGpnmQN_&_8ACpO6t2nf|^&Na_! z<*RY>6q%dm<)SsI{LO4{KsCOuw@X*C>{xuQ6=7lv5;Sn=LaTg`!uOowGLPn^{6Up) z+bW~$aS(3^d1z&Ls9!q=D>x#c_(l4eJbmsqXZ`LfwLMgCS&yrR@gq4}e(1Hkk@P@{ z&M4ICQEPvHuK>oF_B8N0Xfg&WIm0rNk&MhdT<@MN;_dwHzqOl=|8V`_nYCA`l60)J zwZ3ICj4nQQ;MjqTJ`#a~b+a4&c5Cz*Rv;oaa)o0<#=WQpnMmtLqR&VmUa`fWTO>Ua zF*}`SSF`q`nc8Z;l9I?rtEf8SzML$=jrwb8bS(1|I|H~vxb!=++Cx)O{P6e>O{9eICRkkYIIu;7{~XXN$#M zy11MJY~nYX2og<8vMRhRA%59IR84~mPOqHwcd8x8 zZP$xOj>o{O-ZnPp3sztI5CXPnM8Vxd%~n|_dke{}$DXz*h>N^d5{o=-6HsG#!i_vQ zBIcEI63eo_(GQXi>{`D>=f$sr&fQm}jJOT@E#!ZjI?xxh+X*@gMps+flwMW{hB@VE zTrVvfDmjpMj{9|0sY+rD*ME8U|1A9ht>MEO^MtnT#%{JYa(5Pa9mj0QhJ!y#&4r zs|HF1Qg|>}mql0L-h|+AWk98TG-BK^Z@jW`5zXS!YWiZ3usrzuoD5OQNKQv{MiBx}q?j zNACx2L_1FjQ-Q_-AnS()trsHb1|#^?vs|G0_~ z3tIBrQO=_1z)yi*hHlA^!oH?1J@!quF>^jk);~vE;xn#5UZ@Xxp z{J~bxeiKceQvQowYb)4U###DyaOB-t^5LS05??zh0ed9)`Gdj0mvfeLKxsq|v?SZk zlUyWqx@a*9usD;bY2lWr0a!RB9<;C{s@n{W*dM|*-&0(!&PNsqAB~4Da3yke#F0%t|ZT!SB??H+2z$Av!$Hw(5A+;VPzlM zKaU=0*hXaV+S#rxiY6TEd}pvyHl&OE#{qKUn3Y;vyt1T>@I;&{z-K$w#x;RFIae=o z>-^%wXroW)%N^BHr>}5y!UL0TpThKKG5jkDj&%i~{A!HBJ!$y))R@%RER~kFbr9qb z6OCL2MeM8VWDV-ZZ=-0Zz^CJH+aVWiSq-&V9}P3=fcqWD)5TBCpI*n@)cQl#aAguL zd^L`U8bKPxE=lLy$yn(^xgb|hqcl7+*Vz`lN>t3r6yPWO7CQ=ny8-FfIE5U{)>L2~ zC3ot1hcqu&!pQKDx+s^AM|0@2IZR+r?)PbU9zQvxkwyzre=Pn`gZ*~DCplO?gpwX@ z3hS1>N)RqD(u8E7kz%VX^6w@(=&r`p%0Uf`k{Z7r>5_s@i1h2=dQte2AHS-X!{JW$ z0i$rQ3CJikE<7>NV*6}DSn?SgCCs8PUyt@ROn>kv2*QW|Rwwo&G_dMl#j72Qb2+RJ zQ`_v<7T$r#)oE7SZn?WC;xs-Pf19rn!8V#w*#xr}o`DfwT35f4H6`PdJpSx`A;J+j zTcH*hwyITQiX)V_vXVV&$0TpZ#{*axYE!FmMD)C#o){e7*|5uA2!N4a=>o{w`T`1bHnUtI$zu1jTsalbNSHc93;g9NVPX$7*k_+}$-uI(z`~6$d$*|7xzqG5yOv~u} zMJLl4^^Ai1d$(!vheiZ=Qf&H+fcNFY=hg(Hjirl+H)54}F`v^lf2e80t3wvGNpBzP zhV3%2SlVslb)EyDDMu73eeJ8V0Y$%aEQRJ~{c0qkiia~_b}Tk<&UmS>M&c2&X@gH1$R z%ckyitL{~N1S0FKJ9|N3va8Ut5tI3qyzB}4qm?d}kkCr4P4wj#DN90qT29;+lz|2* z-C);B)j849z_|cJ>Fr(Tu~uUULEX4YwJh zmy?9Y5Q;Z);Uhi8%G7%eO;=#h=@j|}dU$Yzl%sl&#L!z7r1vcpwh!xlQ-BObz!*pr z1x>{;*sv6KDhGp;i^5ICF?e_>d{jJxpFk0y3NnO*DI!!+hL|`-f=XmaN>QW}WO|qK z-DR$?!QRTVH!Hvt0g4h;nW3UeQKPCeG&Ctks9Fqd9f~ehkD+fsF{BzXjE_=|QI9iB zNEB158N=LyLZ(_WPMoBiqFOOdTT^VPXBf726nm-z!_kT2Om$(nQYdazcg9%{iYL{J z;q625rTQ`asgwX}AmiM5N)R=e5fVxXqlPmgE>M6-Y7`?nhC-vpGU6^$;;EMy35k>> zD!@oip`=pN7?;y28PrThRyHMvN@wKeQSzx*7zKrttJEUKwd)iH^#)JDeBCQ384h0*$q(gsl5 z8P8u(I;fqDu5L;XwU^QNlJbh$&lnh_yrvE@-n^x}qYg7hMk!;|amK`Z$|UszV``f6 zkvhZpG)wtR{lb`=rz}vvGQNGMEK+|km`jvp>I!3Zjj~St$=LWs`AywqZ2h6IsN0O4 zUCJJHpYivAa!3VPvQh97L14B-T+WBBl=_S-3=@$?stP_jjr3tIm1U6Q30bJj#tGR5 zOi%4sCkc}eR9zO*%TpV_5$~+A=e3`j<_z#wZPMpa2c8#1uWDy+ z@({S^1Tl1VovMCLdX9t9YK*mQW;YV)-#1fsxuQ!>==k^Y=h=-wzcwU50>-mBL+6s} z2n!pXSG_`#VK7%7-ti@HmizdtHtM!WD-R#<9i2mPHtr#6jD*2@h|pPt|NAh}_KF(v z;cP_~a;K%jU@62R0Mj!wGuT|-zJ_)HGjLhW-2E@*CJoD;HNC47P){<^05PTyOa$Mz ze=+Evh~y3rNdnG33r9c)OhWA+-xW4G_DLkl%8=M}PCz8K3tdq7&kkeaINwl&CneYY z2SmF(aXsEFgOD0L0c|L#AP{y|*0Og@-X4{HVp7c0qBOXa^7V>$m!c-REGJZg@D%Q5 zr9G785SG!N!oDXs({hI{?)3cB%s&Ti3xqAj;tMD4rz4Q{m%e!JY@ClNea(DwiNvpw z7j8=zP3wL|C>55i2|@hcWTlR<1&7r6nRC!q2*_GC3v3>K!~E^@XYQ}EaWOXS_nc#4 zE7MI5jMn%N2wtq!3&)-ct(dx)@nnsG2o2?M@2bfdL4Qw1kN)aO>w%N+?i=((A%#LI zcHwJn0BFD*iBzc;yEL6GAnGli#tK<<+IB<9Hfav4i9murjA%Z-rnRHkvohxJ?z=5c zU^bbJ5YrNU7?Xu9V6)(?KQv)?Np1s0SEY_^AI>Vn#am>I;Ig-HZf>ylqB0cE24%3- z`sj}CWDh6L8m&XIE=(!U^7DhK*#97w3FJcnKfKgp2X4|Dv9g>` zZ(~Tu4K||gt>iC7q>Ac}C=XhQk_C!3nOl&MTF4j_Kj z#Qj5e)>Bzlt%Qe(JGr>WGv)n)2L%o(wM!|fhnU0a<_B4n*l2VLrtvOwr&R&%?tkLa zQ)99+Rr-iK-^$~U_)<(;B3!C(lV^^9BB?1RE2L7KR6XNnZv`eFD@MR0kJcJH0f_&& zR#3*ERHWj6e69JYv8-|NXPH%iayD4{2+k5XZgVULgY zW@W%u3|y(4mxWsMW-pJp4LxEX<#hLSExkYxev(&Hg}<`jorQ1?{^tnXU1lACS;jm& zRu5~57BBLpVGwNn>um+wSAKc4OpD0cmd_dkJGtXoqSYR#r8! z1Ir#yktdm5H*yutbs9)J)-s7OiZH9S&AG>J?cG&&3p$`&>%d)5dks-~T>6RdP}eIH z8{5Z>je)d1ET>~aE${u6?k974@V}xfLwJ?^FP1l6LIZTO2w=_ayCW;f<0|!dNM@xl zsN!QR6pKKR-e;kSUVwgDjZOfvX9}@q`l)8RfhHc-Tu@ANz%)XFz#F^CU+woQ10;Nw z-tWLAzxCSN)aZG>BKJIoI4wNM)z5{5RCBoeRR}KT!iR2rOMAo}TGgCW*|h$gr-r_# z+owhs2A<05IJ z?X|aT&zxn}Wk|I(#&mtWq`YVj8|!$mE%dGxp&Q&Ux!kR?rz$q2Svp9v+9;`7c}BYW z?<4$NVCfU#SRTZlnEH07J0)r7EHNg~4575>Wt9Rb5;$AJMKRFmm%)BNY1vPGd0zNt zC;iPb7YOyHm(q^Kbgig}7g=m7@t8<>aCaeP`ybp(UrEM$+&hx`^qL^eN1!Wbs$bLf z(L7oUr@M>9s60pYX;m+$1JO4B~j|lohT$+SQU(7J;;0z`?U8i@ifZw5Wi?x|QrRD~6H+!fyD@&YQ zDZQgbCl-a<1w-LQGj>Yws)gDjjJ-BMSNCpHj&FxBZ(yi@8FTp@zdlw^Sn=MNLD}5r z7yZoaL*3I#gM1X%3g)Ec_^DyWqG0`%AsaCIw#0|WdsvJJw-<9O5X}FAob+Ko3D2IJ z%>T?@^&FSu0>vp=W4+K!8PF`->>TL`RJQ4ollOV*)23(W@-d&H;L12b2f0 z5*q66n|O1sB^@E6OlO8Ij*q7tn%kWh+)mdA-08<`t=Uq7mAypFdwj`k(hp^(g74#p z?7j81HO*W6T%45n!+6w5NmFw19Xv*d(Q-yf@idu9PLuVdRsJvlK~K~JJ}#xtbM}HL zcG~t~=fvL9ufwHMj~|}ibr0>oB*_@dn2FMMjL3$gFHhl!8gGM>{Qmr`;K^EcgXv91 zDU5DZowV=|&qNd~&Bno(@@Mbns3|_^$8)=evFLZRAZ8zl3;p{I6@kP0A#H}NH^WA^ zEAT?60#A3~hBJX~#by({?Ii_8p$kT)_(1KBK1B~wvm@U5lAxlHrI9N>@I(hjQH#`U zgZICLP!tj~iogd(cl=dkBQ;0j<1Xzeifxu(!PD}468PqFzm(`UD4a#6^)aW1%8$+% z^hkjzK48d5!z24y7sD)%t>WJr^nenuh$Aw}{4hT3XvYA`kc}Ahm^tb|e zrl0GjkJ1AfkP}J{Q$#O4C8?Dz`8NMr6;KW8QEuk9K9^oD%p~~l<8770C5v2;(@S}NRg5A2=smthl?MZ7m*qrO@*3y6veq{ z2`esPlu52G?^XCflM>{eZPDoM;h1|WJmE7%FI^;#5Cvc!1Seo;_M?d4Dse6~GFiYg*O-}Cnm6e%dVzqS zY`-(gjk0x6$Q6ovT}DfdOWMI6zf9M);Jk7sNM34!=KkuVd)|)Hx|~2yu_?z% zhocqmKnQ(a{b-XM=shvMJFXN~+XS5V)yCXmuNplQn^RQcss@!QdgCe&)O0kn`lRu( z;O%xI#CgcOvL$Eln9|0yj-M~R;)sBq(~!%zFX#-ZW(ZlE4Q#(Xx}Ls6&el8G?Ol0{ zDSf*DhboDKEab|9mv5tPm6rWQ-@l3_S=#;Q_q(%Lz@!K|_^|lM0EbG-*}}_%?p$3E z8#Akd0{;l?H&yxVTap(62-Nt?t)edCfDQlB;DIDRd}zt;R>j;Mww6M2j3_Eb#GvD% zYbzh*rzI2kKL!x>v-J}Av;J#a4}3k84ZiPL&jWO<*8^?uCy__dM=Zp^o0SDs)_O9i zmMm2Ol9Oqx;8?wATwsaW`lQ*#GXD%4o%5RK^c^id_k#|(2gHyUa8n<)Z|0Dcp;&rV z`>AF6In3HO@@g+nBfQk6=*ES0?%_P84w(j(rgkS8*=ARi<(NQr$^v z@~N-M?GWeRz-b4J&XqRXkE5qu@QIu91CnYrxX$iyV4_h51rXYy5Q_e8K<62QR?}&1|(GVB=`O8-b&g8xX+kdHMIP8Jsg~6TMrnwcgeR4}d=>HpWc+yzcr(43wMA{;JT{p*c z0gxIoM??%_n*V%W8O5mw&CB=46nY z4)T}5oT(Z%FT?em-kPS9s_h*0+}M`Q8vcQuF1T&$SukI@D`*T_AR{lJq`O;WLsTM* zd?5&I6*ygxzIOM5^YUF@<}QN!QTsA2FgtEuc z4@C~Aeu<8*IMt~lwzt1(4obX2bc(gqq@z;_V17B)OfXiTbmlafE1rEv7h&VP81x&m z0;0LqzVQWQBzv!aDoaJqe=fTmP>Kp^F3XS)SYUVhq=j#V)40g~bAmBMryXDeq&J69 z-oYbmwN2H$=_3-p;<=|g34V*VJ688khPZFumkzyuAVGfx&-h)Z^P{;R{mogTE5BnP z=3Uz`|Lt-ysH%+jAN?y=7aw3N0&F|pY}5YQNi%|T&V;sc9kQm(ZZeA?8Vxtp2feH? zXEm2p0yvXBrZrWu?n$7xfEqy2bN7HJ(?i+)axnfLRrek7w8lbLh{{RlFHA(%y?a^C zr8^%}{N>JV(E>GD!b$?cJK2{v*DR`&`;O-bv`(yJm7EEosw{z9%;CaE!|q&J2Lj1^ zK&)OT;y4Zd3jGhwNjX%ji)>p|mp5Xfr7mrOHtz1mD-Cztpr?djz$5NxiU;p_YVnIV z$QP)*bl%XSXvQwGaKas)1sv(Oj+Buw&L4o;Sq z6r9C8TYN0a_SvxHXm-3IM@FmN3B|)o6wpNxHRo<0TBhcT=*idfaE>= zgynW}_DlY>Z821}3HVe4@hWGGC#4eBHkyCrmWScn*|Kxylytj`%IJmbAEax=8ajlW zLE8HCr3fLjXPDN*2be_TJ#9}tNJR5dB2T0o6bvdbb2pdh#&yRid48d<{nB~>3xB2s z&GJ)n2Ma7}w{Yuwiha?O7&iUphq#13m}~8RfeLpOBsdP3M+vW;ti5t)9>Yc*-r8%* zdfg^8UV7QiXU`m^l-&I88NWLuuE%i+Uzc&6$NFfMx$AgN9d+tqLC7T+XJ&vdd9dk5 zD)Wn?c*)8Ow(10}D-OtaS=Lu+76TO zT8I+V>_|DD42_)S`vGYZWeQi8PNIIZKDKlC=+?zlhzO#HQ+e5Ib>xj=t?C4K?Wp7- z`ki7jR-mbWdwnx~%(bfyww1HbXRGK!uKCFfJzfUP&6MuP`LY_pn*5hmPswu*j+7xy zO*7;pP+hgc3@R?4U+_&u_=tkDRm<#a6Jck z9?uyJ%L4ODrf+iY(xUiR;qYB(d!qq)*=M(V^^MSO;UoE7=)gUQS5#hs_tlWy2(LUO z9gy3b?F;qZy=ayP`K_8~sV`&1o~O(1v-@>3S42c^@2vLJT?xxQTDVW&jL}qNi!Wk5 zitgbwVf|lgn&WiPkLtab4j$c&w)NS|Txt_b5uWXK0*ay3k;&t5jdoL8@PQus?Z`hA zr^0CqZSs!OZaTWi?*K$Ey*b>Cj`2b014xB1d1cRqMV))z0lZVw>zanehpy=;o&P2; zcjnLK_uT)5ZX1A`Z!MiVpj{Yi7rdsBMga+sC^a4mgxJP0-F*{pW!nz%`Tet)dnWLH#zn{ zU{dzIAK`=|!TV}9$(t2UDugR~)mFO5s_s)XwX7-j76A#5Z3N;LDf zae1E<5K7VcgX!5?>9|m61)O3Zl`kP?!I2=!dwOv4z32d*12rMZ3N;dX#@WnKNe*%m zR{VrJilmvHg;akcvFmXG79)JT$R_Py7C9zq(c{AIvEsuJ_J!Z=P{bC@JnD}}z2+D( zc-07IKsiFUf2o!UC94NO>R)UaCgp*hnH=Pee-zf4`OE@X(&-IBuDox)8tSF+6t`}P z?jxdO2*69HHi3TwlOi^7RU47AntdMe&p%os7L{3|+cT%L{{x^kwx^-tf4euLz^j5V z!eAD!*Rw+OpG+c0>+VdZ(OVAJ3+qFf2B<(o^gXkuJvfLWA4{I4uXH&0HlqM?hafAL ztO)vK$VpDUfv8@V8|4KjG6XJlZ}1cWnSB`rnPVG?%Wto$^GUV^YHpeOJ7omjl*Zev zOILI{V@3m3xkeFum!OWfxon!()n!i?mH3-Ng^K3<1ECc~C#V376jwAz)dCnHtARos zBKItH3ZU9EF?sUt>i)XyvS25*b@*MWPfsi5j;<-ALX$M1onWA`0=ZQk>1{FK0?jr54~L zmb*^Cy~_-2*%~aup&b>_jJbWB^z*MN=>z?-*!-#+2{E7_V<|n9`&x&J_gXcREKuW{^To(N2 zijzScPfo|@;kUTl8&79Fa?Ma?_V~7}JxT3XhLyW`Tp}3+<*g2XVh% zp}C+3^F}~HI$;~rj`LfU1_=3tB~?yct}dKyhJgsTtY04l%X9gUNy=CC-9&l0e}!d% z6a0w0yCR*Gb)<7=0lIVLbk!ma6!Ol-0>Nwu zM5^+AY@6n31`@S4E2X{g5w+OsJ!bnjCUHx5oa_t2MCPoNe3rf%@$pU*#wyA=LY zmI@xvNxV9-JYwFY`nfs%Q!;0&(YvM(rH7mfj-zg$oqv@Jm@OSm0nc)ANryIdABtfx z3ro$1S8s1{CoC`3vUkr1;^r`OL0t`VLFRs7k$TX1sCdz>AWdsFp z%j+D$Uc_|~Hp>1;L#Il9T(s#Fg-SV=WUn3SzH7RYkTLMOeS%bpr8dv?)L(2}^`?1_SZ5K^jaOvZ{uI~Vt@^UtSj z=CHuLaig7yf|v)0V>Dy@D@1-4=DPgE#LWS8YS* z^4n!%=Cuw-=480Dm}t;w_b|VChrcmbw5T^W1<|aM6n<_4_!DN2M&9ot9GP(sDUwmc0NMeIw?2oy+j$=wbT6 zW;A-XAeugSJ{mw@xf-n=9xdr&bU(Td`}{|g%&=#FR6!laNTH$rSLB^oUbDc|q08p3 z-`1G?4LIZVb&pKV#z6^^-{yX5B=>UGjtOVPVWg`A*K{OlU^vp7=q>To{CBL)Mkgc- zdR+0FCY_bHmPF(9yl#0eOWE<~p25}Yf75rOqctA4UC;nTM%HaPzLyfx;gt`t0m8qT zOrXXVL%z=XNlxFKsz1Xr)MPbcQpGndhph3>YjM@KYPXpOqkQhOX{^^>HFd~TB9Wt#^TRP!3lHVf8dCrSLIOo3O{8UHJrCrR6coLb zI{`Zv3wy^yiqpw6wwDsUNDk)YL(3DVtWE=lQgvKlf}5+Ev#E{ss`0Vo0EPfDnc@_* zRIi6XumF^cTTID-WoTr4^gU=oGBq=Iq4bhP^Gq$FV|Ee;7AI`2tkc#1gQV9>Y7~w5 zZ20>5Q%5?_Pj!Wcd5vC(jQS@)(qiK-#zQb13lE9WrQt_nY{k}z;VO|ae&HIC05$3( zge)*Y;5B5aMua0<^rK>)Mqq;E;MJdmX8iqcLSMik*Ke+3IUs8KCyO`=T?DH-$cEosy^*K*%!X+zsrTWmnQ}L7-bmb^~ zW&Jq3xLx^tbS1Ue_;4kv6#ZC2T`V2a0wX~XLY=UmkWy|gj;9zU;k{incgA1D7>6w4 zQkf3i5PIr3LBa(_H^Bh2?^LJpOFd|HCF5n zhg3UxgBG{+?0DNJln(|_wu-t&o#Ysjh)BqxAa|#Y+9^w}N>E@xG{Rg@{o?-J{8f7; zuB0yn6+G`x0;lfoJXl6hik#|~No@VZH|tDgW>sXC!*j%fQu49 z61%gqqCSp$M@o*!4+#&$Yv3M(e*mrlsC2QhRyZdLFS5ZQ%B%iD;FR@xvymrko1biG z?r{o!9I!qMJ--I6P(ZgIUAvmTeFf^I%n$y^c_M2TyBm&42;#w>>PiPWh;sRXQn461 z0#lEGD0RjopdG(O5m*$)_5br{WWf6nFb2-_fJCxLxn0Z?kgr8HkzUa9qQ{X&7{z~Y K>EnAY;r{_2tNbAV diff --git a/test2.exe b/test2.exe index 243e4682b4290fe5fcebf7662c3669c4c59d5712..fb16b1f74f7dc82134251b02cb84b1da1d5e9d92 100755 GIT binary patch delta 17224 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 L5EuB>ej)x3J03ri delta 18 acmbPsi0Szr#tGT1YV#NvTsIbcj|Bip2M2us diff --git a/vgmtest.exe b/vgmtest.exe index 892afa7ebd4a9f70eac2d885b59bdd1d13e9f365..2ccb997a3e3b9a4c71a99539d7498d1be0f07e81 100755 GIT binary patch literal 67189 zcmW)mWmuDs*T?Vm7~L^qfOK~^3=rv*9^D{p14K%43=r%@5nJ&GN>5-kh)5|CA|S>{ z5pf`OKmY4FFV6Kn=eo}O^ZlIT=z9%t0U!Vr$m0jWx7_~|{~x0NpMSEnayxh6swlhS zPaAVe2N4LMd>Zi!RZc(p^YBnLCys|J<>$r!YB@MKkP;|?b`(HM%<&xdbn%g7hrw9N zj>WO-m(nE01tAf4fQljrAO?mJhy*o4SR5D~qDqd82V}mdVE`});tX|xori-Sh#Vw4 z%9I7P;9BK=!Lz^%%JTvIKLwD2ua+g{t_s|0)r5d@P*u7s#es<4XVvqGwwi%akd z4M~PuIoo(r!0#?CXn=!Z1fHw#aWC#E9s||CQM!w#IZQ#u&hN5_W50l3j>CsC87FwN z`Omqv6~i{y6~Bqx@U1c{NBAFPbh_oP=OE@=%pDcgDASaqw=_7QG1SU_BQvw7e3sg| zO+^(9kq+PmbmAG&?6Rt?{nGJ+n$V*NYBA*y@tqlNpPl4`H5kx>fJ`GebkqKh~tccyoaUYgK zai9F4B-YteZQ-JB15z%LN7e~ISakA;tRQHUKnza?+>O%tY( zs17)hXz_fOv2E@G1~X9oc)c^tDPDNpIH=Am?YCM-s=&E7x1%GYHZ8#bzz^^RP6OF3 zK7jWIV4o1)=;c>Sj7X3LT<1>!&NN@Z@k1Km0QeQy=aK6Q+Xh5^NSe8ihL*Mm}H z>u_Kj4%nou`}lw;iJ-s$KR@5~(>|j(@&Ho3`Q+MbLfAV%Z|U^edCEX81@zi`l0#HK zk)3?YOGEgO(m(!VJn`)w=Vh^jBBdT>7mu##v|ot_YRr|LW6?c86q3;9LpCsLTx-J7j)vDZTYMFIIL_*yb4ITgA{ z+al^7wKQ;*1nzfosDmX%Kr`g!VNQ3}A?g6O5(-Wu*|<&Wa)Z7fZmigXCwBJ@Ndi~A zXsGql+1k{g^k*5fIoc3CR3Kn%e>*SXHqp30=GZw0&@;A3KBzSIO)X<0q5T?y_N0O{ zwb8QcxRsbveX_IgpEQEh{Bu|J)}N%d-l-xI0gm2oBKx3vHzjZ@QDy+Y8Ou<_UtY$qw^&Kzi$~|7 zd(7h!CuSXFVsV;fdvi3s1-8Pw7q-XTxovs0-v)uMt4ciDUO0HU18RXxEl?BmY%d0R z*ByyGCDT#|pJ9JWhEbjKumk8Y>3B7uq?`#(&a0O1bs~OIn%2P`O2;PH1ih2Ku}&?F zeVj|{3q=06vCj`{w0+x{L|-94eahEVaM+e#^iitSkNtPxWVxH7 zLT#q6m&j~QS@3`=nY#F4&jSr51-gsjD&=t-GCSY7C)4hp`tO=krnV z_S?Az>uThDgKc4+$JnWrPsaxb(?3TG2!!trm>A=Tg8&V+DUa^vZ7 z3uS|a`hm?a{2tLoWFhD?B$HcWj&2dP}sn&7s!Q3r|UdfHf% zybM{t_#{8>OrLJYS1KFjy=vFP$0lt9$a_IO2EU0be+?FbTxyBI!C zEAxflzHo_76I@s?L7mtt7KYNasp1JnRE{6|-`AYe?&|8LAj$J*DzbaDAZzkzLHF5W zap)44vKu|@Ul==V2c)fc%UtV+hq@~356>Jm2qB8m0L)r-9?vo8wvX< zj3{PH%*s+ZV>R4TlsH2v!*a}s)Qo994^|U$b+U&b(v(5{V6i#oQ8DYMklK;#(f!_C zcGx3Pm@Ac5$Me*{QTh_cRUJ&X$2o>{az$?NoESMbPT;BB?iu0XCT^6bd1y}ooIQ!r zFP2nLRA8yt?RFuba@(4`oJW|VK$>gq4=8!RThIS4vTpgr@6@fL)3zPMcW{j=9LV{( zribEZBUnZ|m{W4XP8?DOcmIs9V1_P-veVus++r$VlOdDjw}E?OI`2RDy>@-rr=^ZIZ>C%J$xZ^%jE6>TIybQq!Eq9B*7qee>F7d^t;WTW6kCe3<;>)b0GIL2Z;Ba6RkwhR>X7rB z0%2_Sd&7ye2FTgT)?m*B77yqz-Ud4p$XO>r6?J;bNxfQI?KvY;r{t}AM%sba9a=k# zv30;=TvSw6qb{bU0ko`TB)ZBdA5-M737_2fn$43oaD4l9k)Viio?)}uPscE!)%%Q& z5SF9=03}M}gcv-y;HHWdh}AFjn2$_Ps3;Jau=~@YLa~x6WaeYYE&IW_o}>L^4d#ko1@Ah1g}D%qllZ#wt?n2bhW^%b zw|@mZ7K$z%J@Y#@FB&ehL}I-K`Os2TxFmcm)*3I7?S=mJFu%MX!SZWx=Vw5?$ZxLA zkl9(;e|3wq-gFO(u%WMKVq-OE()Z>Te;ld4 zo<}$=(BmrBy#xwcR0iU%=>AseZr}7SSxi*=^PG2Q=+CpD@w6bBjHYtTq0&+e+OP|{ z_G+Pn*#jY|kHecux&x;E`$ZP8;v|SQTACVrDefH{BGJ$dg_QXZ+~=Of_Gz;1F)ZTP zGL6?>p=#fFsTGXw<4YVAtT$Bp;C)$dyOVra^vyTdW)yK5*Dc5*5UCO0)p6?}Z1 zmxgGB;>XHnC`eK6*q>%+XdIHFX^cwOYf_@~Rz)#Bkz(m3uKZ3TReDQIh;#Q0j&np%v*r0VnZOJogT^7`PNP~p`H)y1MM4jf3 zYE5Q6MZ~y$J_)5}?M_jvfJOSyc0?TNBPH_Ty=hai>GnER4O^+72CcESvZl2s66d@a zGXJTo=leR0ah)2Q#mZ-ql+>u8;K|?*_<|EJrQ-( zvvL5#H5%(gRD>gg7@QFgD&XomZQo`SkHUwoC(Z$$sO1OYsF&ZYN_QMh+QUzvn5Hzi ziT}f#Q`wh@`7x55tI@dB(=z$cooq$Zmj}n}YDcRaEmIJeStYk{6~#EtFReV#UCVGq z1Dwn1~OD z*8Nk{jY7W`fA~MOeJd2T+696+PnWVo%>d)mp_evQzRt$lhQi<9ZrsN~$SOU+;Me3$ zQPj0gTzYaOY;Y+g{ZokSgTpVcGUn=6&FJ-8Q?2CK zRJQZ{5^~Nm%LWp>xEjgDk!+l0X7Xj_a=TgJV%ZbvGthW&m5p~H9J#vIkF7Hh>RUb+ zQs>!8Xfxdg1~J_Ypxry-niRxViGmI*B$JL<@RbT+Vp^vAIO zdBTHf*&I`DzdY?2Ru#QwLkSY6twxkL)Zr(z|LJniZFBrDFxuT#SI1Z|5SR^*ZKkZt2ZdQqv9o3JxIvY%l}9xj;{g2Po8x>57mjrX|ic@ z+l&fn8CDwNe?g1Dmf*8!ovzLBjjx@--yLqtl;v*`wr7j4)VgjEDyV1@3Y<2eKY5!6&8TYU8>YChNT5N`3&r&%&?^PQ5k~R8^pCQg_AwDiFL9U5tnlvYe6UnyrbaYYG=+>3Q&XJPB8zZtt zZpj}IlcPgONlnCb84&PsbdL{@KQNJrBVimi9P=A(xL?}CW4q%63V{@LTwKzWSZear zLxLd98K=?cSlRrJTxmE-*mxTj)>M`9h@KKSH++U{O-kSqo&L@L8R#ENoYIM8pHJtD zXSYu1jJ6C7B}D;EQjz>~1X>!_G^CNh)>MR8BmYK0j zxP(NJ#0XlqBygSetzU3@N`ozoX*_A=T>D67Ernsr8PQu^&;ox%HppSi*F5 zLrGn4Id*t>XW7)F@;Kz?>XY_+csZmvX6I~uY%F=3U*c5TRMm)UX>m@?$-vOOiboR1 z6MpWd!cOMdF{9GiIl1{bQ#62Y>6*5{kz=zpvtVg?Uh=2x?g_cV$Q%)Ll6 z%!?+3hf(!Tzcx;c)z&lmrKJ~-zN(|+pBSh0=;ST6R`WN1_uHnE)$AD+sa7N25A)%K|@r3u)E*Autaok_%QJWOS? z@$_HiJK@G@QMyey!=reJ`J=&_$&l!+Irlku8wuV@xkC6z@LiBwyvcp8~z;90v$+;U4&i zi{pkGe4I2+4Tm`b0VUeX+RYKx9RHd^f}=l~m1)-*3LfYu)x<`|dUemGio~(i2))T% zkbKDr*iFw`Rp>ZUPX{MBjrzCjJh(ldk}^smgh}+M$ki8yhQwcsJMkjnTpUU%e6xH% zs^1?T5sgl_e&xZpR(UgDykYFNc0jzohw#sXxzxn_94xra1@$zUFMjeepPk*!OTlSbng(?jUxy+%*|j z$Nd7w>?K|1rz__BFGVMu7K!WX3K?a)W_ixXyuG3#vMD=4^jwtGC-plBj|Y(zjYV!L z)6r)i*NGYeL$fQXK+u>>zUhNei2a55ocxe$a8+nxas_=t86^{7@7b2X3}YjAUnUX? zS1VaaY+=KbgCfd!7t*Bve#O8%xo>O_ct#^{HyaFoOYS{17~~)c~50L}I>?f*R`aDA1cyxD6U>Ca*g; zSa6=TrBq$hYOoAtHDXe(Zh@TOD#$uVG|p@8kTXx7XE)-=n&+er-mTyHTg=4*2 z#5|MLJ5OhaAfkAXVWPvPMnS35!)x=K=ZzU%1n1yBI$XXzK%ORWrxSMFU15X3G$Js$ z<1ohU4K~%0zE-izM5MT`WcN-$$ykUA%%#P3(WTb$6+G6UqyDcGTehC$6Cn0XTo}`g zam}Sda(XYH<_ynV(rB>$<`+=X)DypFjUVa3e01Drh7y^Z5TfnhMi6?Ser}ZY-i`7~ z&+3zqY&Wo;WAZ0B*{`vi`vaiIB5cSm;EcY43*-+s_Bgv3YVk=-xcZXRMUM-C`y#yK zC+e~4t%8eU4?Ny{b1vI2^cp@G`sXb2)u3OeJkoOOt`!X1er z71==-$dJnqy68oh?OrFy2-i%>DJw@|k$#b)vtcRiFF zOm$mnqKo{rIN(5!^Ien+57=aIW$|hdT1&{^W9yGDMW}=PS1@RAvtYN|q^k9X{w2-VBfi%TOFk zY{`XItTd6IR~*n*NoG-vAse^@TD7k? zvr4uOQ+7`YoWv!JG;mXQ#}@rSrM`LcwuaFXJb8cw{6;yr*<`S}T=tVgCOV>N+E2{W zz*9;EoM`Ht8Fi1=V{9J0iQkj8o&ry8#&a{xD904>mpd4x1*|B{A9`%ilfpyUEyc?F zvoWY19DIXnSJuA5P~OB@h3;bK$Vl0IObKpFcV& z`q+b}Zw~c}xez6I&l%cWo-a#@)q%yI@^8~SU-~I4&-ey^2O(R4guHrcTP3B0) zmCwLDQr~vSA;OW-%=vKeK8L_0W(3!S?NH=dSh?dsGtW1_sVkC1je1%D##$98Zs9j% zsR(GJV_vM_tt{DIcFO1!`&$|}M{lg$13xT9t=CL;V!&qlGk}oYWOwln?W1Z_+snIU z-yh1o;#g3hmhRPyFl60?_pY{V3nre|8?atS<^W&dNlya*DfCbTGgkKVkLQ2z^()xN z2K$_vviLYXesXuNFFSxWHZz_H!tZ|%YLqNrC}G+npX9LpdjcaV`QDxuwGH&0qzs5) zm!)Pm7CvJ|<@cVPRM)*j`CTo?M({SYX5V;MiYAnDO%FY^qohL2Lx&wA3Z!-*bko8k zZe4MP7F|%Fxk(UfZp-xsE8jXIga>EsPoPH@Z|b2&x_{cI6*n7GJTX^s({D^>-L~fs zxDEy6wn}I5@_Gcey4RM_hqY5F0)*sNd$ZhQ5O(h2+@3?u zxQCRTUx+q`u?cfLGA`)6doHWz8j1}&)hE2G?4%o>Smo4N$QJB+-)andlP3eT(=tB= zYr4^`+En<%ZZGF6r@~}VhQfj{^DuV+IL@15^*-pPY@a%wT$_BWF3e$|CcTXlgsZoPO#O1F4y*Pif$(9q64>vEA% zE{z86P|wU_{Hq6Y47pNU=it`=`dG_pb762^u5nz2@@;pUOSjH7xAFD-A@Z69N8XRJ z;i!hdJ5Q=6Rc7=^%O;TDD`RQx%C}GeT<`z2zqlhlYCC-7YY&pD&;RTt!MRC;%^e5x3LdgO%yS;D;YL z{@PeyZ&XUZ988-Qu4LqybuU{+NG`ibfHp`mY+?{6ir3kPP3#_jYay0l>n})PTrAvH ze~re@+}uHJitO^fe#koIwl`p_*#_8Hy&kwD6s7;`B;{@1gs8LjDPr(g*_irIlP>+b zOEO&qo1zFof39|+1U_>pTacQGO%Pu{OH$r>z7$Zefiiw)wo7G7uoh}L*=t;-%AIR- zBbARL7(CO*JYYHX^?taz{Iquhi#evP&R_cG&pm#JCt?xraZHeifj0ZLoT)i+$yahl z_=|Z^82aS7DXpmLqdE&Y)1`jvPwGNC>IXXK&>|81>mv#-*LI&+-`8;Mqv~O?L4y2w zr3K|rN!I!}4=QSi&2GIZ*3Uz(xDWL>M1m6bPs_*17jY*ykwQ&nvl`>L-kc?bfSrs| z^zV1tS5-Fn5>JLG7wo6HDC`-s#6o2vRSwmjA^8&PA#eTL{w z(9yqS)obtYk-@W==E))W$PrCGHGsG!!%2Oat(j<=^@Ey(yE5ET?NBmMx)JFLYs3ff%8MO=Ajq56S3;`bzEOYCbRu+BcYc zOO!0%J2sdm{X_icc-Q1F49JW%=~AfsvmPwbz@j>Y|F+16$K(ne8FZ6a>lD8=Y5oYT z({XE{MJIvg(k_7o;NQBflJ36*3BvlHyk>ka>I)^0KZo6PrTh3u0P{3ORK}94XxSyk z5?l2}$>EDv_h&522RCez^#$450U^s0dEHDo^}7jZ&Qdrk>E(eyT(KeSB#&O-$oz$Z zW5sDC7$py9|4p;N=d&uQ$o&%+YhQj~_U{{dhw>KZuv%bYFWI%;H(12X`KV~EAnMNH z+d`0bT@JZ4#_0Hn(yH4?4M6{vdC)Ge3N+}7GT2zx^(qBg4N91=hAo9;G^RrWUeSMWNq;%DwAa1`A93kj*^D%l+z{_jz@5>e2KP@%;k7==+xp2Iv~nDtM(x!&u?&2GuoVAHy>#GN=)i#dI% zi^n?68DR_UTqk;Ha>>CiTr%bP@WTBL6*%_@rYaDnf zD+Otv0$;2WQ-9ijmUOFKWx-Uizs<>A2;w9wwbFtA(dse8ld8Gx1fE*)yB5m!4?7=7 z|0Q=mwWrYVSAvm`px&9Rebypu9AdAT zpRZkN)}&mJ=dKT*KJ6y2Oz#!r>z~Ua1|4PI8Y4%!E25POYnU(1!L&)Bqgy7{Sf}=v zNtmWs-%D4`+#KLmv`d9t#;so$NFvmkz5FtOdT9u6|>1C)uooUKaT3^BK+# zWSy+~hj)ewc?i{+(s3C+R&?1s`SaR%zST>iX~(*X&~#n}HYKGHd8^N+;iw-?k;&0W z1EUJFL^)BvbxAGyo858ytR%|&Tu{hxtB1S!`?kMtl^lza$D6(t@1x+1Q0|!lRI6}Y zoNV4;xFSJF-kRaEf%9gwAJP_$D!q1bHtaG-V=I5`_`ub}XM(%%-M!xi zJ*ld3ZbnMitb~8_z9OoSb6zR4op>%ymfwz%hHG-!GN^x|@m~<>3~7w9Ei`Olonjt^ z*)~xUYpZ$XBOmO>@+Z?4tv*pSE{O{@08GL1>5H+YP~wBwdQ39A#zg6OfW%*m3YN!l zvXUsV#Sx3Ns4P@2CDX)Q-cQe_02K63U-?%sm$uUQ?}Wzf=h{AHSv)S3Ppp0@XI-b6 zdl|P&Il%xETBu@6lYQS?*0&Z>j}hkh|4OXPyS*T`RWcK%#LRxGgbCT#u@A!F07hCN!K{z!Z0b zsn9)jX7QpM#)VJ$2b1k&1HetdMJhCJ03O@X>t}|-isF)r)a`K*z zdBB{2Cn&Y{vrc90YC|0Cj?1-p*C$$5MV1yE|Fld0b3LoAE2+W1b`qTHW^2tAeCn-q zN9lS9?8o09EDAl{;88QBr*HJsVbh4iVua^x*hiS9eFD`wq$#F}IQdeW*H$03Gfp8&+$;v616Wa2}`Ju%dI$_R~Pv@FMm1`w`9JD7VRjOyo^#JETSHiO25F7F-rfN zlTt*BewNAS=#;fYa@Rp}yF0SFxX7EQxrpZZbz;1dUZ{^k_bsNIUt3IQ=5fit$h(~_ z&plm4>91e&I#Zo1Dx-*y+|8l=7zToY5+0>wdwI^=w|x#|Ku(uCNE)zZ0!<^K`>Qdu z6)eD=!44z|Z9GLr@FRXNAOIA!?@kF?9vj5T!qS8TfFIE7OcvmiHK8d0huKzKIJ`a^tp7 zpTzt!RhB1d%<Og0J}-);1y4kmHuO&e;g(<7Orm}x&|N`OE-13OC+R> zyqQJ)H-Mr!U4Dkjs$JH-b6f>;DDi1tL0vMmQNCE0ZBab^2z+v4{fq|PqR?sqD^9K2UIwYL$-zLfxiukkQzaWx z$1-Zu^xYNK1$`+;>RvF7*GHQKZIjqE=yoZ=cLS8o7C|!lVSE%qKz;$C+91&gZ^8d} ztYUDUS8Z|{Wu}f5UHUuH1Oa&c4%F%;xg!2t77@sqqvg6^rMagEK!2j=o|$H_c@}$n z&0@-iTE;7Rs4bP~mCfXN&iCbk{g3y?^RW@s95Dom@MwcU2nzO$Yb86HK7#T{CkQ;g z&LUKxq+^4=J}}@Ok1(mHr$pFF%a#IxAfE%Iv9sS%gi3>pCQHK|_i`IHSzNE@qI=JH zJV)_a>_3c^Dtj|cgPUo9D79bSQhvR;S<_d}-Jx2ji-Vh5iHlWl~g$Ko1UEqj zk4c$KJF}OqbRzZZK0@~wx5zL%bl@&!9bJF^#mh7XzogQ#-2bX!aZLykyf48um&65u z9-hlHy{wi;I$6K(Pi^{fT;K>`&lo=JvdF`mbo^CfDorrr%xb5pMoNSLhoxqN94mri z?6+0yOMG#zr5N|=3SE^J+UxtcWP$k3wQsMu%^udxe>>(cJ&zN~D4dSr2sjC8o6DK4 z$)Q?&RvB{j zwrW?mqcpc`iv=-h-H__#LanpIm+Y2xFiL&jrmuOIs)cs-27AMk#e=}6sRmf%3ux87 zpa&dno&g(fW#y{X0)qtCl3OEZ?->Qul@%VC{{%+FN+;isw%*s!borgdRDQ%bJsw}v zMqM60oQ#zCw0)Dj5)FpNol&pTl6`j^{*A9SS2r|-+L3+Sm$jK=vaUihF;Od)i8Q0U zKCqaZF#NogVPV(Ok5XZU``B`jTF~Eok~CbowM?H{Z_N49uOH(-B|+e0t>SstR!VZ~ z3~U|4eu-*7zuEbT_O;sJ&2P_k-gD7yoxEjLd&i}e@rm7WXgxV3r-SoIn)svMko{*< z3`WFuj_VcNqFH;kF^xlx_(pygQq# z2Fm6fhn0l8NFz}$J1>=eI%QqJn^)qz=%pUkm*~JEwu^*4(I{k*1FmT_wY=oiS+*%I{;T*?V(0i>xgO0SZ#gSjfV&Ql6F)WML ztampp^%cwz0+ZdF0dx82gy!OSWB*m6S&1+@fMwJ2jD9hK`=Dn@G`!tNT~@fP&2vs+OsE>XCn|kcP&eB+A%)ABkkYI~ASt9qt=(Ap_#UWUl*?vf*2;~E z|2yXzC%>#?KVVRgr+m^V_ztKoWy!V)W=1>hZ*}d}UeWizoW*mh>JwE`PsEr#@m>L# zJvZCO)?Wfw|8r=JA#R?C?sXObUl)DdU;E&2WiUk;tW&!=d)kOpD zUH;(a#a)qJQC9BWmu6fAkFHEPJ6&^D`u7KXL_`P=<;{Q=aSSe`x>X+r@<2o|9IC<< zi*@ddlO|QIeH54soELf#qyrOHna*`esXqxuyi~s!;-}z^iWNaVIjJOePtxfsP5Jwo zNBVS%_O^~5^`60VkSJ0CO%h_+xZ}V@TxN^7!>fb!0N_E`tNB7I(R3&j!t1aAyh#L)%#m&J zOtBX@wsCWFcKeQxvI1t85}!Vz+xBZY5k%YBgA&3%65_GCVNpWpQ?3E$fjv)m8*2dV z6zKsNa2EnVyYzJoI--%EHDevqI_(*(VEi)O{bOQ;-J9q0S#CBqfXX1?YdFjjj1j5n zC$pH0&4q0e=1FnCOuoy%HX=fjM#=moS4AmTL$SXvCg}VJvfj52_(u#&`PW# z)aPp=+wQdF%9uv?*N{Wa*5nKPXxw;9OgDe1e46QR=gThE^AgY$(N6~4LB4wF($y;U zxZA2SYm5^M)?%ZullecSN5^|k4a|RBYb_DJrnB}(XrA&Nzu6WW^`(1q?X`4<94|kb zB?b9on+BhD*5@zv3z)#5xjPoWOAVu6u(L;ZG|KrV} zb$0|e{D=NKrmnFz4!zxn zo2C({UA;CGys37F=?$(BpTmMGw2Xbk-n^o0Y26Xa>|c9uczQmqlgHxDO*W?du4Q$8 zRpjdD<>ST=ox0Xps{%E8QOdEm<(obau<0c2i^@Z;mpWsqOU6|H(=YqiV)b}J*JNtj zSjX1JogzPL4%leEW>vFxf8!5{HO+oAXQDW!>txJ$A*#dQ3u#NoZ$f1BSW-&^x35Sc z^y0iq$4909VCwv60;9iwaeJ1Hp+CMOXGWI&r`z9XR4~>gc_BccrSW{g(JUgjQ?%~Ddiwo~1L{{?kPNN( zcEx-Bm(#kVSyVrsidvN@u`1fMRQN~y!>67#xsEpe@eF7;^j|S!V|uXUGon9knEr2A z!(;D9!-b*`(u9d# zLc%_}@Oq(fMlh|Cc#`tj>uMt7V{voTX9jYDD_B8eQH__XUHV|WEc+pL#rU{2!Dl7w z2(fl^#905==GuL>%16J}*It@m5b#=dr}QX~Ib6rE|ELinLZtG*P)?!}EYlWCEMuR- zPu$g5^@f!b`TUG#vBWX>o_naek~(t&QSF^r!XgaGskXAhIYoB-;I0ZCVI9)QPTBIw2L~OuRWzL+-2i`Z$76s2Ai8EXEh@V+3nY9 z`4I|vuCcNiz}QHQuxCL>yN?AVBi%0kF1IwV{aEUPnAJk=YSagp zczlbDPz+hYk}COqGPzAUDk4@--27G7U4n#432LGE(fs`BA>o)CD%%-+@Bok8dTepC z#zaw5-f{6P%OCCdv_5lzn!$Gw9$N-Vx+Z441ynn3JbxHns4n2~5erUKI!aFG;(f2p z8Aq9l(m(aVc)l|e(#vCVN>m;^`sD}Zr)fjn6?J&|u&E0S&4f^*SFex{-nY6og!>=< zgTd;zFE3~9p%rDH+@AOC<>Ti*=x+(&9oQ=ChF<1OxOTry)EqQC&804UFZ7*`@n25d zgvd?ftz$KunuSEiXrOZoq~d#Je5?ZT zdnKcZtq9{T?_4Pty3I!;F3XU>4s|-AXzliNN2MZH4gxpbK~&-%wtiI+AqfhB`{|Ig z3TG1#{AY7`ypzOWm<4YA3Krr-y3I{5ful+n^Ttj%zCf8*nE0(ltp zaz{2$C&um1qL~={jxRf4ac3|3M~9&7=J-%%Kih2FL(a~CXDfZTbNDFFkDfuWfp z1E_Yt1$ga}5bXirQBsuC^R#ya22BWo6nsGC}f zf%XDVHI*$#zT)t1EKoAnS?Qv8!n!k1lwoHktp{ zxh!9}_i2~!nT(i9s=&~i5eLvwE@QgG^2}-ltwCw@y7VARSC00A3}F2E0e@K8;s&&a zMU3hJgb&>>BIM81qSzrG=xd+Rh7vcLp@9BT;h#Oh@);!*G%$k3fE^0oMY-Qqx>TUp zmZ*;3zqPQGuygA?8~>$TTK@llB9}WdH26*tYqR@;6Ilt4y?kB`a?YLcchxIV)%}oh zYd&!67T1%9Q@hGJD4jSi{FD5jW&hfp0oLw+kVJ75wYSB6`82W#_CH7fmI^e$hmCrV zQbd({#a&?fpwI5K5%L&5m5Ls1M7|4-h_4 zG0isJSN?N;y-h_A@Yg?YsIw0I0uHIR7|&0K`(Dj0edMEkDiOZ+&?*+-(=dq`u4RpL zn6F6`Un^f*)LALa8@%W}CllUnu{DB+<$V>BmALE+TD&{rCbuICRrv0A$O_jTFPopM z`^Mf1JgE4wL1hP6KdTd&AXFjy-R}0I73=+zi;ghfojd za+~0_b1Qb>N+s+6QFPw%Q2!4czkTPNbJp3Mz0RtvP-iQYy;oYY;||{xXO(k^hISb# zDY9pAXO>GL`^acHhmer<`Sttj{onhq_v1Yt@7MGBs$c-1&GAik>Nsc>+L1b-O&OPI zigOvy!~%OT+0S30pIO3%k~c(JO5JgLBxm|87VjRui%H+@>3}0^MH=d0k)Pph_G|Q&EB3M6&|CJ8NvUAedes~ zX<(p0~e=r*T^S}c5kU(Yc?xe#}I@aJ4L*w15@jx`+WJTkDNtg^2n=LCGMW4{v0PDUj zY}p6cqz#x51v*wf;nk3HV5}B6-Y1teozv3>B!e;?fCEdrKqcXKMK%R!j>=Z`0Ub$u zOFJS8e?vov!?owlem~t;XOxwltkwCVr(Cp+z0OwNIq_-N1RCv`BLm`f+Tgwgfm5&W z5eTN!vx3Q&A%^<~6cy@am}#&=hFrKd_5!lPg-+_I} z0l1l@*sFfZwoPtA^DAp>WcgD*zoAvh4as^qReJjGB)zL>2>~a>O8hr}uPK1oMn!6D zeLBGST{h)`gtzI7HRdK4N20Q@Jj?K6UPL}0f208X;L?s8eX;SnRD=+AT?F0;Y<<3| z`a<)PYOdoolBCiR=z4H_Q^1EtF!=ZCYfrKT-~VnvQq zY0dmVLbR%9t$hfNd8xaDMIUiKf%210#OQdusJq=hq>ue^&xI5}pL#uTPfq3me^%;5 zLOOrqJVM;~*RCkE2!UukEjlW95M{gguFV1MD!(R&d@KrSofKr+I2N=TgkIkzdDblW z<0_6N3kKb`uF(Bq0o1>A2Pa%?*U%7u=_8GWAD&j95Q6Vox$Pbk(w}!*#M0{gL`{|6 zFT6v%SBhSYMjhbuU3rMk`Lm-cXyaih|MXZQRuSBS;lA0G`}WyzH*X7s=^yW=4SNJN z)}Y`^-o3%-6oKSYRC&K}@QrM#TF7ToWA&DEa+{_714QVg=f36-V%O?T#~T8z$03_@ zdEXIEZ#|&zJcnTejj6SIZljWF?LGm{v$P4BF7w@thCy!@z&jW(#{2$18&4)7r^Tml z0zuwModB_r@Ie`23E>v>Q6{g`a0~y{za0lcGy;y+&Gl zZ2Evk>ih9az0nfIKN82{Fd7|t73DZ-xF(4;jbz`v*2@}nbAJKQm!WK-_t8@VR_cFP zaj;n6*Ot(RLp)(%X?%cvXivQNPxK0Ok{>g`DF}!V8i-l_!ktD=oS@$s>pr+W=sj7@>{|s^AlCk$hB2PDha7?5Af*5j``qBQ2;azq?QKNYnlxFkN zSn>{GFLsJMrq(Zi0FtkRpFU2~+4!6>gY~TIci?kV|C0;u*A!h1bO1G<&#AYmEQH?G zNo|~)NKn$mN@d$e7WfMP153!lSTbGIs{EVn#y&j&W=<6{NACRkg@KprJ}Mb@^RyD7~18qn^Odt1jCw3~su;O4Zs%40e*ELU_) z^|;)H4GIB+vi^B@NU4ziPGy_3V^g`1}jl7^gCEpMOB9-PtZJ{>U$>z$nOg zlmapCkaS{+RURS={erJ#4h5tP)26fbKGRO@=CH#?(BV%9L-t(tG*4!?K@PsxHx>n= zkvFal=x-V{=Rx($MArsdtbAXAp51Wtw3O!` zenlzj=)s~E(DAb%zo)cu-Z zC(}~DNO@{12}CXfe{u)8{cY08<&I7`)jLoplO7e3sSBywfJ6y3F{%*&a;9f-q)tCtzciO5s_M-1YASgRvK*_?ru6Ia{$8;2lY(&BY>+153cN4RszFU&yt|eX zqaej)zn~+zRi9N|(E*Sv2|OyB*K?b8=o|}R2G^&Noz4<>LYL#4I+o;LuqKX`EQOBdS?z9!VY;9H91=e=9xry)^E^ z{)Tnkj*46Sz?~b^AN5J$<{s#{`E&bHy0Z<^^4p|N^2y@`=qCpk@li6g!Yd2&DnPsZ zPs1PWnvV$JMI8HO5282}mJ_n@Kuwuj`4w-3xcr%O4s7^UA+FN25*?@(PFc%cuY@4Z zZsW9U3$AP7zI@yT4*ohL>PiBCItQ@ziyF_#dyx3zX8z1>Vv=Fq6Ydx9?>oSR}O{KQ} zfN&x~GXlQV!lOn*m6&qywLdN{=mS*$_Lu9-2nDSax;yjGMsLVr30m_7@saX{UasmKei5= zoQ^3hJ{HDsu`0ZAHDd56m&EOPpBm-eGxWt+naa;DXu+Iju1s~xZ+V*5Y` z`S|-f2m<^0rf&u8$tVBvTpGm$J7U%#;tb09^QCab17av|?#&y%NY^;k-YxJUK|;@M z^Il{^&iNG7Z3&~3sBaeX*Dw_xa-Jyk_`vNP@qwbR6j8p3TR zYU!p&>KAg_3kfx|Qm?Ae5?PUF%=!$pJ&#lo=-F`dZh8l{9d~Y+Zw}qnQn&4hSiG7x zp!3rqZOb`#Y+s>PRI+?*o6B_9-Dsf9=Vb$p0$1_sW5%P9nr&yxtSqx96x0@ZKA;5# zi+gzR*I{F)Qjx38lE`nHJGo>;m(=S(Zt70pHi!}q0kk#NCpM5!8>0EPD#~y)W|<#n zR;2{i6#o_#ShrIJ+b2~G#P+xE4qQJZ{3V{@c6a|8^a)m<0m$h3ol`?tzU(CUwiWs8k#w$3V^)Z$%B15!kWCU zacRN`?M`EfHkO@m*=Lh~cuvkRgqzxG7(1RQYx71}m2hORe_kXi&zO^|P zVRujWeOjv67U7D4?owHbRS3A>7y0%EY!S;iM&F!~~BtrS&zTc2@_u?z%W#=C(=Gr#eg+p&9g)T(| z^KCkb@;-EGoCw2cVZ?6IK3xE=Sec){cq8C7XJ}#HCaQDf__N2xYwA}5DrB{e_pJ;--_`)xpT2&?)<9;5TNNX5M81+IV#hOkef+6_LI2eaamHb3Q#-s>!_5U3uqe_o z>;vCIqA`-P>C=-*L#8BsjnlzYG(2x^^oz86ma_@=eBFR)%wjT@I+!ivyy{8i>6pj3ho9 zGfHt5>PsmO6QoUe`v@UcQjb93QTLUr`)hd%;``+f!{)Fe80*)!nON9;5w}bv-HM+^iDtr{8iWjVAq`00(Q%`CCfih_e zbWn(dVshlQm+`yzz#Sp$0!?J0fBdQXOZR*%>%GDgHSvB1cY-QO<@_^XawLBkYp! zKbwBp#nrZ;y*7=SI2gOEUs8JzjEH2RS2zrdR%BzkbSY{`y`5y6IW$(H2K}-!DZ&5P ziiv=N&xOD|em73;DPi?A`9N1Ix=1a+xpCS=mms|&OzWO04wn36#;N63aarnGlYiJR z8QZcmUrg)ATIxd(&1vJ6Npq#;p2KKx;r6?J_l9=0-^=2odMMMXwxPCpf}!^FuJU=j zf~}Y-%y)g~qGjnJt9oF*RMNJ?qV-N(pI*vMJc>(H3p*v!?ols-763$NdkEoOdh7Re zuHEk)gMe6uQ8HIe8%yeV?Ptx4=dVmL1g>!VIjPxX%(b`Rg8AngIq3F!Q**Mq@k_EW z<>(ntqNHKv{jM0#BzL(#_h`TIAp~Qe?fI$y_J}$#p_-iXFzdet1j!RC=gQ!(rwO@b zD09mMXP^k*#@u_?>GzFmW>15qE=j1w2GE#C$`?gWw<7%)#Xs){PN==BqmQFc?EA#e zxAKO!cZ7^_@11P2a?%LKT18}Y#!7B4nSm}x?s`JadD$1ROr#+6GALKMnrQMDqyX0D7k+I?bR$~M0NicQrF@A3G?<|kRs?7fi^x%dJpaQ zOJ@0z#=x0*62}Ii-^m!Tpwkqf7SjqkKv@w`QBKLkR4CN0)JEQicS%d0-;d@2vvaXy zV3WE=s z1}*^^#kJtR&F-i@@^vK`!Rx7Y4lRUYBs*&?az(^);}+**M9m*`LwCiLici_@aO=3L zycog2$&qCv+1b^~$LmVJlDa6J9EL1_Td4hTS^xAI0HidX?Bc8&QwPbdvcoz&LS{Qw zP#v*e7O-`6Y6q_2I*J!`$VpwbNxPZq!@|LDsYAq3JaAk62YYEySXILT&zN4t6$X(M=f!wld*cQ2| zgcCeF@bP%VQnvN-u?t1s4kD;Cx24NU_rc`Tr6kHJgw>Gl$9}7>FBklmYme%dTd7*H zGlG>X4RtF=}KUoakyiuSrMin64FHP-(|%sKECZ1G8}h3xz4tP%_(m2Ngxu!P=i zaRs@GX>6?@azni9BV19gcFjP}7l?LsGPm2Ipe5U(MEGD$eJsSa6axg#<$VMP^qIVr zch&KPmO8fEjexDFVmv={BFYMIW>{rQOYF28$OGoyv^Nf*^%~rU$u|i&+2g?RRJ7m~a&p8wG!1xQ)jiB@*O2m4-m;Fg zat;dK2Xjck)QQ?-FK#{0uU62hlWF7h6>XSt0Yi#3<8hnl45+D4nspM{H4t<7s%1~=g6`VsdHjcu}BP?&V|gNeWU zR%Nmho}I(8k;3~hZ*bW4ys%sbL@E3;^9EtLxlrOisLC#R*56AYrQ<;9Jab#4|60we zW7e4L$vkp>@B#RAlhM2A05Wab@2L#}w)+9jCjY=zex012eHsG^Mz7 zTx_hc1I;P239!OA4gd8Lnk!+spw#bJ@Y5zPL(KX^%1MH7>1IkM#8Ecdb=LLMF$#8D z$RXTAIIgDDsGk;V1O&j0ep3p-Y!NrK${=?Da9>`IgLsE}9ycGG;a1=959~fC^m44f zi*A2;-wUOGg2=-f)Oz#FKX#FQBO?8TsrZBVf-A~q<&2WYfm zzTCU6^!tN+&cUJa+Fx2OTm(fPgv33G`GKvtdm!vTEbkC0I@aWty6LILsw`mx6PT^XJ`c55ye#IUbM@$+G*K;|% zA)a|Vo~eS~6kG|InxQ0`((DuX(pW~A+r9h83j0rsbJf@F8su4I2}c6(>em$(%Qi_p zvZgsrDR?$P-|DD?pLvpP^>pzQ<;f)JE^2u*c9HhIVbhb*Y$@X#4a&YCdAuzHNczT5 zE?nP0C>!Ze68B5pkI2k}aJ>6< znqap7_VZ7=Z~ZxwiWr9fis#QSvPoCtG8ev`JkFP4bVX8&;aH&L{T%w_St=JT2-m7O zMgzZ&YdUZ6Gnb8n6+ElmB55>Xf|5*{G#|l`clq84taQ7T$%huY#>bBWmi|UCwXFpa zP0wNFc_qsY7%bT;rMAxZQ|NuDQ?XAaJC`cayMAk23)u!P?Q!Cid0$S?W0dTRdmTat z^$W%DnheZ=OlPoi*-{qih(l;yF{9x13kSPTFaMftmGgFl^#nXm?VZnO1O&&q9XyAg#h zO@28XeU2g5D(xUCoHBFJMkGa}!H2-D`EG1!`_hnq0`vOX-ngUf zf71LTCwL=euS@0z9!aq=9T-2H(ns77>-n1XGq7QJ0}{g+DSi6jLMu4tp&lbLII%OU z+&_mM`wcauIa3Aib*SEtG2siGyAOuEtBRyESy(C0pOQbkBT5B*m$fmCd6h`<^H3`zJ zi~^ZBE)Y(~-y2i=qkpyN_05PFnkaUgq&Yz^_`E*g`p0jGkdtlVv68TQG*okl8*e4o)M#aNtIkkt%*HD=sXO6n(4~$5NP8=OUJgVgP z`=%898oZcneq))hYn0!!yVJS@K_j=Hv}y0kny|fXd}mZK&*fV2P;fi@oZ(@r)dSO54NE@VPR?*D-c~%-+MFVvOb-H#ZWkIC6-nuF$24RJWdY@u7=JI@TngGM z#C7ga-D~4c^$dm54pNr%YZs4XZI;A>Ej~5QB^(-D(XOWw)~tT z2S;)X%+>3Ge}gd}yNri9J^V|QAfSIxMZU8w9^<-a$Jma+CMHr(g29bi!?TUu&oOD` zqz>@Fz&3<-87Y?w-Z;NoGp2A-=Id}4=O2O}Drj-b!XgZl%R(}TJ+JE!gmn(*8v+c; zGbIBPT|7w42Z`SO+uU_4NhcR4@RQIR82UE$7N#)2|G55p5P=}^-Xrr4b1GNlaG(iQaWET_k1ILT=#S94P#n|`DTv|mPy(|q-Xg~$=GPS}l1{8- zyU*j%B_-duCs2+ACp(q3fq5w8?&Jc0qkyoT|9tp`dUt03-_|>+%zv-S_Wps{@T z%!zgF{a-zcYN4KQhP$VY`Wy>#~D}0)Gx20I%L&H^jkr-O#AiU$-rI zAQ&C7Uc)0uwcsxUd1o2iX79fZI;ekn?l$l+Z7a1wFZJ_%5%36cqHXeh7qmLWIkn5N zL#&f*1@WsBpniS;IA>KcM`nm1Qik=~hCKhLPV05cI}Sg=1rUW^BLYE$4LIy z9L6-r4()@BEi;iv!C7^&7Z5hd4&HDLhj@949oos!-6fOd!ps}YK&lNa%jio&N8!i1 z3E!MP0CKC`8YHmO#CZ-Prd2Kp;vt#bLlxL%5Q_Th#$BdaB`~Pavfic3zN4|AO+H0O ztM?0#jIW89fiiN2p}bQ((Pyu%kyNEchfb_Tz)wPWTBbhgh(3V~-|z-Q^c=3oB29Qi zMqUFKkv&xd&laXR6X5W`?b~bhaI95%Qh4BXw^XODLkCI|t4_M_ z6q}#*F6Dchy#yk4Ag*5tSUH+Cc3GfDY-iE0UkuCO5w!Wa0n6%_#hB*Mj#e7{a{12} zwfBszThMq*&be)vkG;v0lN~rMf&3+J^~86o{3}ee$K3ZDuThwpi2F^tN{E!F4SsB6 zduL}2_HQQgm?bgQQc{&$i-)7Xfz!N`p4S9Z@X<8Y(7YCR!??-eIu~Wd*-Lef!n}tA zNLq04SQF8%VxtZgUW!@yWoVQ7{1!Ak8^&mdM%*@Phf9Wwdlfm|SqF^f`lE?x$J+WX zQK?QDyOba2-1w9elyrTyRwd2vGW$YP54Nhca|c~+KCf|9ch}7Lt{19Dj^C%Ci|t|1 z=O`sP=+t4UMb*bL`%@ZFnFd8;sAG)%6za(UTMNwcl`A#X@JVVn>WFPs3oTctWZMWg z&c#(1%1T-969SpMW_KT_2R7Sc129ut$n4A0eq%;Gl+Pzqm*ka`BCtrP!NndpDEs%= z7!Ct=>kC2SK>!x}8L(-x+^8`61ds4B`Ym@HcBu9N!3;23iFv~1q=s2Yk?M;ytd6U# zlE97c=RrJ^McqQPv5&a-Ub$4kqWtr}W$0;}+h-iUst=cnfVe>jAG0xPR87!zm3!PZ zX*Q~e_3TxYl_6a$0LbXj0W#WYMKS~FB5m__)Fa!lEoiiHI|F8bB_kps)ZUe z5gDH)YQz7jsPWH3E1%?$-yDtvc`gYSKcxIoeFgSAe&6EnufGI%))&&iu?)-h`%emqLsC;E#&eB| zpzsS&(wM;5d!ZF8vB?nM(=CElrva8t+Xii<2}|`g%jp*OCnYC=|EWywUF3og z+8y)Dxo6_4Jclj^=s9 zrC_Zqav0FZ!-H^(rUO+bsqb))PJ8rMAyc1tMctJ{`mGTrC=S=DdXa5mpLsgSlJF6? z*fu)rmgeJ4kb0R2WQ%cqKhu9~>1r>I?Za<} z?D+`?ol3$`KTv7y<^qQ&!G(P?$iKPR-mVxPiO_FF*s4_gIQT5v?c z#pHePLAezyT*F7XkPnzGPQwVT-slAP0=e-vQQaLCu~>O_Ys5g=EQvh-oFXNKd^5>= zKtD`D!~VF+5$3>*G|#s0TG?1r7u~qiG7r-%Rs6lICA+v6UcXgrw9W|w+~;}OP%uU4 zqyCT!(1F{SPydjstaZ4qu&Ml`Xs9-6RR@sE5A8OXmOFhhnxB`F$o6f5fy>^NysW8^ z_@_UYjJak<7$zS-8Tz#moEJ_cnavG#V!>iZd6W2mb_&z06iZ<@rp;07+~T&$-X+?W z=M|xiP`ch6B;Ich`>O#PZ#$)^5GQyc7IX*UM#P`U6v)-9tAgsfJ zBAbcs(Yo9z0`>2{k-e0nQJTVzF{M-|EfC;TDT?lZ_z zPE)rnVaCmR6u9ihVB=E=_kIU)J~vjfJ@>u+eb}ga-s{WuTUi@L<>O5oA#3)H8e?VE zFzH)R4rxQiLn&Io1TKr~10k3;5HYC{9*R2c!)-q9(5Xu)_ylIxm>@$_TtZIEYB7(Q zD;&7UQ)4u_n4s1l9`j>Uct)-FJm~swOANHgaUL8s@0KWdl*(q(^ey|p=0rKW@?9oA5sYN97tRl*<4tKv!A z`G=Q;Y$gvo^3{;bo{ilv;?Yf^4_S$2(i)H_8E$fK--^KJFMxq@(V{Lp{0qjQOL7;? zGirnLA0Ql30Z3COinDSn5PEmPHb1_Atw7ng1O!vE)g6O3@9h=^sJR8T>8kWte>-Th z2pdR)*^A`pBr9fy$}F~xJ(x0hAUo#6!o;W~Uy`97S>fS}1+$RD>yk{={sZ>c2jg1X z29zUfQP?Ne06vsQ9lILJrw?ZIvRc=75j(BZ@O=abqzyu%^4lO83xCJ$0!n25TgmEg z;uonneK$yZRokgh*d)44Y# zozGr=IpbM9M-ei!TNZ-HB=m~FtD61E5Y1#33D10drU2za=G zM9xPtd`aVwBGrAB$*s|l)0&WORD}98iy;iD7MLVw#}8bDhx^JgORJL%$y5bbuXRFw z4-Kz@P%zg*Qy?{StGS4PWUM5=b}P>Od^|)zKMO)V^>3X&^|p{tt>59TZDi0>e=ARZi2{O}`BwPM+)q$PL=i<3<1NLJe^%evuR&e~j<=bx-{j(sy&|M6 zv~OJzmS>smh;nrugDCnNNUFtu)Hg5pG}^&n zrjT2Zo-Bhv=3q(@C!MNp60BMP>0BkA740`I2uK0y<*_*>bodqVH=tW5=izT)voKLf zYIb40YckxRnEEYS(X2wTx+@#xPoxEH&wp-_d(I!*QVGM)9sz<{x{C&+$+$8#eTQ~6 z!$Q8tZCxfA@SJh1mV6gHwS<<{QX-wGo+dhW@z@+4Dd=jgnTXuutiezIW94;?t+MrG zIriWX1B6)cOGs6u1cR^NZNzlf)KIboyz5y+m9f}fGTzTkiAzothE)R1o}hJ(JCG(a zH{C4r-c;#ZU_$)+W-DWpb4YXl9UR9HKok+4r4Dd3GYhMpiiB`m`x}!L@_c>di6t%9 zA_W9ZclmRsTmC&b^|3&m2eR1>)~^aXS;Nqf|aZTQ>lB2#r#ktUmBc`ER8Hd=z6+y*V(} zbgUMy&wu&2%pWQFv`-c(N_NF#7bWi~_=(XHhL0vlP{e7_#)P9%=|7?`7u^AKKv(y5 z=Q-PZ8110Sh5;@sFf!T>sYviuxx*RP1CI5b<1kbKrQr2OOE^sF?9A^*>Ru!Peo6Ft zpTD@;NdXyB{&3?Ba4Os9r1EhTCed^OHJYwO^RrF z;wKLqDcT6TTGxaS$-auaDgF0VgRFEn(r|^DJ@B>R)XjXI{k9af4`U6pHP%L2l! zC+7Qlb3y6vx48GXYV_ja(v7FnLEU51(bKJ$;7y+@amOy#w#B@IZJBYIPdi0ST^lvW z=T*m)euH?UIK|&T2QqHFocY3&bSU+Dd1`$PkAMwr=3YG!f7O+o4CheluftA0Ia&nP zIcwroFRm+VQ=bbHlz?JMz7&|I>Gi~QJs8a#p&ZZkk3N~Hl$3Jd5A^}==Q-zd`+s+`n z`NLa+lsn^-H6-{R#;Zxd>rKy}&oD9@Nl?BVh(G1RIp1?TG&0t*S2g`XB{BR*JcDeA zFO<-AYhqx}4$N@Blg7+mIn|g6_tn-+lAALSfoYwe#V#r2kT8j&ii4n7*wDM+2~fny zN1A&9`4MEU7A|Ch8rzvryd8xC*+Q`|YC%WNtvBSGD3RViPF&C6cgqeYsT=9~-2_(r zvD`QA@U3kBkNBA%h=i{zEso18J~=zNVz_8P@Y&b5y0_ zXSFin&GQUzq(9>#02yMt;y#P6`bqeucEVt9le+wN+XMznab($W!~~4@tYt9(iY3oU zYuL9Z&gP840t0S6_j5-HyC^(su`?q#V|nkPlcG5S0C!2ElzQmAKvgrp&}Vd0cq;_K z`Ln;?ZJ}wkXvuy;hw+*#ZCWql`xM?d+ISnRU!7+nP`<0l|Gi#hH7)nH!Y85DU&bLb zXXo<2{kTfrP_rJ{cv;f)Lg#(>ReQ;{NxW>AS)r+ZWv2A3p}x} z5viB`<|TnT|E>B*<)KQug;}w$_33-x4{TcVM#4qr*wA8z$9q-L@tv$>=5UggBw^kc z5|3T^?P`2X$(pgLPPP&P-TA5$y&q;`6c^l#zL(rAwYiYlO%XQE%5Zv9Ho}J6uPU?aV__Kv;I3h;(T zSq@o12RHfi!ofq|D^2e}`UEc6$3a{xUB3X8xh-H-i#zTyu`NRB9v~m82@o8kXks7Z zVlsD(;&k+hJ|#sRn)v{AXoqahIS2ZElzTr8FFbWAm~x6#P_O9`byqA|@`1IL4^C#& zB#dHjOgda|D=lqLjTGXZCD4G8sD&9cD4@764_4tsw@QUX<6J^0 z%cnF9l268ixdXA&WgcV^ljReX{&R@-S~JO5E(o!>V`5Ed^OoCy!??u?7#OeRlPl6t zYJB~}^s;`%I%yB^is%=C{zsPHvZ#OnO|rB}iGpvWqCE_3+mHoa$$owMC-=>iSeVIo zSomek1{wxi|JOlS#!|YvgjL?KD1r4S;PX@VXDEnic}q!d(lq>eANYviuf)@>u9~Pt17(iU?E~PeTDoL%;bg> z-+9H1b*Lpu8U0Oa*E}QsW4fL#nOOT>v+9HG^`HfAvxGz9i%*SHBAs=?0yh^=EYUut zQ@0htvsnrzeQbVe#0(vF9UR00*Em7wz14gB~M8R`5t z$7m}C4jPXoiY%)a@Z~VldizE{rNBJRp<9&-M8Ae&*e+Zz;p`j!(rE`Hiv=o zkN&M(rS1UIOCd9o=m8BiYQOz9=DRlU=1Lt|^=(QcOjz%%Nutr+2-_nqX|kR z2`}@nF)aG~tYt{}XmeP6e;Z%)a?&$q&%pu1<2DV&4#zzgrDRA?0q4zc#Hp z9j?l!_%DI;m3uIhw^>Is`P^Nt55G9acB^7vhrSZB0`o5HZ^1YRc3m((or!xCd1{hm zrJIy6F-t=O3ptC+7ZmowhlueUjfH{*%PM!6q#KbCYbB9cH#j43Ld0LL`gVUuQuE>A zos_UP{|&PvC3IQ!3O-z|g*$c;kk>nZ zJL+Dhpya%85X)k*Sbvo1MWD8zNB9Wh!j3%d&YxHm{>|y0g7F?cOEHVU6uGzFC@oGi z9x8l6km^%z>4VGcu#^yh@P)nkPs=iRxj8p*w;PG#>FKiZt^0=H{cj}-!DTKZu3334 z>U2q17T1L)nVg9s{*!C+UbotcQ8%$5gGa;BmxTC?nm@`{j%6SP3vMmIB&)b{9vtlO zew!V~0L~FH@7;|gr3TE6_I zIZmVPR;oT*h$}PuoD*N<4Y{N)JK^5cmu_)Zkdq}xg&2*B7%BPhyc#f`{@SsPptlgN zobcU<3r}8#6$PUc+9iTe8(eKak9&c>jlI0yr7Z;OOps?K)o6kt>2V=^fch_I2$^t3 zt5YIk&o6@zI@h95IBQyV^w2#EzT@+}4Zc)t)%Rf<3*q4w5yrut2dE$XDoV%P*0PYA}zQN7n@@`K1T}`D< z^FBYdpN^5#J1DXz2$T2o+}&Ay-gx{hRaU+92ZbfNAw84Q~Y%^{vNp*4mQtJ4+();6)`z5Q9HCbd{r8 zf7TW9bp(1gDaOy_T=ePoxHAeU&jpWTJyAFOdjlYdVE6dD9f2SG4*ccLi*B3TOIe+t z-a7o+(FFEId1aolQ*h7#=7r|OVR;@PINAD2+v{M?5AbaSsh0k^N<50~{A-tN0!QeZ z3&J)qZEVzY++`ui1OgUOhJt~9ir?a?`uf+VE4qQ6bh^iP%uIbOg_8QptwF1q7!d$@ zVX2xlbav|e{QIrD&xwE6uRQl0h!o-FJ6zC`d}`(Fb5Sn!*~#ho`~m9LWeGV2&QL&XKfG2)1UqB-;cBjUh?auGGI(rA_y60K3=di~S-3bw!QZYF{^Z;X3DAqE5w5!eh{rtGQ zqm5g^a*@9ZlEXSQBch>d5aOA7Kf=Yh;q5qkn2;c-%(o-h0|wptL!v|^o2MVk z&+HNoLj+9FOyEzO?@=KEpLb(#tee=7b7I`g!?mvt=59YQzO--53oc7+3ryP=n3Ffa zasEr&k89M(N2PD-Y8f7qeDNdb5Vj&jU&4YHwP9wmEU=eUmnnr4zfRS)^6BuO`Jn?~ ztQyCdmomXNtKbq#=S-cS3LAhlskdr(Dm$4Im%PQZ73)>CUn#AZCY6((_O!4(Px%kW zZ$CvPQ{;J|x_mJ3G)31MWOsX!6m#QKye=m9Bh~Z3LhStT*Q|v%kU!_rjW1t58})KK zNJPIdk#92Nid?f!(rvv#VeH3A>_w$`nqjJeHuDDto3dCEFA{zAhh zCn_}lLbyg`3(dZK$0g4lUNZ3m*$n3qo!Q*sxub1{`p~$hclSuuAD(#gd0;2ci7p5( z3jf!^EaU9haKM>00DOgxCwJUrXT5x{>u8tZk|~qzX6d}O@$kCMg$z2H}x|K zQ;$PIda=SQ-s~4biL!nygv-m|Dj-ha@S=OKDvM6nqDN{*h0D_;LuFZg8=#IpFk}bP z@gWx;4uj;w5njl%sC*u@7w=h2J|EVL|KIK}Am}A@Rybb-?{&v-oV=GplwyZSWDDmugx#mYs~QGTt5#=e5Q&=AS}biHqHgs8*1S$IBnMkRQ zWyQr4|Es>lO1MnCQk}?3q7svA&S728CFWJ%VBNe$ zyj`8ox^tI!ulhdg!9(Js>c^}n1;oPYB3AKJVoCKg*7H*0i|R7g%U8tm>I&BDN@7)Y zHLIqUSXW)oYG@=jRX4L*-Vonbx3bz8L}qn6tD}?HRo%_%c}IL--OFNqAof*%WPR!< z4pa}aJ`WLxt4CO)W5n_52^M>jI92_HH9bR|t)63j{YLy={e$&$p2(?QU~w0TOV!J) zUn|7b>NVEyb>g4u4c6us@o)7uYiF0ZSG~^yl$K(kkHnfE$tZX5q&PoLhNd_rx>ja^ zY>KG|efNy9f#KGre z&teB~*WTl6Nk{!mXm7TjxxUNM1MZ7sFF+16`J=@Of<0&&BMar47I0aGd7<>FEsu@4 zA?{=v8kdR4?qHk)%%9k*9kV=ku|LX3HUw_}e6op|>}@vnnsR=|P;FmW)VYq&nmNSh z*A*&odf*{0Nt4!38%x}^O!joE+>Hfo-ewTJWuD3h*9cJW^1>ZPOTe~ve5~UtDL~)d zhur0GG`5jal1qrk%nJNYY{K!$v#kD6g8VdY&6|49iAI1rL|PjHQ8lL(W;ry zM+#w*6O)#~r{^QHCU}rV9w=pAkK{O&V~=t(Itz7$y>+P}-3!-hgk|q7rqTyB|(c_^j|*Qp>dIgIBI-Gyf;ByA0x z?S^VW9I9ry`09aKd{?3}aDuuk$I=dc=y)1BGs89Rq&XF=N#3CuL}w*Gr#cQV z!J+&Y*D|b~<}`&Q)AcAMkF;x@wEs2s9RN)o|Kpe3O9(s27L*{MAP6WRD5&fqAP9&k zY6uX9gak<#Zg8SF>(*9r)T&jB)=gF1byTsoR;7-rty_g*&i_x(Rj$ouU3 z+}-CsckeD~-8ZA?@{Tnh2W(vQXvycHm0t->JI!+Hd}G?`Qhw=?^*c{nHVN#VN5)J% z*CQsj%ikLoHU5>|XQRZbEn?pvZPue!?+6(+nEky|%iMK`3Ty7!7TIhVu(|8;N8yWJ zG!GqKk#eSLV(po=f17z78^wu;8@fR>-+8)l~{r{M*0BeiE;8NyE~9jAZQ{&lMcdZ*Zn|KyXeDPyXX_G#f}% z`!d}H6PG+>Pky@Q*1!8W&Ft1Yyz95t-0b%C&$9k&73`ah*llImv6Or3*>xQInH*%9 z#=3ic56dK5}x&Fgk;)EgH`U6{>6zp1O{G@f>Q z!A6|fS3PH?!jDTT+;owrKH*v_3VxM9)vh?nDRreK&9O zXyo+XEd1P0{YxxbZJz&FvVBPDmes#*o^z{m%(nXXPFsBIP18<%3TW*cYEwQqcAv>{ zm(0K=3cUEr3Qq1(n{M^j-_>7w0W+JIRlq1KKXu?}*-erjvJ? z&B=XYx7qdHV#F<~8F#Mll)1BQzGv@$IPXTMh;gMWvYcv+ z1AhMDPK@%a;Oy2nS1Mj@h9O>gZI{a_-H% z3rDGfL^NS9mz@~jbo=Yf&jnqsm0M(8ws2WHsmsW5$k%=D%=z9878cpF(yle64tz7K z7w6#j6=h96qkvujCQEr=1O0a(v11vkwoZZxW^sdF^UmAMym8_L_s_ku?MHZ7wVrHaTTwQGf1lJo9(!l{lSz}`Pna(o zF#W;jll^Y@ykz&y(a!E;e(jWc@rxkJys|*TZs89YZ@Myj>yYnShCJzarn2`NPnOra z?U(zcmjs(Fp$^ph@+Vl-e>HB5P5Qc4|0J8gSyKwW9hSRnV;eWvj^}?Z+UBcu=ls`? z&i4M1mG$h-H_Ntq44Beqt3XhCDdyOqTBptx(~8}@g@2cveXM?9iqu4PIU_1 zu&KQBlqbF0mf9xloyqQ`IQ1MInlk@udidP(ePcA_1uA``<{ha z?|qow)MGfClP4MB(C^pu^tt9`J1gHhbqR7Zdbf1Cv`c8{3T~xKX+OnIyU4?3{k9o> zozir5>!a;YSdaFy7c@HTsSfewjrsUG*fgKD@OJvXb9VV7h7|IYy!v6>&`fE?9v73K zStoaN>asjOYlOqylOE$sI40R{r{*6qe;Ue>_uD6N?caB(pp_Tmdc&yYyVM=tye{~{ zB>sga$(*2(U4v7`q?Y#J@8^Zvz2UPsmaT!Ao{}ArN>62q#VKb|!`II~nzLf1UPk<$ z>-V33lpD!C{&?)0FgFn0aXQlSsH_0dRXP;;NoxTYFuCyq1 zlh1cIyWRJ>U- zMSnf>{M{|`V`{Bk^KY?JF3%U*+L>4`fAsR&r>g_+I|_=%n>5IR?!Gz3YF1cqO^OyA z>a^+Gz?rgyQ^yundHz*%_AaaK2oAA{zVW1jzb3Sp>g@Vi z!5MXzCwofQE5bc{-{0RguHGVju`+DOqRa0uUz>paDnve8m5bwluJXu5wQJlnYJ|U9 zRcF~7Pf*shai7}Uy*Ii`+oi9*t7{oNi`UTeH-34NUALQEmLITQ{62HRoD=+;IfIP< zwqK6M8B_C?oy|ySsPh_Uv~l6^hu#mG9sj)3yLpjw*S44NolL&d2Zrr?w%dPNoWN_C z-AQFySMHvmhHmKtvVDd9-#qi3#}z!?R(OWyoEN(Z0W(2n?bQ1fEZg`DNSUqL2?%&ncM*j`VqqTrlK2C9mdz zQO%`mZgrP!zh(8Tud|PPbDT=#9o#o7E&jSOtNh`*^8?ux*3)(y2fpAbc!&G34$jzZ z*5fAMZl=Vz%lA~`bZgJrD#hF5HapBM57npeP^?Q%pm0?t_ zH1BLQ!=<(=Yt19&rGvGo_QU%_*JX9tGLy;gt}Cd0oPYSQ*=-`fKWp#uzs6K4uGn`r zz3a79{sk7N;cvmsYrh3p{@IMi;%PQFvIo6wJ;CF#OB{ZA=I(UWpS9wYfAZhd&vP#< ze-qO3i1q2px#@Q~du%y7EuQ~zB7OLR^(M22HCDG?YFefgj;?=O`#?GMpW0`i2l<6e zKNGGrRZcOz{P1#Xs%helCn;?&ELKduds&9ATyANKvv@Q9wb9$lZ~g4AD}}ac&8^wf z(0poLxRJmAyeB7qTKj2G^AD4qANEEwnjTA#?|?S@7~E|Ic1d)R8}p(gvF@i#gKmZQI+M zH*fij{L=i*_8yVX-*mreoAtc=b=%JOJbf8sp-=9JFtD*XOWR_CIiM3(EJ@BZ5QPv9}@6luVB z-W%>)_MdmCr{XmCfEW9GO&^zExgPz!=Ar;)?5hU11;h9U-k99a@Ch`18ZGsl35?v;5qPEgp)k2kPEBDUDAZwrxJQXM@%gg$*MYx~Sfc*I;TLt#<@9UhJ z?(SR3Hok59%1lsu@42x1uT5Um zUB7b2c7JWG=^pEdqXDcR>!!TTz?;m=r&ZosGX1o`@+;eGzlMC?yj3c=)%5wf#?3$Mk2(CTPdDDUwnl}!cgK=vpVmG6bxuyyK3AMzb#>=YuFl`DiRI>; zbzjZd5)tmCoFk5{;<_fx>RU2jSbMr=H}WVj`XWaX6UREla~+t_=oZ)Sj<4|}4~HI~ z>Uf={3A}+5{{7f(*Z$l7_q(6YQ`YrxxdC6fu(u0)%a+dkk0zT2+NRF#RIbcL0=Mv} zoV?F9)9>7CZfIOK?Wi@IO;OxWTvIa>CGY447Mo{m@|17YiT9+Y7JPxJCaW1Ujiz#q zc(Z2L?N*}L#U}Pat2z57M`jIlNOcv>95t1@bExNn77sL|?ANBq`K@P{uWm_M*xz)E z;t+Lw``A4eTN^htqNr`i#J%sGaL>TMBKF@2nVZB!rQ>g}0@ z6#_fseKqDmGP6CYEY@BJ|HKE4RMfNF51h6PBeSaAwqxDA)*A&?t&ZF*FqOW@e4oc& z{rk}={2HIK2y~?XRQ8;AHPo2{@0S_A$DDJV^||5P34@Kdi<1^E`po_n8}AMs(XVD-`1Gsu{2x1`&gMT%GBr|2=Ns9) zc5*bk=I(0kEa(%KX4};?$&8oY=xV;hdeGv)oMUy@Jot&ld#3aKc9hf(GT$zqdBiHs z<=KH6FU4P8{1nz>dALtd=7(K8zDXKdbdU;(j2q zzPzpRoFKF&2tBT~fyI}tp{DaJo>|3r4QZmn(Th2k7aFg=IWw+!=yliZnFnK^$M;EW zX05q4q?c9U_@>?bp%t+&?Jjh(?i7(_=3^h`j@&o&HO}u`bJ&C*^6PP-@TT&yQIm6U zOJ-SO&+EB@J!kn-I?p-JUL9LM+#zcw&$-PTV!}!J?Ub|WwnO1@8zxMgr=ilQax<>|=CT9R?u?rA=9K4TZb_O))7i{lY>zoMu(;#4xmgY4A8|S! zwy6Aez%n>srr`d&KRhC4R^;3I^U|wv+pcoLoDxkxgig6%&K=Tp+K9y&`_$F-tCEIm z6-Gsm%U87h%(1g#otQHy{&dy8!53Zbpc%_$@0^SyuCuzzcGZopA81tNDBI|>DC`}l zD$D;qJK##|MQRNvCR-lX(A@WIBYWNAu!d`jf2YAu4LsY?wzrBa@uO_Jls>;zVcf4_ zwDWD&Fw-8dK83X?{%rekPP>>m$mi=0t^EmtmH}&KHiJ%*woD zRq@N2quu}h99CBGy^Z6O@Kvm{*Q_$_&;Oib9z4EDxl7QqR}IvyPD8^iDsOh# z_IZhI<21_aALn^Dcp;rLMPpO2)#)3LYBF}LKKkt<`RAg|J*@^I>)yxj46vKIblQj7 z3#-mfpF8eW{W0IFaaHV?ds6?Hw4a*qM45bg_sI8i?P1f~?CJaWpuM-8Eo}dpZDD@o z^HLliofN!b#dD64#O>#7i!*nvu0FcDpx1G;=-Z!qv0Zz1Uu*aEUaO4{E;!wFt(o3@ z*LMDnbMRa8nRoqm6*YMsn|k+QlIf!*Iq_rW-FPrKHla>*rEBaxbkn|m$nxk`Wofi@ z$daerM~NJ%Y0RepvwIKa+&D8E2eG$3KQ%|(dhp`Wxz9I$Z~DiA>BmRn9S5(<988;7 zocM<1mZnMmEh|blIPN*X&iTvN{P?`%<2SguthD82oURwePFx&wGS7KH*1S`@X)?TD@%Zf|tnV zJYS#VA~5;$5&Q3%%c7$kSjisYCwwk8KL1>{u;H4|lx=s~h8^Ykw|+ifH@ube&4$&t zD^Se`!M&=dhoXmhM_BSxoBAA}Ot>|PnV)=2!rg<)I?XtIf<3Y)el$JV!|EV)Fno06 zoEfLh-Q-_3c6}(MKCLgm_|v#G`9)(-Jm|DwOln$)F{|^7U0K|>@q%MF?)o?J<3~2L zRu-h1Y#k^+^6sHA+h5>w+dM+{`|r4I+L?`eDaS3nicDN@EjMjcvJ{s7%8Hg-7ml{{ z%BVgTaSMKWgte|_#(*u~jCuC35`T#-&d*qFImc-7`uCr|eEv|vs+952j0n3g{L|Kr zdFYR)xPBhVrq)odU1rRF7?w3Us%&QMv@yT4Q~aBG6U@VY;F~upYj!8~T9@zzyKT#% z+Qi+3x}S$T%Htv)Sk$@$9v%&ko^?0Vbn(^fmwy&s+F{3Q5cOMT|1*NYaT z8B0(8O3j)^#Ts?5O_O{m6;vEF${A$mx%)eLbhn$-E;H086@DS8|B61Q;b}a@^H~q- z%);jXGnhAvi@x|h+xE;sj_(%E*1uLc{m9Nl{6nJ(P?tjv^9CHGP{OmUntd;8Iv2Rk zb66^AFt1zk1U6$B_;FXWeQp z$#JM(()Didvp;n<-g`3kmuq(-CPcrO(CGN2WK%}k_`5F~Yx1v8s1A(ho6d@D{p%EG z=C(oK+!;J>gZb^ml9!JUmbc|OI&?oQSd?Y8-0#*Z7lqq~(x4u9E_8Et_w8waprzA# zR~Ne!lTOmUSK_l1U#=eesPFfWx4pH975M%;gJN+7Pd1EJ?&wn7aC?URb%|-@v;`@T z0+gl7yR7P62W^k_xELo7&U#wkNHzKIJL}ODcDu=J>AoRP6LJnaEdFtr(YDL1MGIz? z98deaDV7>C#l?5-Y(eMgub;v1ThAS{|8@Rzf9u7ceA%-xdhzd@jpd~t(`UU2aW;#$ zt2LfzQhs`r7poy%mJ((z?{DLL_Ahbr-37N-M^k@~;tBdq+9!FF6@9Pm=yA6x-4~n* z+2s>qCfohC#dV(1_r5l+Cwyy0rmiVX|L@BPsC{P`!RW{HmVG;6yp3p0^-tMqnv+1!2q=^it@ zJ|Oq0bB;Bx*)j8uk)q4u>9bDQ9O>j?S>Wtaac^$yi607F?=*U6e}DLt;>YbXCik7_ zU)MZ*%&y%{HoN=73C!QCe@pz=e6_q$wrH1CpE~2SP36j6SHllT+-unTet5?{c9V6S zs+)b8GR9^%T52S}P7URL)zm$dGq5pLx$%hSG{56PH{5zv%@B-?c+cL@c>TKcU6`?a zY4)hsnY_pmA@0wG7d?0<>-HB6c>g(kJaS8e@9^~}PN3(j@89@#OZZ&ALtvqKQ!K|MYFYfkq~TdI zYQ3w+(Eiu?uIo&i%5db|{+FJK{PN~E4%=B~YiDY?|5@9$H3(Tc_3on#2n^~Q9MaGK zeXjvL<8jmWKUIu>Q&B7{+qJcMsz{z+P*|iKTOtYVk%LAlCsgNE=1NO_KKuG1_!eQ* zjBXC>RT1NTGs%A{nt@!LT*H-a?jB>h_w@8?6?#t{svI7ZmN8;jLdu`16DKPp(xYSJ z;s+-_N$TJ2o^sO2tf9eFo^gK5&U)*xE_*!$RRCsw@xm@wN zqOz)b`~<|Kj%QqBaujPnG_DVv-}w8fNyMns^rC}~ z5uNjzSHc8bymF$688ZDMB;V|QR(?FI&}C&FsuP%YdBZ{o*-Lg)mWLzRK~LCgEpM|g z;#b8lHa}baq)l+p^9p{D{O7&Ef3GMxL&U*158|zXm#^$k{(gPnt}ADY4ztg!Kwnkh zHF&juu=F}!z4uD-rOiLVdBYL~K6T|p@*kX>5&SIcsWM{UkpJ%l?T@wX@!qtXB1guvyOTb~ZHKlH7U(<7X}dDv>7r)~C& zjMiHwPCqpgnOx&h&EHj;d*NSt{O|xx_hubhn4Da_-2cbheJ!c3F|&WdwaDMhbwsCg zRuZ=LH*B<nMc90=JxWzg~w+oo8}Sn`y^`SIu{(_N?jyYjv&TEEZazN4vH8jG zpv(D9cUN3NBF|`>B~wF{wl1#xe%6jw%D((AA$HDgPD*>$%8*|7eOXG`AR~VGR1cQ2 z(2lj#yK86159t{;u9i93C`c)A?ls)KyQBS^A>Jw7oRwi-tjMjya+EQvf`@kU`^9^I zl{stE2X3lY-_V4q6%kHO5{HkLM~Cd1I}40II7(P=H@%#=J#=UHNq$qZ-2H+wzOZ}h zW78>4Y2Fu&9^2Dvg;K<_e{hh`dj2NB*fjV>t1W!lRoT!w*3lj%Zi_#$ym&n4sYi|f z-h`d)lo6(x-d-Vm%YV9c7uX)n=LhhD{pu%)r@FiK{K~;?-xn?JduIEUTlepM)p^)L zrIY8xi0owd-wOj`ZfBa=nK^!rw6-wo>DYa0*}Kjz%50~l=FVpGS&x5V^|n?nauRrjV)yhaN3Y;s^vQBbVE0-u<4<<_9DqiQhpWW)|vZbHfm{ICd>zloUF%u>oZ zH79usnlC?l7?19akpG*IpfEf32Q}xXxz4d~uJk?&t5;TMD|itPy^#DvL`3bU%V_%b z&t4D9Ef!px&+`1Z{MDxA3vRS+J9dW}i(FXOSnt~YrZsSZ4?b|_hQ;!gCq{E!=I>qn zaYy#z9bfENv4eGD!HM3@tTWwNy|%|IY{M&F$Hl?9_th2ucJDU~SG{V)ZFg(Wd`9J0 z?%p=yy8M7{{LP&T_TO-~=sYzhDVD_|fr+`;2qWzsLV+rHAcSj#JP{XhRFMDuhse>D ze!ctp$;$V!6UM4`ufD^%o3}$cRcwrYSM451Sw)OqS(~ zvxEVC{Hyx}`j?9f

    ka$PnqTLS`8t`vmo^?%l5s!#TkK35e?6fq@M2OG9K||LWd- zRAP?+l0|f;q$c$d4lgfOh=mB>*Mp{sMfvFpk)lElsLyItsi;^gL{tN~0gS%H7v@Q1 zc_medsxeYSihvPOh^M|MUdfY573DICR8}k>k0`btu0%Y(Sc*_DXiOb@R#Kb`P8JqR z4SZV+8YsR-7Nd8O=00Iak}y#`K3*m(LDW(WI7N~V&`fcj0#Pe9&|;|^?$^RS_yvkp zEG?@*m`|F7Vcn=Ju1`lub;V^EAoVJ)(g3MfaVrgxx)pZ_kaWeV3YRV}uPn|Zm6ri0 z@Mui3tU^uzQvg8QPDta#3K||QmMBDk+^(ih7(#G^W#c1qNj*!LT0}_21PC>YJ2V$v zd4P(nP$*;rI!g`q44z82tWgJ~5NWk9{jQVWe17lO$`v+bP!Pz_|Y^#$)g!2hfX^7MC6aHkSn4p%H^_h;F}9LwI0&@ zG>FaC1_-7%0m}?$Ee1**#UL`qml2oztb>F~22V+ch)M}&WEU;la8a=$7S5B2iMtlH zM?|DYB_sgqv<@mFuOw2GR|3$TUA2+`3XoJ6EhIrcOfD`@fWAch_(lh#3-2$`a)22s zPfgQ-s=Ww8-s^zJG z08gdpngV!qae0O)S0YB#V`DXp1ho=6a8Xb7fclXR$VsQ!!xz$SB<=^%H2`Fw=|#l_ z3Kf(dA8Fe3GI3t9NTQ}@tOgk>1EXLNkt1{+qUHY?FiT4f0_GVgDxTr3@^*4^k}#@B zoL2(1ACsI8zP+Q1qB{`-U)f8CC0*467!(DAGu>vBlZDBmG6o1ofpvjd3{>E+foc_J z(TXSOqG-hoJioUNi&`;*dZ~+o)|6f*qT^sofDQ}YZX(GD1*OY?{6%f5w#&~7(Sd3^ zw{t%&82V1Cf^<;30a{>exme6VEe2|#V0&ssc_Haz5B0%Gj1kR)bcki;iezyq(C&=T zffmWC04ggd{c%XV77<-hS{5y$!}pd1EqIs|;(fk`!)LG-l_67zB*ajVbX*6XCN2Zj z1eioOM1-LBppwMpq?8jfv=Sm^rMW56nDTNGpr{;8mr#%T`5K5$R})v4mO=sm!5!QU z{U=vkAS)L`jDr!D(m+K83NZHX*I_DeR6(2s?~GO77Zgjx^5O}^w=HT|8H5@| zskpRQ3cmthEG4)fhO798r8B*aI0}4Oqw$=|m#7f>`F|G~Ow1D*7`T%dIAnxMK~#h= zrA#c1CO^^*ir4DEqa-r9SdF-#gNPNClaU6CsLF%em3=L!qNio7DAbIw=M0St0nG3oZyQgANQHHC~7 z(6k^@$O;i90H1-~&})lC@*;&O7a@}C|DWx$D9@l>8bg|fe=ksJP7*;tlq*OaQitNP zFuS5du`mxJgG5|Fde&cRpqfEcuFLafk(#GKRIbA|xL99Ld_|#Hm#_a=HD3{6bQn!a zR0xRggdv^j%=x-t#sn2+rw)ev7OoD{M>Pt>p^=W7rHC#evM;=B?CGoo$N!XUSV*`XYqEX{{TO2K-Gsxhf!9P|>kooq;;{6qTs zisYqwGiJ=0tWqKrre`D~?4fs`k{Od0o0Kvf%tU~IwhGf~2nY%x$V2FoR)N9%Ts4c7 zOAW*PSHu%7FI7rqWs*KJI$iDbN(%~LKtpsv;%ZXMbJd{O@81c&g~D*3T6@+vZA^gNDgZs)VZ+9I(FN<|V#XAJ5RM`~Q8A^`Ck7{daP-BZ;5 z5(=fHQ5KfVs-T)qf=X355Ec+PqD~uv(qxt5azy>816OrZ(m5gnRrsFF{1L*3P$-hh zq`d=!5E`IUfU;sy`x-wAhB4tln3@oQ@B!WXbQrv$Y5#ZYhJ_cXRI>h(-mY#(!ZZ() z1RvUo$WoXdnp6uv@El*G)X2SE$9YQ<08vp^e6??0DK8UJ1rmqns$t|kVz&Q zp|R7@XfbK>8n}b03Z5zvjZdzS7w3V9X}UmCa!6pANwUZ?T_Gz|)AiK_GISTzpi~hg zmuf;!=qR*yXy_HC8gM0m=|a(iI}{EEOgKWKhmmryJL- zRV?F6144TD5mu>|rUu$*;XyiZ1;A;O7~iGKDx~>puTU+FW1%ss!Vl#S{sW5u0<9%A z7Yd80=NcGv{WMsT6Vl}c1o%&fSOw*SYZ$1SoJc`1fl)V6Hk}0)81~Vt>PF3=At&W) z2Ud0-9f9=%A+eqmj&vqzg+wBP3<6QVXnUZnQc@rh!Jz%C76$pJREDUlS_n{8it`XA z%e){Bq9vmXn!|MsXoyT9jFHMJ3X6oAnS^Prnn5V8rgPt(T1Y;8hZzA@6)TE_rSd`{ zh?}iNLsAqCy=);sz*(S^E`cyMHAYyjkit5H0RoJq5ooB6AM;8fbCk3X7hh=f$5sB)M2#DuOHsp?V#mkc{M28q^InhH3A_(}1r;RIV1Ff)r>WLN1=7PDGyLIL4XMtch+ug^ z;~kjMi7F+ADvoIQ7(5hho(_|=W$ba8qLqjRqfSAcP!>G(<;)v?CFNXK4z=uux-ldWPDd zSdhjTkGAPZBr(L$rkL3pfe`hWFatq@)Sm{!gcIlreFD_MDOQbC1*<~!y^4UkqvJF! zC!+4_z)65A5=rwV;&Pe|9!uz0Tc*fs-&$vA^axWkqV$`$L?JVrv*Z10dRSbRk+t}W zI#qd@dz7i8kskjH9drU1=%_kDTrLxq(bM;D=BQxMP1S?u2Y}HLUj;zRbtD&%DXO95 z9?*c9F+xbsV9D@8W}9jARnmpRd`Md8x$VORYT5$13Y4-?1)_xm-v|KEmNL^^vSb3# z@JD$Ffr!YItB@=Azj zEtaS}BqY(51_N{)KGaf{hfo)7SLIX;RC6Z#*{0mWijnqh0GTsM* zny-%0CAmfIyWdK+ZW;>_K$ip7>?G|1;dg2d8VekGIywsEVsVL~SE`oMmXW-GS(*{% zRumLKpF`MhnFa-GhTswnW*J~;r_drnO@NM?V#uFhiQYgFwGv2xhYaiqa%K@+#N2g3=UCq!5H`Vmaq8m!k zp@*KHUr}brVfU3rLmsRYz+wWSg7&CEs38cleT_qlVAZT$(o_Vp=z5h&CF6xMSO(6e z)91-*9l!-_AUt=iN^6m7v`y5JP3I_8qITV_Sj|M%tjmCaJlxO%)oi2%LYAj7l}>It z5I035PB?_57{eKXRqNCaQ8N;OWV3>5CJyU2FwN^Acb%=~qzOcoqGDLfL=`%m!Vv$E z;EvXQsOQ?Tn9v~Vg%$vHDIuVjS`Y->kYI6X1v~?mAnLUNf-oSx>Z*pBieb$!SDPzj z5(UkS2H`bYQ~_Ba6_!^>$r_mu9+Z#=B4{Q{>yEtgDp+I|=}+O_XidtiD9V4DS33z5o*cdWGldb*{` zW)SsGtG7%JOFTweLNfA@85mt*h%(h;AOtI5g;p19sl_rOhH#R=fhc<|Dyb~0G(QPe zEfD3T3r#I7C66@`^XQ}}Pd`9KC|;*^K{jq! z$IaS`gz0Sr>3t$77p&ejs9QOi_mU))+2*8f<7A2;7q@FO57ukg;(#Ju3=drN`Uc&> zJ765WQNu`E(Vnva%$JJA?Lu18CJm>W1a#_+%^gL;6g3+J7?LO=k~^wPS1ijl@DwG` zR+bRZh*IceKT+giMSeP+D#2syY8_MxjBgr5q(R~l6a>!>4Pg*UVsvaNC@WXATQfQR z4N#Ev13GhrT?8a(-T@$;2MC2U6BJ4}eas_UlsX7Y0b4a}QOQ7p5Y&a%6|kHJlZuMj4oE$T%koCVV`l^3H^(g6)CIB0=^N62D`K?}hnw2Y)U z!U&*&vj3m~Lo^|L0DJhY%6Y={GH@Pw@=0>u$2&BtNhwtls7cVAz}0jq)WJhtJQORG+gR=lrB$! zq(WX~SXQ)G!$ac@^b~Z+l(1jL#Grx4N5{5~X4_-b90UpUzB=?B_Fb8pLEUpxbU2`$ z%gQ@S#c_k0jjZ{=#sNCx#XH+WdxH^yIwHx`6*vstb4bHUdNwn^)tglp%S8&qh=uQ{ zxo9kGi9#^_({xG3FsaN?*GDxMv#O#d6EeMgnx>blN(N6%^a5{1sYqT@*>2`VwP<^Q zP)!4SsC5j=g8>Kjhqfy`KA>(Jr0_HqwCNu0p;9qCkwq(XM9LK%2cCEhvyhG|3>8TA zJE+zrlo!EqlKx&MkypPy77cK zxBYtED2+%4PgXub;7c8W1OXj}VDj~ws;D$qQUV(n4V+88)^e*!^y7N5j2=J@_;9Jl z7>F}8g;0Nh9oJD3{^6L$D>NQ>vY{5$gLwgDX6>4`({T+C%m*dfmEle&ft7j83Q6OHo*O4ekrj&+d*>y^zApuC}%nVp{*RzXd9X+#hIHR&a^^^hp05<#y zP{sy2iC}<_)j*iOlIL5+swe6CBY6P{n}+7SQM1xmFw972{i&n*^ZB!y@(?tbH0y%O zP;fB4rYncN<|NVPUQ!{%Fz~6L`^eQmGQWidP*@uV(gnIunW6|HlLq%ugDX`87KzD| z>vb(E$+5-N;`~$@%+!RiP12Xq#6%xjyk?=Sxm42GFSPf;KTvZiA;tDEYA3v~o zUs18ZuHsTPRBtVTY(9b~@&@jszR(U4LVD7PsO1JAsA(xkS2sg>A%p|Sj`XI^l)Dk_ zRWeacr}xceB`^>Ap{@xqMw%})05NnUfUaE2Oy~fFqI5JCL5P%>NeuHKYNd{$ghp0g z3@Z{sAT3suk$E-J+d7d?yj-qlHuh~*H->0g!jOzKaOF4v(H#fq6$md;-vTrJI7RZGn7z`%!MHnu*2& z$6y^F(up>7HbYG_)J)LxNCMCFM~6Eq{aTn_l0z2GI@)vBRm~?JoXU?)wFK!xHm{lHzC zTP)Ad%`;3&sW;k)4^PLUBcmX-t^rZ%)=&80_)@#2NcKIo6|lo57e*Mm&)Nf26@*K3 zN%TyC1wq(VN}i%nYjv7$GAL3%jH8A?cTm|*Zx{@MY|Ow05M@}CUDdk4H9}G}A>CZT zL;cm5JaX_#A2&*4HzaX%q6@3yIz9lyV1}G3DirIF7NxoQbOvTPq^l8d}5119Rd)>MW-e_$dR5rG@9;dIc&)C=s{l0vwqqbT)JD@~ZL zVuj}r+UO)qgItOT)Snv_mWy%=%G#^RP!~xkj02L`RFYWfr=HT{j-UGASz2DYT8LI5 zJk~*Yo)%Lb5?q|G{~Wduc6YTK!yl+x3>tXCbSkm9 zgIyd$)EpJeCXQ$7dqQlW6UL~DvUcl<{r*zvWYEA6vQp%6a&9MqBwJ3$KRVR3#+8N#72RItR91gRn=7IsoVvZn>6z{HOMK2QV6 z3Mn)^Z2VHiO3n@;+*^GM+mg#6`1mb24-qUqroi!x-1=6j9AO0sf9cp zHkj@~-eaihh}t$fGRfe0gJw|crqip47l9j5835EB(0T{J+8E1m>S-% zSA++~J+RSmpGD3wX#@N{F*nNJQy{?O(>(dI8`6sYv(yy-HOJi&3?m#r_+! zFgG1zw^T=rgRx&pb(aC|I3X?sQ`te7a=~s@fjGzQm!gU+Y!~H^B@;a`l{Y#1OH9?L zF2dHlL@+fT8+&6s9E`(`ZkSsY5)PYZq12eI*0h7o-eJPR{dl21KG--9Q&pIX%K3V7 zSg#pbp2^tUesVtfge?boM0XK5_=7DWIJ*f~4a)CTo#fdMTh3-aIOxkgirK&L!CNWr z{tmX-c#sHl2Z7TeaF9eQCd z&k|#o0S*=6e}>?3=?>V=UW83}@MyKTs2DG07vg7=^RQwCwo!s_F)j?mTc!@e*U@wz zM{FY0SNb!Dea3|qhIu_Ol~`7^67zz`xq|qNBs{?{2Ak($ZsC_Ru~B*iHvR^Go)~~% z;efz+Y-H`36&CN0O%kzbUWhw(u;)2~^mXiaNCB@FANC%W0P|d4yYqbXHP#rhUwX0J zp(UL3sV<6Nx^h*R1FxtQcY$K@Lh<^k>{`sy6$Ae8b{vJRz2g&bsl7YiIO!L<$vKj`61S7G*eOcjPNB8>-68y`jR zub`%^dq5@GV9MJWe)*I$e4M`a?~U1;2e1arX&%uRW8jhTye{_z5-#+`|Nq`aAJ$g& zt_D}8cm0Og_pPCAX5&839I$C9G&!h3XcR4o_n=o}YDUDOYPfQ+S*S=b0(Wx5WdYbS z9a~PtoIKYN{cz{m*vKvHlmJ%+G{!?q4#rN?UB%FH`Y}aNE82kBH=J15)Gh1>0nYHo zu5P>HF;2(U!6LyhY!MgK2U|cxEd=kTW7jnp^Wp@q*whm2qecPQa>%o!BcD;$px#rB2R zyfBGW`KHA_MVM0$O~$>>(3xDXq^ z3hR}yO22Tgx$OHsEZjBk-~nurC&p&OaYcaROsLW%Y&jj|t>S$d7}0|96^y^frin4p zU_bOzY?P>&QB*fNq|x0UyR_n{!k}={FkI{*@^r!+w#)yz`oEhM(uj7#^TX_ivc*+SofDyt-XnNIxej~7D zD03$a355Hh*lbX3%*jQID&iH}fB0c(QAP_k+eq3io{e9ibvW_pb1WGC9Ged3HDb|l z-X?uD^UT@XZy?rvY!OB9QCNBu;|CbSyZS#@{Q)4F&&D)Ra|;>W&@5*=SlxlqV{aNN*;e0BhLk5RW_#F z@Dy)kvhH$P^c7I6;a{?pYW{wGY$^%u|hxYK5nH>~%&g?E4M248S-MltVcd z(rc+CkNlr5)juGvF3o7BG%HviFh8!EIM&$P9Z%?ijjOO#2{sSKRtupsdt>3CKy2nc zGzr^7ze~g>-Z-QlM}=Zjc{JusjUGP=;8<-2-Q=roR7n}Wr%ZkQ@*0>9d7eEt*sZh}82I&@_LP8hDej*Y*IW9f} z9DT5?5D2xMgcIR`m+amM`6c>`i_X%A;$QuS4}!i$)_ zz?9{T#{<&J-UsvSiw49vU~_NCqsC({guHB0Bm6PG7vl=DgtwZN88xgz~JiRfnB_D!65LRzk{=F7aKgqnl6S*Z^!_w zA&fcXc!c%C81g|`SH}5jZEINU9b6Vk6dduy^c+TL2qV;XIF^9xdxW?Lx&{eop#e70 z0?YxCg$@`mA?YQANxZ)k$aa7_@xYSV5b4^v4tJu|*Gj0mVUPZR_sf=?uNL%K*&{5BfR{_r$y<*r>##`FEcTRa&er$}-G; zX2J4jZ)YzmD+_E`31cix<%vz8EowiD8=vpVFRN~ZXps-EEO;fUK9j#i@XEobP%AzR z<5n89NcK-`7LkZe*Xft&FlOKOU{JOvhCxHbX5XE}WxVHcp@|vhf#P^05o{}5%+sz zEPNf2JmN>t15eOFk1xFc&oBXzmpN^&QUqtrRe^jowq6r78uO>ao7F^;9dn><497Tt z{5OV9ljuWY1g3<65xzn0*u)QVVRuMMdSWbx++zu(n(~2|Bh>j@rMj<*WgM$kcZ|iJ z&1HpG1N0o-p~!>l|7pD8scKaj;18xmmbjh;5yZGkEP*yRC?3)gQeoW0{OwRn?)eT| zNa(=$vqbPxDjjR zfT29I3+u!FDXzo3g$gn-h4f1G#1~N&_Hx7c+kDWLjYoj*hQpjGy$FwSf)3Tg0gtG1 zb-)=tk{lokM>}9{0Ji=PubVQQ^y6DBZ-KtHb8Pl@OO^wUvWK1>2tCr#-vRz(BYV7Y zN**v+I|Mp9;7;~D$X)Dt0^H5s0q*VXF(k#D?6RDY=t(2IR`Qm0jyaG8Q#yzPgIq)O zb!>)cY0HA>5e(fi+uidI5|D84Xn+VOgLg;*4AoB!7xY_I6f_yK{m_WsLEgEQW&TM1l+_bQ~n@O&pTd+F=>gJQRJV--b@ zmq>!J@qS2YdkH*Gt?Zoyp}UI!_ZWnQc~F`R=VczLo`M)D%n1RLgem*zE|bGyvc3az zheI-GKNMH?=!H$J^~Im#u+Mw4f@~p9a_qgZu@ksgfX$t7MR4-yEm=wAS!toKIIBgfPt2eG@P~~?0v$z`7T{`eVK966o8X@CJ>oY)KOuZ^R?k%u z85)21!$$CvPQVQbFKCSyl7tjAGoNNV8v1WP&3X-Z&0i#o7_;W=$e^Nc1uCb01I zn&u%7kQzGRVJvzDXo?LZ16=jC@CLfH9wtzP7|InEgpz!#2<$lkdF1;OAMuGr+KaJc zkR_p{zrlk(4{bwJ5<3WWgjGkLX`p!^ticrm^n(ACE(do}Z1N2l2vtH2y3>?ICb;ZB zqz76N9`e-_2z7;5PYn-&Fc)Kc1x-mHB1;eOhrh-S(r)6ceBoVtIm1UbaXd0hH$fn*lASaqIRec*jUj)Ti;?t##*-7z2z`Lp-?UHls$10)q8y1%a$p(Jr?A6m zozUTQE=K1InsNqBNoF6~i@|q;z(TRfsbPf7I;fpI8c&}IM){ycdolcnX*@aEixByu z2<^q-hdUAZNIPnIIP4*W2W z#*-Sj#%Fin#}hQ3ocu%x!kEs*$p4qdlT)7XZTC7@wSFH68Wfv8(}`y4H3^2lhQ^cQ znGn}I;NMN-$x%#%#&m#hqw(a#rC~iW@?BvZquAtdB|>fFO>;5$VKkncq-3@cYS1eG z&7$$-?0Y?buI=kr19jOB0^*k(OwLGr-1O2 z(})NecfhZt@#Ju!q5qk7+Rv5nr_ybX3p7Nk;W)x*+D%g~rzN=)ahi*fWYLXCIz;1% zq)b|7PYo6Mz(`u*MkvYYGK6|`Q0Mn(JUK1Kj6>uvb20o*pq^rrLtzMh=ur1!@WW_4 zIr>Epx;g|5ej$w~XS@(3!#ZeHk32@>YXI|zUj#mdf~kB$MhIqHAg3ndtU8KJ$sWWy z`V1B-1#a!dXkSj_$+;>-KdmyvU!d{y2`cnni-b=MzZ~36u^)o|NA&onC1LPeX*@Zo z1oIUw5EU)JzAfw)85E zr%wPOeN!3!98V&joXhFBo>tR%(m*criS62p;s1rklS4KzI%$#ci7Bax7m-iS(;zez zUS!;P#MdtgL%D&bBu89ecOZF#P!ngR*ECf!pV5@$_zFT};YH4+KH~e5Tg}DDoCQrE z=It~k$sc?`X2&)58%^o^pLlb4s7bNOp%6IwuhBw2Fn)-l@#OdiLU+lV=3?**XgoR6 z(Q&47n#PmE8_cE^@|U?7{`WMV9Mpg(*?LZ4@V-98K5{0b;~14o}{m-1REWLw4sgdp^it=3>fe3Zf}C*@n+-FjgVq z4}*`U@np9>LT*~520xX?lTGyu&=m5fxfuD}-b6pW7al#-YjI598cE~n zjqPXv1i3zRjdayWAs-k@%RWR>NHc-B!z-1h)Dx+q%%dqs(Uhc>rgcEcShtU+%=l0I zGa6q?OIn~8f*JlEkg!s0vX>iXW8_V9G5Bm6Pxfsiv|Mj|V#;)g#*$;33tAYrBuU3L5?47_T zaR#$cMpH&#Lg_%`^}WyF*U)&f*%oFidSzzt&uKi_H;Yg;dDC1BzIQN@Pj? zIOtrAq%AaMCg2T61LzbGBks_6vRjm~os2C^M%I<_o?bmM+VlGn?ezXmtx?6uDiR`rO7(ar>kL*A`W61&BeCPm-!qKpC;JVV zlOW_Tb20TaipJAB3z0P-GU0WZ-wodL|Fg_L(L7{-AVNF!>XEU@Y5>tmcK#s*6DOUE z!HZ}-*~-V9c+?Uw_$@S^Y|%rAcwT!kcqNS|`|1qK#NZPK68&TY9gM_!_AzCyrSbjg zq?-%9R6>{34yXlO((_?$O6Ou^iU$#yWbYY59y(Zc&s<64$u={DM(E)gotJ1ly`hX= zCz(d;B*sB-YByIwzWMYwd6VxFSAQ1e=9Y^q)pz7;pVgm5>aV8qM-CBRf_T;RRls) zP!pPf2uSAuK zS=d!L1ZXZ&I}0bUW&m?*y(H==An2EK|AAbFEH8yW!=t4Ty0)UcD00L9u6ZduaQ{r3 zN6tz%e5T35Sy_WRK|TCPhk>*{G;`cITdoe40K1nvgAIi0#DBRe-W0$@h_4z!(Mg8! zoMrnrYtZiHcfj8%G4ehn*;SCMKLg}E2I_PI}K=t<4)qaoTUd5+@EXT4UK;|H0 z(0FP}eR6f&skqn}|LB=0%lPWBtAGYb9i#?Q1udw6q+KW=UJy5kQ)u5t!p&W<&&&J3 z$5#U3=9bi*yMo#{XbA<)O|{@bRJ)zMLc1e&3bg}6$zCh$W2_Z%nE>;|K$EYe$R^+} zs-=yKjs{Ckwp~2k(~G1sn)phAiHb`onm`#!q|A76gt)<;YqnmEKu-Y@JlztnIah$R zxEfpw4g{=GSN!~tk|98FP(XnHNx#8xTyH%>lYV^pO#~K%Z~c1mG`06v4%KJ(>3%km zqA5$cbxEsHnA)>2{A2iI#xC`@%p={@!XRZTlIDO)sB{EarvO$wxaoSh6HI|)^)wwm zx7t(M$q^;A%KJC{g7F9WB07w#5Sf-q=Kv?pd`-6i8LRk~xz=S5I#5Cu8$bkmS9!QeiGa|JJ zT%k82i>Jb?L+I(xrm`n=!1{*4phd@p+}mWL$tmrl)7hXl6U)?#CjJv?CEI!sEp0)k z{OXk0BzYX`6u!8VES&K>O&a@r)m`)Fz)2rMo0lX$wa;YnOxk;n*IFHt6yo#jmPB`< zq1=iab$8wZY^qIoUDYomDp$6DQ~y#|O45Ey90B^x+jIMF*rr8rB8*w|S-9;tn)UVY z0OFl2rf2_%gt$`Terp|D61-L=d^XfGipOdBUdCwh!Aawrib8yn@C?$lpO3$#~UA`?MlFm$Dk1uL_b-9dQyEUf2vi@be6_F+p znL@om$gkb)BA4y$8t}+GTkqyz+UX`JuhZ_X!dByLtGyN$7_uTse!RI4yxangZ65;w zZNU3oA@7PaK;$W!ke-JAo+;`_&H&JTNIz*QsA#)%8yHnzrIhZ%fnU^y6@c2h_6UG9 z-Z{NOiz|2%l+!&IjCi#d!!J_*(YU^yl~1m6=F6`=Xl)Z(Eg?p?qT_zG`p*rQUDy)n zmWa6?AVo7H2XFT6Z+TMJQK9SO@@w00fUZ}^ah9!2^a*`N1g!U^Q|kkez?=V<19iL6 z_ZR7e!jKrHqvg%WYHow1-MTR{Kb2=f6CBZo{TDiL8Vvt#UA3`(&-ZIR>5BlmS+b2= z1xe=u5pd!OJ2^zhYv*^qDHP5};Ze(`6jXrcD0@`SG|=6_&_EpLc&!%8v3ViQ1WbPo z5nXg{%nLv|ZiX6WXpr)-n|3_0o2#1@<-7zD%0DxK>{FZrYs$^K_Km2XybwU$`jMp~ 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

    QFl^>i76SnaY$a2F8#c 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 a0001xlhvJk0hE(co;?VD0002mBn}$v@#0tj diff --git a/x-demo.smp b/x-demo.smp new file mode 100755 index 0000000000000000000000000000000000000000..42aafa326bedafbb29b05c84803a43793888e844 GIT binary patch literal 32352 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 literal 0 HcmV?d00001 diff --git a/x_demo.exe b/x_demo.exe new file mode 100755 index 0000000000000000000000000000000000000000..75369abaeac5b4ea65201db3e49bc84a54e7aca8 GIT binary patch literal 58447 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 b<+f4w;SoHPfq$oq^=;Y`S;let_E_xSH)f$o literal 0 HcmV?d00001 diff --git a/x_demo.smp b/x_demo.smp new file mode 100755 index 0000000000000000000000000000000000000000..85d0078fdf9789f25069d319d66e24234ae2db19 GIT binary patch literal 15619 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

    hT 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 delta 56876 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 idownright]) mx = motion_Right,my = motion_Down;*/ - //if(!inpu.Keyboard[def->left] && !inpu.Keyboard[def->right]){ + if(!inpu.Keyboard[def->left] && !inpu.Keyboard[def->right]){ if((inpu.Keyboard[def->up] && !inpu.Keyboard[def->down] && player[playnum].d == 2))// || player[playnum].info.dir == 0) my = motion_Up; if((inpu.Keyboard[def->down] && !inpu.Keyboard[def->up] && player[playnum].d == 2))// || player[playnum].info.dir == 4) my = motion_Down; - //}else if(!inpu.Keyboard[def->up] && !inpu.Keyboard[def->down]){ + }else if(!inpu.Keyboard[def->up] && !inpu.Keyboard[def->down]){ if((inpu.Keyboard[def->left] && !inpu.Keyboard[def->right] && player[playnum].d == 2))// || player[playnum].info.dir == 1) mx = motion_Left; if((inpu.Keyboard[def->right] && !inpu.Keyboard[def->left] && player[playnum].d == 2))// || player[playnum].info.dir == 3) mx = motion_Right; - //} + } + //input from player if (inpu.Keyboard[def->button0]) buttons += 1 << 0; if (inpu.Keyboard[def->button1]) diff --git a/src/lib/bakapee.c b/src/lib/bakapee.c index 040db6f9..000ac84a 100755 --- a/src/lib/bakapee.c +++ b/src/lib/bakapee.c @@ -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 diff --git a/src/lib/bakapee.h b/src/lib/bakapee.h index 3e228a4a..df74c1bd 100755 --- a/src/lib/bakapee.h +++ b/src/lib/bakapee.h @@ -25,6 +25,8 @@ #include "src/lib/16_head.h" #include "src/lib/modex16.h" +//#include "src/lib/modex/modex.h" +#include "16/x/modex.h" #define TILEWH 16 #define QUADWH TILEWH/2 @@ -32,7 +34,10 @@ #define LGQ 32 #define HGQ 55 -//#define TILE +#define TILE + +//which lib? +#define MXLIB typedef struct { word gq; diff --git a/src/lib/modex/asm.bat b/src/lib/modex/asm.bat new file mode 100755 index 00000000..2e5785f9 --- /dev/null +++ b/src/lib/modex/asm.bat @@ -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 index 00000000..01182013 --- /dev/null +++ b/src/lib/modex/c_utils.asm @@ -0,0 +1,456 @@ +;======================================================= +;=== C_UTILS.ASM - Asm Utilities for C/C++ === +;======================================================= + + PAGE 255, 132 + + .MODEL Huge +; .286 + + ; ==== MACROS ==== + + ; macros to PUSH and POP multiple registers + +; PUSHx MACRO R1, R2, R3, R4;, R5, R6, R7, R8 +; IFNB +; push R1 ; Save R1 +; PUSHx R2, R3, R4;, R5, R6, R7, R8 +; ENDIF +; ENDM +; +; POPx MACRO R1, R2, R3, R4;, R5, R6, R7, R8 +; IFNB +; pop R1 ; Restore R1 +; POPx R2, R3, R4;, R5, R6, R7, R8 +; ENDIF +; ENDM + + ; Macro to Clear a Register to 0 + +CLR MACRO Register + xor Register, Register ; Set Register = 0 +ENDM + + ; Macros to Decrement Counter & Jump on Condition + +LOOPx MACRO Register, Destination + dec Register ; Counter-- + jnz Destination ; Jump if not 0 +ENDM + +LOOPjz MACRO Register, Destination + dec Register ; Counter-- + jz Destination ; Jump if 0 +ENDM + + + ; ==== General Constants ==== + + False EQU 0 + True EQU -1 + nil EQU 0 + + b EQU BYTE PTR + w EQU WORD PTR + d EQU DWORD PTR + o EQU OFFSET + f EQU FAR PTR + s EQU SHORT + ?x4 EQU + ?x3 EQU + ?x2 EQU + ?x1 EQU + + + .Data + + EVEN + +RND_Seed DW 7397, 29447, 802 +RND_Mult DW 179, 183, 182 +RND_ModV DW 32771, 32779, 32783 + +CR_LF DB 13, 10 ; the CRLF data + + .Code + +;=========================================== +;void far pascal dos_print (far char *Text) +;=========================================== +; +; - Print Text Directly to DOS console w/ CR/LF +; + + PUBLIC DOS_PRINT + +DP_Stack STRUC + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DD ? ; Caller + DP_Text DD ? ; Far Address of Text to print +DP_Stack ENDS + + +DOS_PRINT PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + mov BP, SP ; Set up Stack Frame + + lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor + + ; Compute Length of string + + CLR CX ; Length = 0 + mov SI, DX ; DS:SI = String data + +@@DP_Scan_it: + + cmp b [SI], 0 ; Null Byte found? + je @@DP_Got_Len ; exit loop if so + + inc CX ; Len++ + inc SI ; Point to next char + jmp s @@DP_Scan_it ; check again... + +@@DP_Got_len: + + jcxz @No_Print ; Don't Print if empty + + mov BX, 1 ; 1= DOS Handle for Display + mov AH, 40h ; Write Text Function + int 21h ; Call DOS to do it + +@No_Print: + mov AX, SEG DGROUP ; Restore DGroup + mov DS, AX + + mov DX, o CR_LF ; Get Addr of CR/LF pair + mov CX, 2 ; 2 Characters to Write + mov BX, 1 ; 1= DOS Handle for Display + + mov AH, 40h ; Write Text Function + int 21h ; Call DOS to do it + + cld ; Reset Direction Flag + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + ret 4 ; Exit & Clean Up Stack + +DOS_PRINT ENDP + + +;=========================================== +;void far pascal dos_prints (char far *Text) +;=========================================== +; +; Print Text Directly to DOS console +; without a trailing CR/LF +; + + PUBLIC DOS_PRINTS + +DOS_PRINTS PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + mov BP, SP ; Set up Stack Frame + + lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor + + ; Compute Length of string + + CLR CX ; Length = 0 + mov SI, DX ; DS:SI = String data + +@@DPS_Scan_it: + + cmp b [SI], 0 ; Null Byte found? + je @@DPS_Got_Len ; exit loop if so + + inc CX ; Len++ + inc SI ; Point to next char + jmp s @@DPS_Scan_it ; check again... + +@@DPS_Got_len: + + jcxz @DPS_Exit ; Don't Print if empty + + mov BX, 1 ; 1= DOS Handle for Display + mov AH, 40h ; Write Text Function + int 21h ; Call DOS to do it + +@DPS_Exit: + cld ; Reset Direction Flag + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + ret 2 ; Exit & Clean Up Stack + +DOS_PRINTS ENDP + + +;========================================= +;void far pascal set_video_mode (int Mode) +;========================================= +; +; Sets the Video Mode through the BIOS +; + + PUBLIC SET_VIDEO_MODE + +SVM_Stack STRUC + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DD ? ; Caller + SVM_Mode DB ?,? ; Desired Video Mode +SVM_Stack ENDS + + +SET_VIDEO_MODE PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + mov BP, SP ; Set up Stack Frame + + CLR AH ; Function 0 + mov AL, [BP].SVM_Mode ; Get Mode # + + int 10H ; Change Video Modes + +@SVM_Exit: + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + ret 2 ; Exit & Clean Up Stack + +SET_VIDEO_MODE ENDP + + +;=================================== +;int far pascal scan_keyboard (void) +;=================================== +; +; Function to scan keyboard for a pressed key +; + + PUBLIC SCAN_KEYBOARD + +SCAN_KEYBOARD PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + + mov AH, 01H ; Function #1 + INT 16H ; Call Keyboard Driver + JZ @SK_NO_KEY ; Exit if Zero flag set + + mov AH, 00H ; Remove Key from Buffer + INT 16H ; Get Keycode in AX + + OR AL, AL ; Low Byte Set (Ascii?) + JZ @SK_Exit ; if not, it's a F-Key + + CLR AH ; Clear ScanCode if Ascii + JMP s @SK_Exit ; Return Key in AX + +@SK_NO_KEY: + CLR AX ; Return Nil (no Keypress) + +@SK_Exit: + cld ; Reset Direction Flag + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + ret ; Exit & Clean Up Stack + +SCAN_KEYBOARD ENDP + + +;======================================== +;int far pascal random_int (int MaxValue) +;======================================== +; +; Returns a pseudo-random number in the range of (0.. MaxInt-1) +; + + + PUBLIC RANDOM_INT + +RI_Stack STRUC + DW ? ; BP + DD ? ; Caller + RI_MaxVal DW ? ; Maximum Value to Return + 1 +RI_Stack ENDS + + +RANDOM_INT PROC FAR + + push BP ; Preserve Important Registers + mov BP, SP ; Set up Stack Frame + + CLR BX ; BX is the data index + CLR CX ; CX is the accumulator + +REPT 3 + mov AX, RND_Seed[BX] ; load the initial seed + mul RND_Mult[BX] ; multiply it + div RND_ModV[BX] ; and obtain the Mod value + mov RND_Seed[BX], DX ; save that for the next time + + add CX, DX ; add it into the accumulator + inc BX + inc BX ; point to the next set of values +ENDM + + mov AX, CX ; AX = Random # + CLR DX ; DX = 0 + div [BP].RI_MaxVal ; DX = DX:AX / MAxVal Remainder + + mov AX, DX + + pop BP ; Restore BP + ret 2 ; back to BASIC with AX holding the result + +RANDOM_INT ENDP + + +;================================== +;void far pascal init_random (void) +;================================== +; +; Scrambles the psuedo-random number sequence +; (XOR's the seed value with the timer) +; + + PUBLIC INIT_RANDOM + +INIT_RANDOM PROC FAR + + CLR AX ; Segment = 0000 + mov ES, AX + mov AX, ES:[046Ch] ; Get Timer Lo Word + + xor RND_Seed, AX ; Scramble 1st Seed + + ret ; Exit & Clean Up Stack + +INIT_RANDOM ENDP + +;========================================= +;int far pascal int_sqr (int X, int Round) +;========================================= +; +; Returns the Integer Square Root of (X) +; Round allows the return value to be rounded to the +; nearest integer value by passing 0x80. Passing 0 +; return the Integer Portion only. The rounding amound is +; a number from 0 to 1 multiplied by 256, thus +; 0.5 * 0x100 = 0x80! +; + +ISQ_Stack STRUC + DW ?,? ; BP, DI + DD ? ; Caller + ISQ_Round DW ? ; Amount to Round Result * 256 + ISQ_X DW ? ; "X" +ISQ_Stack ENDS + + PUBLIC INT_SQR + +INT_SQR PROC FAR + + ;PUSHx BP, DI ; Save BP + push bp + push di + mov BP, SP ; Set up Stack Frame + + xor AX, AX ; {xor eax,eax} + xor DX, DX ; {xor edx,edx} + mov DI, [BP].ISQ_X ; {mov edi,x} + + mov CX, 16 ; {mov cx, 32} + +@ISQ_L: + + shl DI, 1 ; {shl edi,1} + rcl DX, 1 ; {rcl edx,1} + shl DI, 1 ; {shl edi,1} + rcl DX, 1 ; {rcl edx,1} + shl AX, 1 ; {shl eax,1} + mov BX, AX ; {mov ebx,eax} + shl BX, 1 ; {shl ebx,1} + inc BX ; {inc ebx} + cmp DX, BX ; {cmp edx,ebx} + jl @ISQ_S + + sub DX, BX ; {sub edx,ebx} + inc AX ; {inc eax} + +@ISQ_S: + loop @ISQ_L + + add ax, [BP].ISQ_Round ; {add eax,$00008000} + ; {*round* result in hi word: ie. +0.5} + shr ax, 1 ; {shr eax,16} {to ax (result)} + shr ax, 1 ; {shr eax,16} {to ax (result)} + shr ax, 1 ; {shr eax,16} {to ax (result)} + shr ax, 1 ; {shr eax,16} {to ax (result)} + shr ax, 1 ; {shr eax,16} {to ax (result)} + shr ax, 1 ; {shr eax,16} {to ax (result)} + shr ax, 1 ; {shr eax,16} {to ax (result)} + shr ax, 1 ; {shr eax,16} {to ax (result)} + + ;POPx DI, BP ; Restore Registers + pop di + pop bp + ret 4 ; Exit + +INT_SQR ENDP + +;================================= +;int far pascal timer_count (void) +;================================= +; +; Returns the current timer value as an integer/long integer +; + + PUBLIC TIMER_COUNT + +TIMER_COUNT PROC FAR + + CLR AX ; Segment = 0000 + mov ES, AX + mov AX, ES:[046Ch] ; Get Timer Lo Word + mov DX, ES:[046Eh] ; Get Timer Hi Word + ret ; Exit & Clean Up Stack + +TIMER_COUNT ENDP + + + END diff --git a/src/lib/modex/c_utils.h b/src/lib/modex/c_utils.h new file mode 100755 index 00000000..9be6ba2d --- /dev/null +++ b/src/lib/modex/c_utils.h @@ -0,0 +1,117 @@ + +#ifndef __C_UTILS_H +#define __C_UTILS_H + + + /* Misc Constants */ + +#define True -1 +#define False 0 +#define nil 0 + + /* Color Constants */ + +#define c_BLACK 0 +#define c_BLUE 1 +#define c_GREEN 2 +#define c_CYAN 3 +#define c_RED 4 +#define c_PURPLE 5 +#define c_BROWN 6 +#define c_WHITE 7 +#define c_GREY 8 +#define c_bBLUE 9 +#define c_bGREEN 10 +#define c_bCYAN 11 +#define c_bRED 12 +#define c_bPURPLE 13 +#define c_YELLOW 14 +#define c_bWHITE 15 +#define c_BRIGHT 16 + + +#define Ky_F1 0x3B00 +#define Ky_F2 0x3C00 +#define Ky_F3 0x3D00 +#define Ky_F4 0x3E00 +#define Ky_F5 0x3F00 +#define Ky_F6 0x4000 +#define Ky_F7 0x4100 +#define Ky_F8 0x4200 +#define Ky_F9 0x4300 +#define Ky_F10 0x4400 + +#define Ky_Up 0x4800 +#define Ky_Left 0x4B00 +#define Ky_Right 0x4D00 +#define Ky_Down 0x5000 +#define Ky_SUp 0xC800 +#define Ky_SLeft 0xCB00 +#define Ky_SRight 0xCD00 +#define Ky_SDown 0xD000 + +#define Ky_Home 0x4700 +#define Ky_End 0x4F00 +#define Ky_PgUp 0x4900 +#define Ky_PgDn 0x5100 +#define Ky_SHome 0xC700 +#define Ky_SEnd 0xCF00 +#define Ky_SPgUp 0xC900 +#define Ky_SPgDn 0xD100 + +#define Ky_Ins 0x5200 +#define Ky_Del 0x5300 +#define Ky_SIns 0xC200 +#define Ky_SDel 0xC300 + +#define Ky_Tab 0x0009 +#define Ky_RvsTab 0x8F00 +#define Ky_STab 0x8F00 + +#define Ky_BS 0x0008 +#define Ky_CR 0x000D +#define Ky_ESC 0x001B +#define Ky_Clr 0x007F + +#define Ky_Plus 0x002D +#define Ky_Minus 0x002B + +#define Ky_AltA 0x1E00 +#define Ky_AltB 0x3000 +#define Ky_AltC 0x2E00 +#define Ky_AltD 0x2000 +#define Ky_AltE 0x1200 +#define Ky_AltF 0x2100 +#define Ky_AltG 0x2200 +#define Ky_AltH 0x2300 +#define Ky_AltI 0x1700 +#define Ky_AltJ 0x2400 +#define Ky_AltK 0x2500 +#define Ky_AltL 0x2600 +#define Ky_AltM 0x3200 +#define Ky_AltN 0x3100 +#define Ky_AltO 0x1800 +#define Ky_AltP 0x1900 +#define Ky_AltQ 0x1000 +#define Ky_AltR 0x1300 +#define Ky_AltS 0x1F00 +#define Ky_AltT 0x1400 +#define Ky_AltU 0x1600 +#define Ky_AltV 0x2F00 +#define Ky_AltW 0x1100 +#define Ky_AltX 0x2D00 +#define Ky_AltY 0x1500 +#define Ky_AltZ 0x2C00 + + /* .ASM Functions From C_UTILS.ASM */ + +void far pascal dos_print (char far *Text); +void far pascal dos_prints (char far *Text); +void far pascal set_video_mode (int Mode); +int far pascal scan_keyboard (void); +int far pascal random_int (int MaxValue); +void far pascal init_random (void); +int far pascal int_sqr (int X, int Round); +int far pascal timer_count (void); + +#endif diff --git a/src/lib/modex/c_utils.lst b/src/lib/modex/c_utils.lst new file mode 100755 index 00000000..f9664ba0 --- /dev/null +++ b/src/lib/modex/c_utils.lst @@ -0,0 +1,597 @@ +Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18 +c_utils.asm Page 1 - 1 + + + ;======================================================= + ;=== C_UTILS.ASM - Asm Utilities for C/C++ === + ;======================================================= + + PAGE 255, 132 + + .MODEL Medium + .286 + + ; ==== MACROS ==== + + ; macros to PUSH and POP multiple registers + + PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8 + IFNB + push R1 ; Save R1 + PUSHx R2, R3, R4, R5, R6, R7, R8 + ENDIF + ENDM + + POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8 + IFNB + pop R1 ; Restore R1 + POPx R2, R3, R4, R5, R6, R7, R8 + ENDIF + ENDM + + ; Macro to Clear a Register to 0 + + CLR MACRO Register + xor Register, Register ; Set Register = 0 + ENDM + + ; Macros to Decrement Counter & Jump on Condition + + LOOPx MACRO Register, Destination + dec Register ; Counter-- + jnz Destination ; Jump if not 0 + ENDM + + LOOPjz MACRO Register, Destination + dec Register ; Counter-- + jz Destination ; Jump if 0 + ENDM + + + ; ==== General Constants ==== + + = 0000 False EQU 0 + =-0001 True EQU -1 + = 0000 nil EQU 0 + + = BYTE PTR b EQU BYTE PTR + = WORD PTR w EQU WORD PTR + = DWORD PTR d EQU DWORD PTR + = OFFSET o EQU OFFSET + = FAR PTR f EQU FAR PTR + = SHORT s EQU SHORT + = ?,?,?,? ?x4 EQU + = ?,?,? ?x3 EQU + + + 0000 .Data + + EVEN + + 0000 1CE5 7307 0322 RND_Seed DW 7397, 29447, 802 + 0006 00B3 00B7 00B6 RND_Mult DW 179, 183, 182 + 000C 8003 800B 800F RND_ModV DW 32771, 32779, 32783 + + 0012 0D 0A CR_LF DB 13, 10 ; the CRLF data + + 0000 .Code + + ;=========================================== + ;void far pascal dos_print (far char *Text) + ;=========================================== + ; + ; - Print Text Directly to DOS console w/ CR/LF + ; + + PUBLIC DOS_PRINT + + 0010 DP_Stack STRUC + 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP + 0000 + 0008 00000000 DD ? ; Caller + 000C 00000000 DP_Text DD ? ; Far Address of Text to print + DP_Stack ENDS + + + 0000 DOS_PRINT PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 0000 55 1 push BP ; Save R1 + 0001 1E 2 push DS ; Save R1 + 0002 56 3 push SI ; Save R1 + 0003 57 4 push DI ; Save R1 + 0004 8B EC mov BP, SP ; Set up Stack Frame + + 0006 C5 56 0C lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor + + ; Compute Length of string + + CLR CX ; Length = 0 + 0009 33 C9 1 xor CX, CX ; Set Register = 0 + 000B 8B F2 mov SI, DX ; DS:SI = String data + + 000D @@DP_Scan_it: + + 000D 80 3C 00 cmp b [SI], 0 ; Null Byte found? + 0010 74 04 je @@DP_Got_Len ; exit loop if so + + 0012 41 inc CX ; Len++ + 0013 46 inc SI ; Point to next char + 0014 EB F7 jmp s @@DP_Scan_it ; check again... + + 0016 @@DP_Got_len: + + 0016 E3 07 jcxz @No_Print ; Don't Print if empty + + 0018 BB 0001 mov BX, 1 ; 1= DOS Handle for Display + 001B B4 40 mov AH, 40h ; Write Text Function + 001D CD 21 int 21h ; Call DOS to do it + + 001F @No_Print: + 001F B8 ---- R mov AX, SEG DGROUP ; Restore DGroup + 0022 8E D8 mov DS, AX + + 0024 BA 0012 R mov DX, o CR_LF ; Get Addr of CR/LF pair + 0027 B9 0002 mov CX, 2 ; 2 Characters to Write + 002A BB 0001 mov BX, 1 ; 1= DOS Handle for Display + + 002D B4 40 mov AH, 40h ; Write Text Function + 002F CD 21 int 21h ; Call DOS to do it + + 0031 FC cld ; Reset Direction Flag + POPx DI, SI, DS, BP ; Restore Saved Registers + 0032 5F 1 pop DI ; Restore R1 + 0033 5E 2 pop SI ; Restore R1 + 0034 1F 3 pop DS ; Restore R1 + 0035 5D 4 pop BP ; Restore R1 + 0036 CA 0004 ret 4 ; Exit & Clean Up Stack + + 0039 DOS_PRINT ENDP + + + ;=========================================== + ;void far pascal dos_prints (char far *Text) + ;=========================================== + ; + ; Print Text Directly to DOS console + ; without a trailing CR/LF + ; + + PUBLIC DOS_PRINTS + + 0039 DOS_PRINTS PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 0039 55 1 push BP ; Save R1 + 003A 1E 2 push DS ; Save R1 + 003B 56 3 push SI ; Save R1 + 003C 57 4 push DI ; Save R1 + 003D 8B EC mov BP, SP ; Set up Stack Frame + + 003F C5 56 0C lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor + + ; Compute Length of string + + CLR CX ; Length = 0 + 0042 33 C9 1 xor CX, CX ; Set Register = 0 + 0044 8B F2 mov SI, DX ; DS:SI = String data + + 0046 @@DPS_Scan_it: + + 0046 80 3C 00 cmp b [SI], 0 ; Null Byte found? + 0049 74 04 je @@DPS_Got_Len ; exit loop if so + + 004B 41 inc CX ; Len++ + 004C 46 inc SI ; Point to next char + 004D EB F7 jmp s @@DPS_Scan_it ; check again... + + 004F @@DPS_Got_len: + + 004F E3 07 jcxz @DPS_Exit ; Don't Print if empty + + 0051 BB 0001 mov BX, 1 ; 1= DOS Handle for Display + 0054 B4 40 mov AH, 40h ; Write Text Function + 0056 CD 21 int 21h ; Call DOS to do it + + 0058 @DPS_Exit: + 0058 FC cld ; Reset Direction Flag + POPx DI, SI, DS, BP ; Restore Saved Registers + 0059 5F 1 pop DI ; Restore R1 + 005A 5E 2 pop SI ; Restore R1 + 005B 1F 3 pop DS ; Restore R1 + 005C 5D 4 pop BP ; Restore R1 + 005D CA 0002 ret 2 ; Exit & Clean Up Stack + + 0060 DOS_PRINTS ENDP + + + ;========================================= + ;void far pascal set_video_mode (int Mode) + ;========================================= + ; + ; Sets the Video Mode through the BIOS + ; + + PUBLIC SET_VIDEO_MODE + + 000E SVM_Stack STRUC + 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP + 0000 + 0008 00000000 DD ? ; Caller + 000C 00 00 SVM_Mode DB ?,? ; Desired Video Mode + SVM_Stack ENDS + + + 0060 SET_VIDEO_MODE PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 0060 55 1 push BP ; Save R1 + 0061 1E 2 push DS ; Save R1 + 0062 56 3 push SI ; Save R1 + 0063 57 4 push DI ; Save R1 + 0064 8B EC mov BP, SP ; Set up Stack Frame + + CLR AH ; Function 0 + 0066 32 E4 1 xor AH, AH ; Set Register = 0 + 0068 8A 46 0C mov AL, [BP].SVM_Mode ; Get Mode # + + 006B CD 10 int 10H ; Change Video Modes + + 006D @SVM_Exit: + POPx DI, SI, DS, BP ; Restore Saved Registers + 006D 5F 1 pop DI ; Restore R1 + 006E 5E 2 pop SI ; Restore R1 + 006F 1F 3 pop DS ; Restore R1 + 0070 5D 4 pop BP ; Restore R1 + 0071 CA 0002 ret 2 ; Exit & Clean Up Stack + + 0074 SET_VIDEO_MODE ENDP + + + ;=================================== + ;int far pascal scan_keyboard (void) + ;=================================== + ; + ; Function to scan keyboard for a pressed key + ; + + PUBLIC SCAN_KEYBOARD + + 0074 SCAN_KEYBOARD PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 0074 55 1 push BP ; Save R1 + Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18 +c_utils.asm Page 2 - 1 + + + 0075 1E 2 push DS ; Save R1 + 0076 56 3 push SI ; Save R1 + 0077 57 4 push DI ; Save R1 + + 0078 B4 01 mov AH, 01H ; Function #1 + 007A CD 16 INT 16H ; Call Keyboard Driver + 007C 74 0C JZ @SK_NO_KEY ; Exit if Zero flag set + + 007E B4 00 mov AH, 00H ; Remove Key from Buffer + 0080 CD 16 INT 16H ; Get Keycode in AX + + 0082 0A C0 OR AL, AL ; Low Byte Set (Ascii?) + 0084 74 06 JZ @SK_Exit ; if not, it's a F-Key + + CLR AH ; Clear ScanCode if Ascii + 0086 32 E4 1 xor AH, AH ; Set Register = 0 + 0088 EB 02 JMP s @SK_Exit ; Return Key in AX + + 008A @SK_NO_KEY: + CLR AX ; Return Nil (no Keypress) + 008A 33 C0 1 xor AX, AX ; Set Register = 0 + + 008C @SK_Exit: + 008C FC cld ; Reset Direction Flag + POPx DI, SI, DS, BP ; Restore Saved Registers + 008D 5F 1 pop DI ; Restore R1 + 008E 5E 2 pop SI ; Restore R1 + 008F 1F 3 pop DS ; Restore R1 + 0090 5D 4 pop BP ; Restore R1 + 0091 CB ret ; Exit & Clean Up Stack + + 0092 SCAN_KEYBOARD ENDP + + + ;======================================== + ;int far pascal random_int (int MaxValue) + ;======================================== + ; + ; Returns a pseudo-random number in the range of (0.. MaxInt-1) + ; + + + PUBLIC RANDOM_INT + + 0008 RI_Stack STRUC + 0000 0000 DW ? ; BP + 0002 00000000 DD ? ; Caller + 0006 0000 RI_MaxVal DW ? ; Maximum Value to Return + 1 + RI_Stack ENDS + + + 0092 RANDOM_INT PROC FAR + + 0092 55 push BP ; Preserve Important Registers + 0093 8B EC mov BP, SP ; Set up Stack Frame + + CLR BX ; BX is the data index + 0095 33 DB 1 xor BX, BX ; Set Register = 0 + CLR CX ; CX is the accumulator + 0097 33 C9 1 xor CX, CX ; Set Register = 0 + + REPT 3 + mov AX, RND_Seed[BX] ; load the initial seed + mul RND_Mult[BX] ; multiply it + div RND_ModV[BX] ; and obtain the Mod value + mov RND_Seed[BX], DX ; save that for the next time + + add CX, DX ; add it into the accumulator + inc BX + inc BX ; point to the next set of values + ENDM + 0099 8B 87 0000 R 1 mov AX, RND_Seed[BX] ; load the initial seed + 009D F7 A7 0006 R 1 mul RND_Mult[BX] ; multiply it + 00A1 F7 B7 000C R 1 div RND_ModV[BX] ; and obtain the Mod value + 00A5 89 97 0000 R 1 mov RND_Seed[BX], DX ; save that for the next time + 00A9 03 CA 1 add CX, DX ; add it into the accumulator + 00AB 43 1 inc BX + 00AC 43 1 inc BX ; point to the next set of values + 00AD 8B 87 0000 R 1 mov AX, RND_Seed[BX] ; load the initial seed + 00B1 F7 A7 0006 R 1 mul RND_Mult[BX] ; multiply it + 00B5 F7 B7 000C R 1 div RND_ModV[BX] ; and obtain the Mod value + 00B9 89 97 0000 R 1 mov RND_Seed[BX], DX ; save that for the next time + 00BD 03 CA 1 add CX, DX ; add it into the accumulator + 00BF 43 1 inc BX + 00C0 43 1 inc BX ; point to the next set of values + 00C1 8B 87 0000 R 1 mov AX, RND_Seed[BX] ; load the initial seed + 00C5 F7 A7 0006 R 1 mul RND_Mult[BX] ; multiply it + 00C9 F7 B7 000C R 1 div RND_ModV[BX] ; and obtain the Mod value + 00CD 89 97 0000 R 1 mov RND_Seed[BX], DX ; save that for the next time + 00D1 03 CA 1 add CX, DX ; add it into the accumulator + 00D3 43 1 inc BX + 00D4 43 1 inc BX ; point to the next set of values + + 00D5 8B C1 mov AX, CX ; AX = Random # + CLR DX ; DX = 0 + 00D7 33 D2 1 xor DX, DX ; Set Register = 0 + 00D9 F7 76 06 div [BP].RI_MaxVal ; DX = DX:AX / MAxVal Remainder + + 00DC 8B C2 mov AX, DX + + 00DE 5D pop BP ; Restore BP + 00DF CA 0002 ret 2 ; back to BASIC with AX holding the result + + 00E2 RANDOM_INT ENDP + + + ;================================== + ;void far pascal init_random (void) + ;================================== + ; + ; Scrambles the psuedo-random number sequence + ; (XOR's the seed value with the timer) + ; + + PUBLIC INIT_RANDOM + + 00E2 INIT_RANDOM PROC FAR + + CLR AX ; Segment = 0000 + 00E2 33 C0 1 xor AX, AX ; Set Register = 0 + 00E4 8E C0 mov ES, AX + 00E6 26: A1 046C mov AX, ES:[046Ch] ; Get Timer Lo Word + + 00EA 31 06 0000 R xor RND_Seed, AX ; Scramble 1st Seed + + 00EE CB ret ; Exit & Clean Up Stack + + 00EF INIT_RANDOM ENDP + + ;========================================= + ;int far pascal int_sqr (int X, int Round) + ;========================================= + ; + ; Returns the Integer Square Root of (X) + ; Round allows the return value to be rounded to the + ; nearest integer value by passing 0x80. Passing 0 + ; return the Integer Portion only. The rounding amound is + ; a number from 0 to 1 multiplied by 256, thus + ; 0.5 * 0x100 = 0x80! + ; + + 000C ISQ_Stack STRUC + 0000 0000 0000 DW ?,? ; BP, DI + 0004 00000000 DD ? ; Caller + 0008 0000 ISQ_Round DW ? ; Amount to Round Result * 256 + 000A 0000 ISQ_X DW ? ; "X" + ISQ_Stack ENDS + + PUBLIC INT_SQR + + 00EF INT_SQR PROC FAR + + PUSHx BP, DI ; Save BP + 00EF 55 1 push BP ; Save R1 + 00F0 57 2 push DI ; Save R1 + 00F1 8B EC mov BP, SP ; Set up Stack Frame + + 00F3 33 C0 xor AX, AX ; {xor eax,eax} + 00F5 33 D2 xor DX, DX ; {xor edx,edx} + 00F7 8B 7E 0A mov DI, [BP].ISQ_X ; {mov edi,x} + + 00FA B9 0010 mov CX, 16 ; {mov cx, 32} + + 00FD @ISQ_L: + + 00FD D1 E7 shl DI, 1 ; {shl edi,1} + 00FF D1 D2 rcl DX, 1 ; {rcl edx,1} + 0101 D1 E7 shl DI, 1 ; {shl edi,1} + 0103 D1 D2 rcl DX, 1 ; {rcl edx,1} + 0105 D1 E0 shl AX, 1 ; {shl eax,1} + 0107 8B D8 mov BX, AX ; {mov ebx,eax} + 0109 D1 E3 shl BX, 1 ; {shl ebx,1} + 010B 43 inc BX ; {inc ebx} + 010C 3B D3 cmp DX, BX ; {cmp edx,ebx} + 010E 7C 03 jl @ISQ_S + + 0110 2B D3 sub DX, BX ; {sub edx,ebx} + 0112 40 inc AX ; {inc eax} + + 0113 @ISQ_S: + 0113 E2 E8 loop @ISQ_L + + 0115 03 46 08 add ax, [BP].ISQ_Round ; {add eax,$00008000} + ; {*round* result in hi word: ie. +0 + .5} + 0118 C1 E8 08 shr ax, 8 ; {shr eax,16} {to ax (result)} + + POPx DI, BP ; Restore Registers + 011B 5F 1 pop DI ; Restore R1 + 011C 5D 2 pop BP ; Restore R1 + 011D CA 0004 ret 4 ; Exit + + 0120 INT_SQR ENDP + + ;================================= + ;int far pascal timer_count (void) + ;================================= + ; + ; Returns the current timer value as an integer/long integer + ; + + PUBLIC TIMER_COUNT + + 0120 TIMER_COUNT PROC FAR + + CLR AX ; Segment = 0000 + 0120 33 C0 1 xor AX, AX ; Set Register = 0 + 0122 8E C0 mov ES, AX + 0124 26: A1 046C mov AX, ES:[046Ch] ; Get Timer Lo Word + 0128 26: 8B 16 046E mov DX, ES:[046Eh] ; Get Timer Hi Word + 012D CB ret ; Exit & Clean Up Stack + + 012E TIMER_COUNT ENDP + + + END + Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18 +c_utils.asm Symbols 3 - 1 + + + + +Macros: + + N a m e Type + +CLR . . . . . . . . . . . . . . Proc +LOOPjz . . . . . . . . . . . . . Proc +LOOPx . . . . . . . . . . . . . Proc +POPx . . . . . . . . . . . . . . Proc +PUSHx . . . . . . . . . . . . . Proc + Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18 +c_utils.asm Symbols 4 - 1 + + + + +Structures and Unions: + + N a m e Size + Offset Type + +DP_Stack . . . . . . . . . . . . 0010 + DP_Text . . . . . . . . . . . 000C DWord +ISQ_Stack . . . . . . . . . . . 000C + ISQ_Round . . . . . . . . . . 0008 Word + ISQ_X . . . . . . . . . . . . 000A Word +RI_Stack . . . . . . . . . . . . 0008 + RI_MaxVal . . . . . . . . . . 0006 Word +SVM_Stack . . . . . . . . . . . 000E + SVM_Mode . . . . . . . . . . . 000C Byte + Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18 +c_utils.asm Symbols 5 - 1 + + + + +Segments and Groups: + + N a m e Size Length Align Combine Class + +C_UTILS_TEXT . . . . . . . . . . 16 Bit 012E Word Public 'CODE' +DGROUP . . . . . . . . . . . . . GROUP +_DATA . . . . . . . . . . . . . 16 Bit 0014 Word Public 'DATA' + Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18 +c_utils.asm Symbols 6 - 1 + + + + +Procedures, parameters and locals: + + N a m e Type Value Attr + +DOS_PRINTS . . . . . . . . . . . P Far 0039 C_UTILS_TEXT Length= 0027 Public +DOS_PRINT . . . . . . . . . . . P Far 0000 C_UTILS_TEXT Length= 0039 Public +INIT_RANDOM . . . . . . . . . . P Far 00E2 C_UTILS_TEXT Length= 000D Public +INT_SQR . . . . . . . . . . . . P Far 00EF C_UTILS_TEXT Length= 0031 Public +RANDOM_INT . . . . . . . . . . . P Far 0092 C_UTILS_TEXT Length= 0050 Public +SCAN_KEYBOARD . . . . . . . . . P Far 0074 C_UTILS_TEXT Length= 001E Public +SET_VIDEO_MODE . . . . . . . . . P Far 0060 C_UTILS_TEXT Length= 0014 Public +TIMER_COUNT . . . . . . . . . . P Far 0120 C_UTILS_TEXT Length= 000E Public + Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18 +c_utils.asm Symbols 7 - 1 + + + + +Symbols: + + N a m e Type Value Attr + +?x3 . . . . . . . . . . . . . . Text ?,?,? +?x4 . . . . . . . . . . . . . . Text ?,?,?,? +@@DPS_Got_len . . . . . . . . . L Near 004F C_UTILS_TEXT +@@DPS_Scan_it . . . . . . . . . L Near 0046 C_UTILS_TEXT +@@DP_Got_len . . . . . . . . . . L Near 0016 C_UTILS_TEXT +@@DP_Scan_it . . . . . . . . . . L Near 000D C_UTILS_TEXT +@CodeSize . . . . . . . . . . . Number 0001h +@DPS_Exit . . . . . . . . . . . L Near 0058 C_UTILS_TEXT +@DataSize . . . . . . . . . . . Number 0000h +@ISQ_L . . . . . . . . . . . . . L Near 00FD C_UTILS_TEXT +@ISQ_S . . . . . . . . . . . . . L Near 0113 C_UTILS_TEXT +@Interface . . . . . . . . . . . Number 0000h +@Model . . . . . . . . . . . . . Number 0004h +@No_Print . . . . . . . . . . . L Near 001F C_UTILS_TEXT +@SK_Exit . . . . . . . . . . . . L Near 008C C_UTILS_TEXT +@SK_NO_KEY . . . . . . . . . . . L Near 008A C_UTILS_TEXT +@SVM_Exit . . . . . . . . . . . L Near 006D C_UTILS_TEXT +@code . . . . . . . . . . . . . Text C_UTILS_TEXT +@data . . . . . . . . . . . . . Text DGROUP +@fardata? . . . . . . . . . . . Text FAR_BSS +@fardata . . . . . . . . . . . . Text FAR_DATA +@stack . . . . . . . . . . . . . Text DGROUP +CR_LF . . . . . . . . . . . . . Byte 0012 _DATA +False . . . . . . . . . . . . . Number 0000h +RND_ModV . . . . . . . . . . . . Word 000C _DATA +RND_Mult . . . . . . . . . . . . Word 0006 _DATA +RND_Seed . . . . . . . . . . . . Word 0000 _DATA +True . . . . . . . . . . . . . . Number -0001h +b . . . . . . . . . . . . . . . Text BYTE PTR +d . . . . . . . . . . . . . . . Text DWORD PTR +f . . . . . . . . . . . . . . . Text FAR PTR +nil . . . . . . . . . . . . . . Number 0000h +o . . . . . . . . . . . . . . . Text OFFSET +s . . . . . . . . . . . . . . . Text SHORT +w . . . . . . . . . . . . . . . Text WORD PTR + + 0 Warnings + 0 Errors diff --git a/src/lib/modex/c_utils.sbr b/src/lib/modex/c_utils.sbr new file mode 100755 index 0000000000000000000000000000000000000000..0301171bdd90f778ed3f244b37130f9388df7f0a GIT binary patch literal 1731 zcmZ8hU1(fY5dQAuK&p#UAC#&fKJ+1i$i~{%wn9$2yN#Fb?%mvb6JlMtU9-E%CfnU~ zf101hwzk#OG>vU+Qxyc!2N9n{@L3cD5qwebS;PmQL{UWW!I`<6G!~ZSyEEr}b7tn7 zf#VpY4i`@p2M@?E>mDuUymV$_FuA{&&g8tHn1VAIbvw0s`>9g<6zE0t(XKMmUJw<0 zHy?s-iluVL5`exDQx!objKacF3Q)yL8lNHdY z(+7JBZZH}JozmniXxuTJN{Wv@-hiJ^M?s}hMq&mu*DsS$~{0n-MBnhI>?z>CnI#*j%$*se|?lw^L;Am0jr`8vA;!PtUtas20*?Hi0*+i(!2Hh%{}P54 z_G#P|n2N?_722Je1Nq{j!*c#C+FFi3V9shrA1PormzFJYr&ErZQ7#snRblNA+d*;C z6T-HvU7lI$73~$+6c;V1EivB_IdG1j_Y7zZ<{aoN{XZ!7^WX&1Qo0MOv0S&_QE5Hw zm^9=@G|V+G0ZTGHjWd zH094>s_NnCv^9gq`OFt0J}$u|(Chr?lQ$-gku%FnC7^3dP43Vsqdz2BReRUM4r z&SY>OS3z^Vxw#t8%}BEo)hj%!GcZ>rq*MyiYe!nkJm^fWUJyos>YWht>1?8)m$MPs3x4WckJ5rSNp>pVkJ&l@Pnu910PcFYZ} z=06a?@BBdlx8ySgOm|rU=eI`yb$hznh;_vxm~+eqXi%#~18?D2sosvCf#gltN!GXq zJMWlTO@sHZ<$b%oe<#F2_sDL&1>fD0z= MaxOfs THEN Offset = Restart + IF Delay THEN + Delay = Delay - 1 + ELSE + LOAD.DACS SSEGADD(Pal1$) + Offset2, 20, 60, 0 + IF Offset2 = Offset2Max THEN Offset2Dir = -3 + IF Offset2 = Offset2Min THEN Offset2Dir = 3 + Offset2 = Offset2 + Offset2Dir + END IF + + LOOP UNTIL SCAN.KEYBOARD + + ERROR.OUT "DEMO OVER" + +REM $STATIC +SUB ERROR.OUT (Text$) + + SET.VIDEO.MODE 3 + + DOS.PRINT Text$ + + END + +END SUB + +SUB LOAD.FONT (FontFile$, FontNum) STATIC + + IF LEN(DIR$(FontFile$)) = 0 THEN ERROR.OUT "FILE NOT FOUND: " + FontFile$ + + OPEN FontFile$ FOR BINARY AS #1 + + SEEK #1, 1 + GET #1, , CharSet(FontNum) + + CLOSE #1 + +END SUB + +FUNCTION MakePal$ (Red, Green, Blue) STATIC + + MakePal$ = CHR$(Red) + CHR$(Green) + CHR$(Blue) + +END FUNCTION + +SUB PRINT.STRING (Text$, Xpos, Ypos, Colour) + + TPRINT.STR SSEG(Text$), SADD(Text$), LEN(Text$), Xpos * 8, Ypos * 8, Colour + +END SUB + diff --git a/src/lib/modex/demos/basic7/make-lib.bat b/src/lib/modex/demos/basic7/make-lib.bat new file mode 100755 index 00000000..fc0b3b5c --- /dev/null +++ b/src/lib/modex/demos/basic7/make-lib.bat @@ -0,0 +1,5 @@ +ECHO ... Building MODEX.QLB for BASIC PDS 7.1 +LIB MODEX -+MODEX,, +LIB MODEX -+UTILS,, +DEL MODEX.BAK +LINK /Q MODEX+UTILS, MODEX.QLB, NUL, C:\BC7\LIB\QBXQLB.LIB; diff --git a/src/lib/modex/demos/basic7/modex.bi b/src/lib/modex/demos/basic7/modex.bi new file mode 100755 index 00000000..6b1d7afe --- /dev/null +++ b/src/lib/modex/demos/basic7/modex.bi @@ -0,0 +1,63 @@ + + ' ===== SCREEN RESOLUTIONS ===== + +CONST Mode320x200 = 0, Mode320x400 = 1 +CONST Mode360x200 = 2, Mode360x400 = 3 +CONST Mode320x240 = 4, Mode320x480 = 5 +CONST Mode360x240 = 6, Mode360x480 = 7 + + ' ===== MODE X SETUP ROUTINES ===== + +DECLARE FUNCTION SET.VGA.MODEX% ALIAS "SET_VGA_MODEX" (BYVAL ModeType%, BYVAL MaxXpos%, BYVAL MaxYpos%, BYVAL Pages%) +DECLARE FUNCTION SET.MODEX% ALIAS "SET_MODEX" (BYVAL Mode%) + + ' ===== BASIC GRAPHICS PRIMITIVES ===== + +DECLARE SUB CLEAR.VGA.SCREEN ALIAS "CLEAR_VGA_SCREEN" (BYVAL ColorNum%) +DECLARE SUB SET.POINT ALIAS "SET_POINT" (BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorNum%) +DECLARE FUNCTION READ.POINT% ALIAS "READ_POINT" (BYVAL Xpos%, BYVAL Ypos%) +DECLARE SUB FILL.BLOCK ALIAS "FILL_BLOCK" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%) +DECLARE SUB DRAW.LINE ALIAS "DRAW_LINE" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%) + + ' ===== DAC COLOR REGISTER ROUTINES ===== + +DECLARE SUB SET.DAC.REGISTER ALIAS "SET_DAC_REGISTER" (BYVAL RegNo%, BYVAL Red%, BYVAL Green%, BYVAL Blue%) +DECLARE SUB GET.DAC.REGISTER ALIAS "GET_DAC_REGISTER" (BYVAL RegNo%, Red%, Green%, Blue%) +DECLARE SUB LOAD.DAC.REGISTERS ALIAS "LOAD_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%, BYVAL VSync%) +DECLARE SUB READ.DAC.REGISTERS ALIAS "READ_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%) + + + ' ===== PAGE FLIPPING AND SCROLLING ROUTINES ===== + +DECLARE SUB SET.ACTIVE.PAGE ALIAS "SET_ACTIVE_PAGE" (BYVAL PageNo%) +DECLARE FUNCTION GET.ACTIVE.PAGE% ALIAS "GET_ACTIVE_PAGE" +DECLARE SUB SET.DISPLAY.PAGE ALIAS "SET_DISPLAY_PAGE" (BYVAL PageNo%) +DECLARE FUNCTION GET.DISPLAY.PAGE% ALIAS "GET_DISPLAY_PAGE" +DECLARE SUB SET.WINDOW ALIAS "SET_WINDOW" (BYVAL DisplayPage%, BYVAL XOffset%, BYVAL YOffset%) +DECLARE FUNCTION GET.X.OFFSET% ALIAS "GET_X_OFFSET" () +DECLARE FUNCTION GET.Y.OFFSET% ALIAS "GET_Y_OFFSET" () +DECLARE SUB SYNC.DISPLAY ALIAS "SYNC_DISPLAY" + + ' ===== TEXT DISPLAY ROUTINES ===== + +DECLARE SUB GPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%) +DECLARE SUB TGPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%) +DECLARE SUB PRINT.STR ALIAS "PRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%) +DECLARE SUB TPRINT.STR ALIAS "TPRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%) +DECLARE SUB SET.DISPLAY.FONT ALIAS "SET_DISPLAY_FONT" (SEG FontData AS ANY, BYVAL FontNumber%) + + ' ===== BITMAP (SPRITE) DISPLAY ROUTINES ===== + +DECLARE SUB DRAW.BITMAP ALIAS "DRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%) +DECLARE SUB TDRAW.BITMAP ALIAS "TDRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%) + + ' ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES ===== + +DECLARE SUB COPY.PAGE ALIAS "COPY_PAGE" (BYVAL SourcePage%, BYVAL DestPage%) +DECLARE SUB COPY.BITMAP ALIAS "COPY_BITMAP" (BYVAL SourcePage%, BYVAL X1%, BYVAL Y1%, BYVAL X2%, BYVAL Y2%, BYVAL DestPage%, BYVAL DestX1%, BYVAL DestY1%) + + + + + + diff --git a/src/lib/modex/demos/basic7/modex.qlb b/src/lib/modex/demos/basic7/modex.qlb new file mode 100755 index 0000000000000000000000000000000000000000..70d22db30925923e0b60160c34b8aa97949e70d0 GIT binary patch literal 11141 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 literal 0 HcmV?d00001 diff --git a/src/lib/modex/demos/basic7/test6.bas b/src/lib/modex/demos/basic7/test6.bas new file mode 100755 index 00000000..220a67ba --- /dev/null +++ b/src/lib/modex/demos/basic7/test6.bas @@ -0,0 +1,562 @@ +'File: TEST6.BAS +'Descp.: A Mode "X" demonstration +'Author: Matt Pritchard +'Date: 14 April, 1993 +' +DECLARE SUB DEMO.RES (Mode%, Xmax%, Ymax%) +DECLARE SUB ERROR.OUT (Message$) +DECLARE FUNCTION GET.KEY% () +DECLARE SUB LOAD.SHAPES () +DECLARE SUB PAGE.DEMO () +DECLARE SUB PRINT.TEXT (Text$, Xpos%, Ypos%, ColorF%, ColorB%) +DECLARE SUB TPRINT.TEXT (Text$, Xpos%, Ypos%, ColorF%) +DEFINT A-Z + + +TYPE ShapeType + ImgData AS STRING * 512 + xWidth AS INTEGER + yWidth AS INTEGER +END TYPE + +TYPE Sprite + Xpos AS INTEGER + Ypos AS INTEGER + XDir AS INTEGER + YDir AS INTEGER + Shape AS INTEGER +END TYPE + + +CONST MaxShapes = 32 + + REM $INCLUDE: 'UTILS.BI' + REM $INCLUDE: 'MODEX.BI' + +DIM SHARED Img(32) AS ShapeType +COMMON SHARED Img() AS ShapeType + + + CALL INIT.RANDOM + + CALL LOAD.SHAPES + + CALL DEMO.RES(Mode320x200, 320, 200) + CALL DEMO.RES(Mode320x400, 320, 400) + + CALL DEMO.RES(Mode360x200, 360, 200) + CALL DEMO.RES(Mode360x400, 360, 400) + + CALL DEMO.RES(Mode320x240, 320, 240) + CALL DEMO.RES(Mode320x480, 320, 480) + + CALL DEMO.RES(Mode360x240, 360, 240) + CALL DEMO.RES(Mode360x480, 360, 480) + + CALL PAGE.DEMO + + SET.VIDEO.MODE 3 + DOS.PRINT "THIS MODE X DEMO IS FINISHED" + END + +SUB DEMO.RES (Mode, Xmax, Ymax) + + IF SET.MODEX%(Mode) = 0 THEN + ERROR.OUT "Unable to SET_MODEX" + STR$(Mode) + END IF + + XCenter = Xmax \ 2 + + X1 = 10 + Y1 = 10 + X2 = Xmax - 1 + Y2 = Ymax - 1 + + FOR Z = 0 TO 3 + Colr = 31 - Z * 2 + DRAW.LINE X1 + Z, Y1 + Z, X2 - Z, Y1 + Z, Colr + DRAW.LINE X1 + Z, Y1 + Z, X1 + Z, Y2 - Z, Colr + DRAW.LINE X1 + Z, Y2 - Z, X2 - Z, Y2 - Z, Colr + DRAW.LINE X2 - Z, Y1 + Z, X2 - Z, Y2 - Z, Colr + NEXT Z + + XChars = Xmax \ 10 + YChars = Ymax \ 10 + + FOR X = 0 TO XChars - 1 + TGPRINTC 48 + ((X + 1) MOD 10), X * 10 + 1, 1, 9 + ((X \ 8) MOD 7) + DRAW.LINE X * 10 + 9, 0, X * 10 + 9, 3, 15 + NEXT X + + FOR Y = 0 TO YChars - 1 + TGPRINTC 48 + ((Y + 1) MOD 10), 1, Y * 10 + 1, 9 + ((Y \ 10) MOD 7) + DRAW.LINE 0, Y * 10 + 9, 3, Y * 10 + 9, 15 + NEXT Y + + ' Draw Lines + + FOR X = 0 TO 63 + N = 15 + X * .75 + SET.DAC.REGISTER 64 + X, N, N, N + SET.DAC.REGISTER 128 + X, 0, N, N + + DRAW.LINE 103 - X, 60, 40 + X, 123, 64 + X + DRAW.LINE 40, 60 + X, 103, 123 - X, 128 + X + + NEXT X + TPRINT.TEXT "LINE TEST", 37, 130, c.BLUE + + Y = 60: Gap = 0 + FOR X = 0 TO 9 + FILL.BLOCK 120, Y, 120 + X, Y + Gap, 64 + X + FILL.BLOCK 140 - (15 - X), Y, 150 + X, Y + Gap, 230 + X + FILL.BLOCK 170 - (15 - X), Y, 170, Y + Gap, 128 + X + Y = Y + Gap + 2 + Gap = Gap + 1 + NEXT X + TPRINT.TEXT "FILL TEST", 110, 46, c.GREEN + + + FOR X = 190 TO 250 STEP 2 + FOR Y = 60 TO 122 STEP 2 + SET.POINT X, Y, X + Y + X + Y + NEXT Y + NEXT X + + TPRINT.TEXT "PIXEL TEST", 182, 130, c.RED + + FOR X = 190 TO 250 STEP 2 + FOR Y = 60 TO 122 STEP 2 + IF READ.POINT(X, Y) <> ((X + Y + X + Y) AND 255) THEN + ERROR.OUT "READ.PIXEL Failure" + END IF + NEXT Y + NEXT X + + + + Msg$ = " This is a MODE X demo " + PRINT.TEXT Msg$, XCenter - (LEN(Msg$) * 4), 20, c.bRED, c.BLUE + Msg$ = "Screen Resolution is by " + Xp = XCenter - (LEN(Msg$) * 4) + PRINT.TEXT Msg$, Xp, 30, c.bGREEN, c.BLACK + + PRINT.TEXT LTRIM$(STR$(Xmax)), Xp + 8 * 21, 30, c.bPURPLE, c.BLACK + PRINT.TEXT LTRIM$(STR$(Ymax)), Xp + 8 * 28, 30, c.bWHITE, c.BLACK + + FOR X = 0 TO 15 + SET.DAC.REGISTER 230 + X, 63 - X * 4, 0, 15 + X * 3 + DRAW.LINE 30 + X, Ymax - 6 - X, Xmax - 20 - X, Ymax - 6 - X, 230 + X + NEXT X + TPRINT.TEXT "Press to Continue", XCenter - (26 * 4), Ymax - 18, c.YELLOW + + X = GET.KEY% + IF X = KyESC THEN ERROR.OUT "ABORT" + +END SUB + +SUB ERROR.OUT (Message$) + + SET.VIDEO.MODE 3 + DOS.PRINT Message$ + END + +END SUB + +FUNCTION GET.KEY% + + DO + X = SCAN.KEYBOARD + LOOP UNTIL X + + GET.KEY% = X + +END FUNCTION + +SUB LOAD.SHAPES + +DIM Grid(1 TO 32, 1 TO 32) + + FOR Shape = 0 TO MaxShapes - 1 + + FOR Y = 1 TO 32 + FOR X = 1 TO 32 + Grid(X, Y) = 0 + NEXT X + NEXT Y + + Style = RANDOM.INT(6) + Colour = 1 + RANDOM.INT(15) + + SELECT CASE Style + + CASE 0: ' Solid Box + + DO + xWidth = 3 + RANDOM.INT(30) + yWidth = 3 + RANDOM.INT(30) + LOOP UNTIL ((xWidth * yWidth) <= 512) + + FOR Y = 1 TO yWidth + FOR X = 1 TO xWidth + Grid(X, Y) = Colour + NEXT X + NEXT Y + + CASE 1: ' Hollow Box + + DO + xWidth = 5 + RANDOM.INT(28) + yWidth = 5 + RANDOM.INT(28) + LOOP UNTIL ((xWidth * yWidth) <= 512) + + FOR Y = 1 TO yWidth + FOR X = 1 TO xWidth + Grid(X, Y) = Colour + NEXT X + NEXT Y + + HollowX = 1 + RANDOM.INT(xWidth \ 2 - 1) + HollowY = 1 + RANDOM.INT(yWidth \ 2 - 1) + + FOR Y = HollowY + 1 TO yWidth - HollowY + FOR X = HollowX + 1 TO xWidth - HollowX + Grid(X, Y) = nil + NEXT X + NEXT Y + + CASE 2: ' Solid Diamond + + xWidth = 3 + 2 * RANDOM.INT(10) + yWidth = xWidth + Centre = xWidth \ 2 + + FOR Y = 0 TO Centre + FOR X = 0 TO Y + Grid(Centre - X + 1, Y + 1) = Colour + Grid(Centre + X + 1, Y + 1) = Colour + Grid(Centre - X + 1, yWidth - Y) = Colour + Grid(Centre + X + 1, yWidth - Y) = Colour + NEXT X + NEXT Y + + + CASE 3: ' Hollow Diamond + + + xWidth = 3 + 2 * RANDOM.INT(10) + yWidth = xWidth + Centre = xWidth \ 2 + sWidth = RANDOM.INT(Centre) + + FOR Y = 0 TO Centre + FOR X = 0 TO Y + IF X + (Centre - Y) >= sWidth THEN + Grid(Centre - X + 1, Y + 1) = Colour + Grid(Centre + X + 1, Y + 1) = Colour + Grid(Centre - X + 1, yWidth - Y) = Colour + Grid(Centre + X + 1, yWidth - Y) = Colour + END IF + NEXT X + NEXT Y + + CASE 4: ' Ball + + xWidth = 7 + 2 * RANDOM.INT(8) + yWidth = xWidth + Centre = 1 + xWidth \ 2 + + FOR Y = 1 TO yWidth + FOR X = 1 TO xWidth + D = SQR(((Centre - X) * (Centre - X)) + ((Centre - Y) * (Centre - Y))) + IF D < Centre THEN Grid(X, Y) = 150 + Colour * 2 + D * 3 + NEXT X + NEXT Y + + CASE 5: ' Ball + + + xWidth = 7 + 2 * RANDOM.INT(8) + yWidth = xWidth + Centre = 1 + xWidth \ 2 + sWidth = RANDOM.INT(xWidth) + + FOR Y = 1 TO yWidth + FOR X = 1 TO xWidth + D = SQR(((Centre - X) * (Centre - X)) + ((Centre - Y) * (Centre - Y))) + IF D < Centre AND D >= sWidth THEN Grid(X, Y) = 150 + Colour * 2 + D * 3 + NEXT X + NEXT Y + + END SELECT + + Img(Shape).xWidth = xWidth + Img(Shape).yWidth = yWidth + + A$ = STRING$(xWidth * yWidth, nil) + + c = 1 + FOR Y = 1 TO yWidth + FOR X = 1 TO xWidth + MID$(A$, c, 1) = CHR$(Grid(X, Y)) + c = c + 1 + NEXT X + NEXT Y + + Img(Shape).ImgData = A$ + + + NEXT Shape + +END SUB + +SUB PAGE.DEMO + +CONST MaxSprites = 64 + +DIM Obj(MaxSprites) AS Sprite +DIM LastX(MaxSprites, 1), LastY(MaxSprites, 1) +DIM LastObjects(1) + + ScreenX = 360: ScreenY = 240 + + IF SET.VGA.MODEX%(Mode320x200, ScreenX, ScreenY, 3) = 0 THEN + ERROR.OUT "Unable to SET_VGA_MODEX" + STR$(Mode) + END IF + + SET.ACTIVE.PAGE 0 + + CLEAR.VGA.SCREEN c.BLACK + + PRINT.TEXT "This is a Test of the Following Functions:", 10, 9, c.bWHITE, c.BLACK + + DRAW.LINE 10, 18, 350, 18, c.YELLOW + PRINT.TEXT "SET_ACTIVE_PAGE", 10, 20, c.bBLUE, c.BLACK + PRINT.TEXT "SET_DISPLAY_PAGE", 10, 30, c.GREEN, c.BLACK + PRINT.TEXT "SET_DAC_REGISTER", 10, 40, c.RED, c.BLACK + PRINT.TEXT "CLEAR_VGA_SCREEN", 10, 50, c.CYAN, c.BLACK + + PRINT.TEXT "TDRAW_BITMAP", 10, 60, c.PURPLE, c.BLACK + PRINT.TEXT "COPY_PAGE", 10, 70, c.GREEN, c.BLACK + PRINT.TEXT "COPY_BITMAP", 10, 80, c.CYAN, c.BLACK + + PRINT.TEXT "GPRINTC", 10, 90, c.BLUE, c.BLACK + PRINT.TEXT "TGPRINTC", 10, 100, c.GREEN, c.BLACK + PRINT.TEXT "SET_WINDOW", 10, 110, c.RED, c.BLACK + + PRINT.TEXT "VIRTUAL SCREEN SIZES", 190, 20, c.bBLUE, c.BLACK + PRINT.TEXT " SMOOTH SCROLLING", 190, 30, c.GREEN, c.BLACK + PRINT.TEXT " SPRITE ANIMATION", 190, 40, c.CYAN, c.BLACK + PRINT.TEXT " PAGE FLIPPING", 190, 50, c.RED, c.BLACK + PRINT.TEXT " COLOR CYCLING", 190, 60, c.PURPLE, c.BLACK + + + FOR X = 0 TO 60 + SET.DAC.REGISTER 50 + X, 3 + X, 0, 60 - X + SET.DAC.REGISTER 150 + X, 3 + X, 0, 60 - X + NEXT X + + c = 0: DC = 1 + FOR X = 0 TO ScreenX \ 2 + DRAW.LINE ScreenX \ 2 - 1, ScreenY \ 4, X, ScreenY - 1, c + 50 + DRAW.LINE ScreenX \ 2, ScreenY \ 4, ScreenX - X - 1, ScreenY - 1, c + 50 + c = c + DC + IF c = 0 OR c = 60 THEN DC = -DC + NEXT X + + TPRINT.TEXT "Press to Continue", 72, 190, c.bWHITE + TPRINT.TEXT "< > = Faster < > = Slower", 72, 204, c.bGREEN + TPRINT.TEXT "< > = Fewer Shapes < > = More Shapes", 32, 218, c.bCYAN + + TGPRINTC 43, 80, 204, c.YELLOW + TGPRINTC 45, 200, 204, c.YELLOW + + TGPRINTC 25, 40, 218, c.YELLOW + TGPRINTC 24, 200, 218, c.YELLOW + + COPY.PAGE 0, 1 + COPY.PAGE 0, 2 + + FOR X = 1 TO MaxSprites + DO + Obj(X).XDir = RANDOM.INT(7) - 3 + Obj(X).YDir = RANDOM.INT(7) - 3 + LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0) + + Obj(X).Shape = X MOD MaxShapes + + SpriteX = Img(Obj(X).Shape).xWidth + SpriteY = Img(Obj(X).Shape).yWidth + + Obj(X).Xpos = 1 + RANDOM.INT(ScreenX - SpriteX - 2) + Obj(X).Ypos = 1 + RANDOM.INT(ScreenY - SpriteY - 2) + + LastX(X, 0) = Obj(X).Xpos + LastX(X, 1) = Obj(X).Xpos + LastY(X, 0) = Obj(X).Ypos + LastY(X, 1) = Obj(X).Ypos + NEXT X + + CurrentPage = 0 + + 'View Shift... + + ViewX = 0 + ViewY = 0 + ViewMax = 3 + ViewCnt = 0 + ViewXD = 1 + ViewYD = 1 + + SetColor = 3: SDir = 1 + PrevColor = 0: PDir = 1 + + VisObjects = MaxSprites \ 2 + LastObjects(0) = 0 + LastObjects(1) = 0 + +DRAW.LOOP: + + + SET.ACTIVE.PAGE CurrentPage + + ' Erase Old Images + + FOR X = 1 TO LastObjects(CurrentPage) + + X1 = LastX(X, CurrentPage) AND &HFFFC + Y1 = LastY(X, CurrentPage) + X2 = ((LastX(X, CurrentPage) + Img(Obj(X).Shape).xWidth)) OR 3 + Y2 = Y1 + Img(Obj(X).Shape).yWidth - 1 + + COPY.BITMAP 2, X1, Y1, X2, Y2, CurrentPage, X1, Y1 + + NEXT X + + ' Draw new images + + FOR X = 1 TO VisObjects + + SpriteX = Img(Obj(X).Shape).xWidth + SpriteY = Img(Obj(X).Shape).yWidth + + ' Move Sprite + +REDOX: + NewX = Obj(X).Xpos + Obj(X).XDir + IF NewX < 0 OR NewX + SpriteX > ScreenX THEN + Obj(X).XDir = -Obj(X).XDir + IF RANDOM.INT(20) = 1 THEN + DO + Obj(X).XDir = RANDOM.INT(7) - 3 + Obj(X).YDir = RANDOM.INT(7) - 3 + LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0) + GOTO REDOX + END IF + END IF + Obj(X).Xpos = Obj(X).Xpos + Obj(X).XDir + +REDOY: + NewY = Obj(X).Ypos + Obj(X).YDir + IF NewY < 0 OR NewY + SpriteY > ScreenY THEN + Obj(X).YDir = -Obj(X).YDir + IF RANDOM.INT(20) = 1 THEN + DO + Obj(X).XDir = RANDOM.INT(7) - 3 + Obj(X).YDir = RANDOM.INT(7) - 3 + LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0) + GOTO REDOY + END IF + END IF + Obj(X).Ypos = Obj(X).Ypos + Obj(X).YDir + + 'Draw Sprite + + TDRAW.BITMAP Img(Obj(X).Shape), Obj(X).Xpos, Obj(X).Ypos, SpriteX, SpriteY + + LastX(X, CurrentPage) = Obj(X).Xpos + LastY(X, CurrentPage) = Obj(X).Ypos + + NEXT X + + LastObjects(CurrentPage) = VisObjects + + ' Pan Screen Back & Forth + + ViewCnt = ViewCnt + 1 + IF ViewCnt >= ViewMax THEN + ViewX = ViewX + ViewXD + IF ViewX = 0 OR ViewX = 39 THEN ViewXD = -ViewXD + IF ViewXD < 0 THEN + ViewY = ViewY + ViewYD + IF ViewY = 0 OR ViewY = 39 THEN ViewYD = -ViewYD + END IF + + SET.WINDOW CurrentPage, ViewX, ViewY + + ViewCnt = 0 + ELSE + SET.DISPLAY.PAGE CurrentPage + END IF + + ' Cycle Colors + + SET.DAC.REGISTER 50 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor + SET.DAC.REGISTER 50 + SetColor, SetColor, 10, 63 - SetColor + + SET.DAC.REGISTER 150 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor + SET.DAC.REGISTER 150 + SetColor, 63, 63, SetColor + + SetColor = SetColor + SDir + IF SetColor = 60 OR SetColor = 0 THEN SDir = -SDir + + PrevColor = PrevColor + PDir + IF PrevColor = 60 OR PrevColor = 0 THEN PDir = -PDir + + CurrentPage = 1 - CurrentPage + + Code = SCAN.KEYBOARD + + IF Code = False THEN GOTO DRAW.LOOP + + IF Code = KyPlus THEN + IF ViewMax < 12 THEN ViewMax = ViewMax + 1 + GOTO DRAW.LOOP + END IF + + IF Code = KyMinus THEN + IF ViewMax > 1 THEN ViewMax = ViewMax - 1 + IF ViewCnt >= ViewMax THEN ViewCnt = 0 + GOTO DRAW.LOOP + END IF + + IF Code = KyUp THEN + IF VisObjects < MaxSprites THEN VisObjects = VisObjects + 1 + GOTO DRAW.LOOP + END IF + + IF Code = KyDown THEN + IF VisObjects > 1 THEN VisObjects = VisObjects - 1 + GOTO DRAW.LOOP + END IF + + +END SUB + +SUB PRINT.TEXT (Text$, Xpos, Ypos, ColorF, ColorB) + + IF LEN(Text$) = 0 THEN EXIT SUB + + PRINT.STR SSEG(Text$), SADD(Text$), LEN(Text$), Xpos, Ypos, ColorF, ColorB + + +END SUB + +SUB TPRINT.TEXT (Text$, Xpos, Ypos, ColorF) + + IF LEN(Text$) = 0 THEN EXIT SUB + + TPRINT.STR SSEG(Text$), SADD(Text$), LEN(Text$), Xpos, Ypos, ColorF + +END SUB + diff --git a/src/lib/modex/demos/basic7/uasm-bc7.bat b/src/lib/modex/demos/basic7/uasm-bc7.bat new file mode 100755 index 00000000..5ad67fb5 --- /dev/null +++ b/src/lib/modex/demos/basic7/uasm-bc7.bat @@ -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 index 00000000..811b8f8e --- /dev/null +++ b/src/lib/modex/demos/basic7/utils.asm @@ -0,0 +1,406 @@ +;======================================================= +;=== UTILS.ASM - Asm Utilities for QuickBasic/BC7 === +;======================================================= + + PAGE 255, 132 + + .MODEL Medium + .286 + + ; ==== MACROS ==== + + ; macros to PUSH and POP multiple registers + +PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8 + IFNB + push R1 ; Save R1 + PUSHx R2, R3, R4, R5, R6, R7, R8 + ENDIF +ENDM + +POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8 + IFNB + pop R1 ; Restore R1 + POPx R2, R3, R4, R5, R6, R7, R8 + ENDIF +ENDM + + ; Macro to Clear a Register to 0 + +CLR MACRO Register + xor Register, Register ; Set Register = 0 +ENDM + + ; Macros to Decrement Counter & Jump on Condition + +LOOPx MACRO Register, Destination + dec Register ; Counter-- + jnz Destination ; Jump if not 0 +ENDM + +LOOPjz MACRO Register, Destination + dec Register ; Counter-- + jz Destination ; Jump if 0 +ENDM + + + ; ==== General Constants ==== + + False EQU 0 + True EQU -1 + nil EQU 0 + + b EQU BYTE PTR + w EQU WORD PTR + d EQU DWORD PTR + o EQU OFFSET + f EQU FAR PTR + s EQU SHORT + ?x4 EQU + ?x3 EQU + + +IFDEF FARSTRINGS + + EXTRN stringaddress:far + EXTRN stringlength:far + +ENDIF + + + .Data + + EVEN + +RND_Seed DW 7397, 29447, 802 +RND_Mult DW 179, 183, 182 +RND_ModV DW 32771, 32779, 32783 + +CR_LF DB 13, 10 ; the CRLF data + + .Code + +;================= +;DOS_PRINT (Text$) +;================= +; +; Prints Text Directly to DOS console w/ CR/LF +; + + PUBLIC DOS_PRINT + +DP_Stack STRUC + DW ?x4 ; DI, SI, DS, BP + DD ? ; Caller + DP_Text DW ? ; Address of Text$ Descriptor +DP_Stack ENDS + + +DOS_PRINT PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + mov BP, SP ; Set up Stack Frame + + mov SI, [BP].DP_Text ; Get Addr of Text$ descriptor + +IFDEF FARSTRINGS + push SI ; Push Addr of BC7 Decriptor Ptr + call stringaddress ; Get Address + Len of string!!! + ; DX:AX = Addr CX = Len + mov DS, DX ; DS = DX = Segment of string + mov DX, AX ; DX = AX = Offset of String +ELSE + mov CX, [SI] ; put its length into CX + mov DX, [SI+02] ; now DS:DX points to the String +ENDIF + + jcxz @No_Print ; Don't Print if empty + + mov BX, 1 ; 1= DOS Handle for Display + mov AH, 40h ; Write Text Function + int 21h ; Call DOS to do it + +@No_Print: + mov AX, SEG DGROUP ; Restore DGroup + mov DS, AX + + mov DX, o CR_LF ; Get Addr of CR/LF pair + mov CX, 2 ; 2 Characters to Write + mov BX, 1 ; 1= DOS Handle for Display + + mov AH, 40h ; Write Text Function + int 21h ; Call DOS to do it + + cld ; Reset Direction Flag + POPx DI, SI, DS, BP ; Restore Saved Registers + ret 2 ; Exit & Clean Up Stack + +DOS_PRINT ENDP + + +;================== +;DOS_PRINTS (Text$) +;================== +; +; Print Text$ Directly to DOS console +; without a trailing CR/LF +; + + PUBLIC DOS_PRINTS + +DOS_PRINTS PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + mov BP, SP ; Set up Stack Frame + + mov SI, [BP].DP_Text ; Get Addr of Text$ descriptor + +IFDEF FARSTRINGS + push SI ; Push Addr of BC7 Decriptor Ptr + call stringaddress ; Get Address + Len of string!!! + ; DX:AX = Addr CX = Len + mov DS, DX ; DS = DX = Segment of string + mov DX, AX ; DX = AX = Offset of String +ELSE + mov CX, [SI] ; put its length into CX + mov DX, [SI+02] ; now DS:DX points to the String +ENDIF + + jcxz @DPS_Exit ; Don't Print if empty + + mov BX, 1 ; 1= DOS Handle for Display + mov AH, 40h ; Write Text Function + int 21h ; Call DOS to do it + +@DPS_Exit: + cld ; Reset Direction Flag + POPx DI, SI, DS, BP ; Restore Saved Registers + ret 2 ; Exit & Clean Up Stack + +DOS_PRINTS ENDP + + +;====================== +;SET_VIDEO_MODE (Mode%) +;====================== +; +; Sets the Video Mode through the BIOS +; + + PUBLIC SET_VIDEO_MODE + +SVM_Stack STRUC + DW ?x4 ; DI, SI, DS, BP + DD ? ; Caller + SVM_Mode DB ?,? ; Desired Video Mode +SVM_Stack ENDS + + +SET_VIDEO_MODE PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + mov BP, SP ; Set up Stack Frame + + CLR AH ; Function 0 + mov AL, [BP].SVM_Mode ; Get Mode # + + int 10H ; Change Video Modes + +@SVM_Exit: + POPx DI, SI, DS, BP ; Restore Saved Registers + ret 2 ; Exit & Clean Up Stack + +SET_VIDEO_MODE ENDP + + +;============== +;SCAN_KEYBOARD% +;============== +; +; Function to scan keyboard for a pressed key +; + + PUBLIC SCAN_KEYBOARD + +SCAN_KEYBOARD PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + + mov AH, 01H ; Function #1 + int 16H ; Call Keyboard Driver + jz @SK_NO_KEY ; Exit if Zero flag set + + mov AH, 00H ; Remove Key from Buffer + int 16H ; Get Keycode in AX + + or AL, AL ; Low Byte Set (Ascii?) + jz @SK_Exit ; if not, it's a F-Key + + CLR AH ; Clear ScanCode if Ascii + jmp s @SK_Exit ; Return Key in AX + +@SK_NO_KEY: + CLR AX ; Return Nil (no Keypress) + +@SK_Exit: + cld ; Reset Direction Flag + POPx DI, SI, DS, BP ; Restore Saved Registers + ret ; Exit & Clean Up Stack + +SCAN_KEYBOARD ENDP + + +;==================== +;RANDOM_INT (MaxInt%) +;==================== +; +; Returns a pseudo-random number in the range of (0.. MaxInt-1) +; + + + PUBLIC RANDOM_INT + +RI_Stack STRUC + DW ? ; BP + DD ? ; Caller + RI_MaxVal DW ? ; Maximum Value to Return + 1 +RI_Stack ENDS + + +RANDOM_INT PROC FAR + + push BP ; Preserve Important Registers + mov BP, SP ; Set up Stack Frame + + CLR BX ; BX is the data index + CLR CX ; CX is the accumulator + +REPT 3 + mov AX, RND_Seed[BX] ; load the initial seed + mul RND_Mult[BX] ; multiply it + div RND_ModV[BX] ; and obtain the Mod value + mov RND_Seed[BX], DX ; save that for the next time + + add CX, DX ; add it into the accumulator + inc BX + inc BX ; point to the next set of values +ENDM + + mov AX, CX ; AX = Random # + CLR DX ; DX = 0 + div [BP].RI_MaxVal ; DX = DX:AX / MAxVal Remainder + + mov AX, DX + + pop BP ; Restore BP + ret 2 ; back to BASIC with AX holding the result + +RANDOM_INT ENDP + + +;=========== +;INIT_RANDOM +;=========== +; +; Scrambles the psuedo-random number sequence +; (XOR's the seed value with the timer) +; + + PUBLIC INIT_RANDOM + +INIT_RANDOM PROC FAR + + clr AX ; Segment = 0000 + mov ES, AX + mov AX, ES:[046Ch] ; Get Timer Lo Word + + xor RND_Seed, AX ; Scramble 1st Seed + + ret ; Exit & Clean Up Stack + +INIT_RANDOM ENDP + + +;==================== +;INT_SQR (X%, Round%) +;==================== +; +; Returns the Integer Square Root of (X) +; Round allows the return value to be rounded to the +; nearest integer value by passing 0x80. Passing 0 +; return the Integer Portion only. The rounding amound is +; a number from 0 to 1 multiplied by 256, thus +; 0.5 * 0x100 = 0x80! +; + +ISQ_Stack STRUC + DW ?,? ; BP, DI + DD ? ; Caller + ISQ_Round DW ? ; Amount to Round Result * 256 + ISQ_X DW ? ; "X" +ISQ_Stack ENDS + + PUBLIC INT_SQR + +INT_SQR PROC FAR + + PUSHx BP, DI ; Save BP + mov BP, SP ; Set up Stack Frame + + xor AX, AX ; {xor eax,eax} + xor DX, DX ; {xor edx,edx} + mov DI, [BP].ISQ_X ; {mov edi,x} + + mov CX, 16 ; {mov cx, 32} + +@ISQ_L: + + shl DI, 1 ; {shl edi,1} + rcl DX, 1 ; {rcl edx,1} + shl DI, 1 ; {shl edi,1} + rcl DX, 1 ; {rcl edx,1} + shl AX, 1 ; {shl eax,1} + mov BX, AX ; {mov ebx,eax} + shl BX, 1 ; {shl ebx,1} + inc BX ; {inc ebx} + cmp DX, BX ; {cmp edx,ebx} + jl @ISQ_S + + sub DX, BX ; {sub edx,ebx} + inc AX ; {inc eax} + +@ISQ_S: + loop @ISQ_L + + add ax, [BP].ISQ_Round ; {add eax,$00008000} + ; {*round* result in hi word: ie. +0.5} + shr ax, 8 ; {shr eax,16} {to ax (result)} + + POPx DI, BP ; Restore Registers + ret 4 ; Exit + +INT_SQR ENDP + + +;============ +;TIMER_COUNT& +;============ +; +; Returns the current timer value as an integer/long integer +; + + + PUBLIC TIMER_COUNT + +TIMER_COUNT PROC FAR + + clr AX ; Segment = 0000 + mov ES, AX ; use ES to get at data + mov AX, ES:[046Ch] ; Get Timer Lo Word + mov DX, ES:[046Eh] ; Get Timer Hi Word + ret ; Exit & Return value in DX:AX + +TIMER_COUNT ENDP + + + END diff --git a/src/lib/modex/demos/basic7/utils.bi b/src/lib/modex/demos/basic7/utils.bi new file mode 100755 index 00000000..aeafeef4 --- /dev/null +++ b/src/lib/modex/demos/basic7/utils.bi @@ -0,0 +1,51 @@ + + ' Misc Constants + +CONST True = -1, False = 0, nil = 0 + + ' Keyboard Codes: Extended + +CONST KyF1 = &H3B00, KyF2 = &H3C00, KyF3 = &H3D00, KyF4 = &H3E00, KyF5 = &H3F00 +CONST KyF6 = &H4000, KyF7 = &H4100, KyF8 = &H4200, KyF9 = &H4300, KyF10 = &H4400 + +CONST KyUp = &H4800, KyLeft = &H4B00, KyRight = &H4D00, KyDown = &H5000 +CONST KySLeft = &HCB00, KySRight = &HCD00, KySUp = &HC800, KySDown = &HD000 + +CONST KyHome = &H4700, KyPgUp = &H4900, KyEnd = &H4F00, KyPgDn = &H5100 +CONST KySHome = &HC700, KySPgUp = &HC900, KySEnd = &HCF00, KySPgDn = &HD100 + +CONST KyIns = &H5200, KyDel = &H5300, KyRvsTab = &H8F00 +CONST KySIns = &HC200, KySDel = &HC300 + +CONST KyAltA = &H1E00, KyAltB = &H3000, KyAltC = &H2E00, KyAltD = &H2000 +CONST KyAltE = &H1200, KyAltF = &H2100, KyAltG = &H2200, KyAltH = &H2300 +CONST KyAltI = &H1700, KyAltJ = &H2400, KyAltK = &H2500, KyAltL = &H2600 +CONST KyAltM = &H3200, KyAltN = &H3100, KyAltO = &H1800, KyAltP = &H1900 +CONST KyAltQ = &H1000, KyAltR = &H1300, KyAltS = &H1F00, KyAltT = &H1400 +CONST KyAltU = &H1600, KyAltV = &H2F00, KyAltW = &H1100, KyAltX = &H2D00 +CONST KyAltY = &H1500, KyAltZ = &H2C00 + + ' Keyboard Codes: Ascii + +CONST KyBS = 8, KyTab = 9, KyCR = 13, KyESC = &H1B, KyClr = &H7F +CONST KyPlus = 45, KyMinus = 43 + + ' Color Constants + +CONST c.BLACK = 0, c.BLUE = 1, c.GREEN = 2, c.CYAN = 3 +CONST c.RED = 4, c.PURPLE = 5, c.BROWN = 6, c.WHITE = 7 +CONST c.GREY = 8, c.bBLUE = 9, c.bGREEN = 10, c.bCYAN = 11 +CONST c.bRED = 12, c.bPURPLE = 13, c.YELLOW = 14, c.bWHITE = 15 +CONST c.BRIGHT = 8 + + ' From UTILS.ASM + +DECLARE SUB DOS.PRINT ALIAS "DOS_PRINT" (Text$) +DECLARE SUB DOS.PRINTS ALIAS "DOS_PRINTS" (Text$) +DECLARE SUB SET.VIDEO.MODE ALIAS "SET_VIDEO_MODE" (BYVAL Mode%) +DECLARE FUNCTION SCAN.KEYBOARD% ALIAS "SCAN_KEYBOARD" +DECLARE FUNCTION RANDOM.INT ALIAS "RANDOM_INT" (BYVAL MaxInt%) +DECLARE SUB INIT.RANDOM ALIAS "INIT_RANDOM" +DECLARE FUNCTION TIMER.COUNT& ALIAS "TIMER_COUNT" +DECLARE FUNCTION INT.SQR ALIAS "INT_SQR" (BYVAL X%, BYVAL Round%) + diff --git a/src/lib/modex/demos/c/c_utils.asm b/src/lib/modex/demos/c/c_utils.asm new file mode 100755 index 00000000..01182013 --- /dev/null +++ b/src/lib/modex/demos/c/c_utils.asm @@ -0,0 +1,456 @@ +;======================================================= +;=== C_UTILS.ASM - Asm Utilities for C/C++ === +;======================================================= + + PAGE 255, 132 + + .MODEL Huge +; .286 + + ; ==== MACROS ==== + + ; macros to PUSH and POP multiple registers + +; PUSHx MACRO R1, R2, R3, R4;, R5, R6, R7, R8 +; IFNB +; push R1 ; Save R1 +; PUSHx R2, R3, R4;, R5, R6, R7, R8 +; ENDIF +; ENDM +; +; POPx MACRO R1, R2, R3, R4;, R5, R6, R7, R8 +; IFNB +; pop R1 ; Restore R1 +; POPx R2, R3, R4;, R5, R6, R7, R8 +; ENDIF +; ENDM + + ; Macro to Clear a Register to 0 + +CLR MACRO Register + xor Register, Register ; Set Register = 0 +ENDM + + ; Macros to Decrement Counter & Jump on Condition + +LOOPx MACRO Register, Destination + dec Register ; Counter-- + jnz Destination ; Jump if not 0 +ENDM + +LOOPjz MACRO Register, Destination + dec Register ; Counter-- + jz Destination ; Jump if 0 +ENDM + + + ; ==== General Constants ==== + + False EQU 0 + True EQU -1 + nil EQU 0 + + b EQU BYTE PTR + w EQU WORD PTR + d EQU DWORD PTR + o EQU OFFSET + f EQU FAR PTR + s EQU SHORT + ?x4 EQU + ?x3 EQU + ?x2 EQU + ?x1 EQU + + + .Data + + EVEN + +RND_Seed DW 7397, 29447, 802 +RND_Mult DW 179, 183, 182 +RND_ModV DW 32771, 32779, 32783 + +CR_LF DB 13, 10 ; the CRLF data + + .Code + +;=========================================== +;void far pascal dos_print (far char *Text) +;=========================================== +; +; - Print Text Directly to DOS console w/ CR/LF +; + + PUBLIC DOS_PRINT + +DP_Stack STRUC + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DD ? ; Caller + DP_Text DD ? ; Far Address of Text to print +DP_Stack ENDS + + +DOS_PRINT PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + mov BP, SP ; Set up Stack Frame + + lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor + + ; Compute Length of string + + CLR CX ; Length = 0 + mov SI, DX ; DS:SI = String data + +@@DP_Scan_it: + + cmp b [SI], 0 ; Null Byte found? + je @@DP_Got_Len ; exit loop if so + + inc CX ; Len++ + inc SI ; Point to next char + jmp s @@DP_Scan_it ; check again... + +@@DP_Got_len: + + jcxz @No_Print ; Don't Print if empty + + mov BX, 1 ; 1= DOS Handle for Display + mov AH, 40h ; Write Text Function + int 21h ; Call DOS to do it + +@No_Print: + mov AX, SEG DGROUP ; Restore DGroup + mov DS, AX + + mov DX, o CR_LF ; Get Addr of CR/LF pair + mov CX, 2 ; 2 Characters to Write + mov BX, 1 ; 1= DOS Handle for Display + + mov AH, 40h ; Write Text Function + int 21h ; Call DOS to do it + + cld ; Reset Direction Flag + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + ret 4 ; Exit & Clean Up Stack + +DOS_PRINT ENDP + + +;=========================================== +;void far pascal dos_prints (char far *Text) +;=========================================== +; +; Print Text Directly to DOS console +; without a trailing CR/LF +; + + PUBLIC DOS_PRINTS + +DOS_PRINTS PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + mov BP, SP ; Set up Stack Frame + + lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor + + ; Compute Length of string + + CLR CX ; Length = 0 + mov SI, DX ; DS:SI = String data + +@@DPS_Scan_it: + + cmp b [SI], 0 ; Null Byte found? + je @@DPS_Got_Len ; exit loop if so + + inc CX ; Len++ + inc SI ; Point to next char + jmp s @@DPS_Scan_it ; check again... + +@@DPS_Got_len: + + jcxz @DPS_Exit ; Don't Print if empty + + mov BX, 1 ; 1= DOS Handle for Display + mov AH, 40h ; Write Text Function + int 21h ; Call DOS to do it + +@DPS_Exit: + cld ; Reset Direction Flag + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + ret 2 ; Exit & Clean Up Stack + +DOS_PRINTS ENDP + + +;========================================= +;void far pascal set_video_mode (int Mode) +;========================================= +; +; Sets the Video Mode through the BIOS +; + + PUBLIC SET_VIDEO_MODE + +SVM_Stack STRUC + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DD ? ; Caller + SVM_Mode DB ?,? ; Desired Video Mode +SVM_Stack ENDS + + +SET_VIDEO_MODE PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + mov BP, SP ; Set up Stack Frame + + CLR AH ; Function 0 + mov AL, [BP].SVM_Mode ; Get Mode # + + int 10H ; Change Video Modes + +@SVM_Exit: + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + ret 2 ; Exit & Clean Up Stack + +SET_VIDEO_MODE ENDP + + +;=================================== +;int far pascal scan_keyboard (void) +;=================================== +; +; Function to scan keyboard for a pressed key +; + + PUBLIC SCAN_KEYBOARD + +SCAN_KEYBOARD PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + + mov AH, 01H ; Function #1 + INT 16H ; Call Keyboard Driver + JZ @SK_NO_KEY ; Exit if Zero flag set + + mov AH, 00H ; Remove Key from Buffer + INT 16H ; Get Keycode in AX + + OR AL, AL ; Low Byte Set (Ascii?) + JZ @SK_Exit ; if not, it's a F-Key + + CLR AH ; Clear ScanCode if Ascii + JMP s @SK_Exit ; Return Key in AX + +@SK_NO_KEY: + CLR AX ; Return Nil (no Keypress) + +@SK_Exit: + cld ; Reset Direction Flag + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + ret ; Exit & Clean Up Stack + +SCAN_KEYBOARD ENDP + + +;======================================== +;int far pascal random_int (int MaxValue) +;======================================== +; +; Returns a pseudo-random number in the range of (0.. MaxInt-1) +; + + + PUBLIC RANDOM_INT + +RI_Stack STRUC + DW ? ; BP + DD ? ; Caller + RI_MaxVal DW ? ; Maximum Value to Return + 1 +RI_Stack ENDS + + +RANDOM_INT PROC FAR + + push BP ; Preserve Important Registers + mov BP, SP ; Set up Stack Frame + + CLR BX ; BX is the data index + CLR CX ; CX is the accumulator + +REPT 3 + mov AX, RND_Seed[BX] ; load the initial seed + mul RND_Mult[BX] ; multiply it + div RND_ModV[BX] ; and obtain the Mod value + mov RND_Seed[BX], DX ; save that for the next time + + add CX, DX ; add it into the accumulator + inc BX + inc BX ; point to the next set of values +ENDM + + mov AX, CX ; AX = Random # + CLR DX ; DX = 0 + div [BP].RI_MaxVal ; DX = DX:AX / MAxVal Remainder + + mov AX, DX + + pop BP ; Restore BP + ret 2 ; back to BASIC with AX holding the result + +RANDOM_INT ENDP + + +;================================== +;void far pascal init_random (void) +;================================== +; +; Scrambles the psuedo-random number sequence +; (XOR's the seed value with the timer) +; + + PUBLIC INIT_RANDOM + +INIT_RANDOM PROC FAR + + CLR AX ; Segment = 0000 + mov ES, AX + mov AX, ES:[046Ch] ; Get Timer Lo Word + + xor RND_Seed, AX ; Scramble 1st Seed + + ret ; Exit & Clean Up Stack + +INIT_RANDOM ENDP + +;========================================= +;int far pascal int_sqr (int X, int Round) +;========================================= +; +; Returns the Integer Square Root of (X) +; Round allows the return value to be rounded to the +; nearest integer value by passing 0x80. Passing 0 +; return the Integer Portion only. The rounding amound is +; a number from 0 to 1 multiplied by 256, thus +; 0.5 * 0x100 = 0x80! +; + +ISQ_Stack STRUC + DW ?,? ; BP, DI + DD ? ; Caller + ISQ_Round DW ? ; Amount to Round Result * 256 + ISQ_X DW ? ; "X" +ISQ_Stack ENDS + + PUBLIC INT_SQR + +INT_SQR PROC FAR + + ;PUSHx BP, DI ; Save BP + push bp + push di + mov BP, SP ; Set up Stack Frame + + xor AX, AX ; {xor eax,eax} + xor DX, DX ; {xor edx,edx} + mov DI, [BP].ISQ_X ; {mov edi,x} + + mov CX, 16 ; {mov cx, 32} + +@ISQ_L: + + shl DI, 1 ; {shl edi,1} + rcl DX, 1 ; {rcl edx,1} + shl DI, 1 ; {shl edi,1} + rcl DX, 1 ; {rcl edx,1} + shl AX, 1 ; {shl eax,1} + mov BX, AX ; {mov ebx,eax} + shl BX, 1 ; {shl ebx,1} + inc BX ; {inc ebx} + cmp DX, BX ; {cmp edx,ebx} + jl @ISQ_S + + sub DX, BX ; {sub edx,ebx} + inc AX ; {inc eax} + +@ISQ_S: + loop @ISQ_L + + add ax, [BP].ISQ_Round ; {add eax,$00008000} + ; {*round* result in hi word: ie. +0.5} + shr ax, 1 ; {shr eax,16} {to ax (result)} + shr ax, 1 ; {shr eax,16} {to ax (result)} + shr ax, 1 ; {shr eax,16} {to ax (result)} + shr ax, 1 ; {shr eax,16} {to ax (result)} + shr ax, 1 ; {shr eax,16} {to ax (result)} + shr ax, 1 ; {shr eax,16} {to ax (result)} + shr ax, 1 ; {shr eax,16} {to ax (result)} + shr ax, 1 ; {shr eax,16} {to ax (result)} + + ;POPx DI, BP ; Restore Registers + pop di + pop bp + ret 4 ; Exit + +INT_SQR ENDP + +;================================= +;int far pascal timer_count (void) +;================================= +; +; Returns the current timer value as an integer/long integer +; + + PUBLIC TIMER_COUNT + +TIMER_COUNT PROC FAR + + CLR AX ; Segment = 0000 + mov ES, AX + mov AX, ES:[046Ch] ; Get Timer Lo Word + mov DX, ES:[046Eh] ; Get Timer Hi Word + ret ; Exit & Clean Up Stack + +TIMER_COUNT ENDP + + + END diff --git a/src/lib/modex/demos/c/c_utils.h b/src/lib/modex/demos/c/c_utils.h new file mode 100755 index 00000000..9be6ba2d --- /dev/null +++ b/src/lib/modex/demos/c/c_utils.h @@ -0,0 +1,117 @@ + +#ifndef __C_UTILS_H +#define __C_UTILS_H + + + /* Misc Constants */ + +#define True -1 +#define False 0 +#define nil 0 + + /* Color Constants */ + +#define c_BLACK 0 +#define c_BLUE 1 +#define c_GREEN 2 +#define c_CYAN 3 +#define c_RED 4 +#define c_PURPLE 5 +#define c_BROWN 6 +#define c_WHITE 7 +#define c_GREY 8 +#define c_bBLUE 9 +#define c_bGREEN 10 +#define c_bCYAN 11 +#define c_bRED 12 +#define c_bPURPLE 13 +#define c_YELLOW 14 +#define c_bWHITE 15 +#define c_BRIGHT 16 + + +#define Ky_F1 0x3B00 +#define Ky_F2 0x3C00 +#define Ky_F3 0x3D00 +#define Ky_F4 0x3E00 +#define Ky_F5 0x3F00 +#define Ky_F6 0x4000 +#define Ky_F7 0x4100 +#define Ky_F8 0x4200 +#define Ky_F9 0x4300 +#define Ky_F10 0x4400 + +#define Ky_Up 0x4800 +#define Ky_Left 0x4B00 +#define Ky_Right 0x4D00 +#define Ky_Down 0x5000 +#define Ky_SUp 0xC800 +#define Ky_SLeft 0xCB00 +#define Ky_SRight 0xCD00 +#define Ky_SDown 0xD000 + +#define Ky_Home 0x4700 +#define Ky_End 0x4F00 +#define Ky_PgUp 0x4900 +#define Ky_PgDn 0x5100 +#define Ky_SHome 0xC700 +#define Ky_SEnd 0xCF00 +#define Ky_SPgUp 0xC900 +#define Ky_SPgDn 0xD100 + +#define Ky_Ins 0x5200 +#define Ky_Del 0x5300 +#define Ky_SIns 0xC200 +#define Ky_SDel 0xC300 + +#define Ky_Tab 0x0009 +#define Ky_RvsTab 0x8F00 +#define Ky_STab 0x8F00 + +#define Ky_BS 0x0008 +#define Ky_CR 0x000D +#define Ky_ESC 0x001B +#define Ky_Clr 0x007F + +#define Ky_Plus 0x002D +#define Ky_Minus 0x002B + +#define Ky_AltA 0x1E00 +#define Ky_AltB 0x3000 +#define Ky_AltC 0x2E00 +#define Ky_AltD 0x2000 +#define Ky_AltE 0x1200 +#define Ky_AltF 0x2100 +#define Ky_AltG 0x2200 +#define Ky_AltH 0x2300 +#define Ky_AltI 0x1700 +#define Ky_AltJ 0x2400 +#define Ky_AltK 0x2500 +#define Ky_AltL 0x2600 +#define Ky_AltM 0x3200 +#define Ky_AltN 0x3100 +#define Ky_AltO 0x1800 +#define Ky_AltP 0x1900 +#define Ky_AltQ 0x1000 +#define Ky_AltR 0x1300 +#define Ky_AltS 0x1F00 +#define Ky_AltT 0x1400 +#define Ky_AltU 0x1600 +#define Ky_AltV 0x2F00 +#define Ky_AltW 0x1100 +#define Ky_AltX 0x2D00 +#define Ky_AltY 0x1500 +#define Ky_AltZ 0x2C00 + + /* .ASM Functions From C_UTILS.ASM */ + +void far pascal dos_print (char far *Text); +void far pascal dos_prints (char far *Text); +void far pascal set_video_mode (int Mode); +int far pascal scan_keyboard (void); +int far pascal random_int (int MaxValue); +void far pascal init_random (void); +int far pascal int_sqr (int X, int Round); +int far pascal timer_count (void); + +#endif diff --git a/src/lib/modex/demos/c/c_utils.lst b/src/lib/modex/demos/c/c_utils.lst new file mode 100755 index 00000000..f9664ba0 --- /dev/null +++ b/src/lib/modex/demos/c/c_utils.lst @@ -0,0 +1,597 @@ +Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18 +c_utils.asm Page 1 - 1 + + + ;======================================================= + ;=== C_UTILS.ASM - Asm Utilities for C/C++ === + ;======================================================= + + PAGE 255, 132 + + .MODEL Medium + .286 + + ; ==== MACROS ==== + + ; macros to PUSH and POP multiple registers + + PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8 + IFNB + push R1 ; Save R1 + PUSHx R2, R3, R4, R5, R6, R7, R8 + ENDIF + ENDM + + POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8 + IFNB + pop R1 ; Restore R1 + POPx R2, R3, R4, R5, R6, R7, R8 + ENDIF + ENDM + + ; Macro to Clear a Register to 0 + + CLR MACRO Register + xor Register, Register ; Set Register = 0 + ENDM + + ; Macros to Decrement Counter & Jump on Condition + + LOOPx MACRO Register, Destination + dec Register ; Counter-- + jnz Destination ; Jump if not 0 + ENDM + + LOOPjz MACRO Register, Destination + dec Register ; Counter-- + jz Destination ; Jump if 0 + ENDM + + + ; ==== General Constants ==== + + = 0000 False EQU 0 + =-0001 True EQU -1 + = 0000 nil EQU 0 + + = BYTE PTR b EQU BYTE PTR + = WORD PTR w EQU WORD PTR + = DWORD PTR d EQU DWORD PTR + = OFFSET o EQU OFFSET + = FAR PTR f EQU FAR PTR + = SHORT s EQU SHORT + = ?,?,?,? ?x4 EQU + = ?,?,? ?x3 EQU + + + 0000 .Data + + EVEN + + 0000 1CE5 7307 0322 RND_Seed DW 7397, 29447, 802 + 0006 00B3 00B7 00B6 RND_Mult DW 179, 183, 182 + 000C 8003 800B 800F RND_ModV DW 32771, 32779, 32783 + + 0012 0D 0A CR_LF DB 13, 10 ; the CRLF data + + 0000 .Code + + ;=========================================== + ;void far pascal dos_print (far char *Text) + ;=========================================== + ; + ; - Print Text Directly to DOS console w/ CR/LF + ; + + PUBLIC DOS_PRINT + + 0010 DP_Stack STRUC + 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP + 0000 + 0008 00000000 DD ? ; Caller + 000C 00000000 DP_Text DD ? ; Far Address of Text to print + DP_Stack ENDS + + + 0000 DOS_PRINT PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 0000 55 1 push BP ; Save R1 + 0001 1E 2 push DS ; Save R1 + 0002 56 3 push SI ; Save R1 + 0003 57 4 push DI ; Save R1 + 0004 8B EC mov BP, SP ; Set up Stack Frame + + 0006 C5 56 0C lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor + + ; Compute Length of string + + CLR CX ; Length = 0 + 0009 33 C9 1 xor CX, CX ; Set Register = 0 + 000B 8B F2 mov SI, DX ; DS:SI = String data + + 000D @@DP_Scan_it: + + 000D 80 3C 00 cmp b [SI], 0 ; Null Byte found? + 0010 74 04 je @@DP_Got_Len ; exit loop if so + + 0012 41 inc CX ; Len++ + 0013 46 inc SI ; Point to next char + 0014 EB F7 jmp s @@DP_Scan_it ; check again... + + 0016 @@DP_Got_len: + + 0016 E3 07 jcxz @No_Print ; Don't Print if empty + + 0018 BB 0001 mov BX, 1 ; 1= DOS Handle for Display + 001B B4 40 mov AH, 40h ; Write Text Function + 001D CD 21 int 21h ; Call DOS to do it + + 001F @No_Print: + 001F B8 ---- R mov AX, SEG DGROUP ; Restore DGroup + 0022 8E D8 mov DS, AX + + 0024 BA 0012 R mov DX, o CR_LF ; Get Addr of CR/LF pair + 0027 B9 0002 mov CX, 2 ; 2 Characters to Write + 002A BB 0001 mov BX, 1 ; 1= DOS Handle for Display + + 002D B4 40 mov AH, 40h ; Write Text Function + 002F CD 21 int 21h ; Call DOS to do it + + 0031 FC cld ; Reset Direction Flag + POPx DI, SI, DS, BP ; Restore Saved Registers + 0032 5F 1 pop DI ; Restore R1 + 0033 5E 2 pop SI ; Restore R1 + 0034 1F 3 pop DS ; Restore R1 + 0035 5D 4 pop BP ; Restore R1 + 0036 CA 0004 ret 4 ; Exit & Clean Up Stack + + 0039 DOS_PRINT ENDP + + + ;=========================================== + ;void far pascal dos_prints (char far *Text) + ;=========================================== + ; + ; Print Text Directly to DOS console + ; without a trailing CR/LF + ; + + PUBLIC DOS_PRINTS + + 0039 DOS_PRINTS PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 0039 55 1 push BP ; Save R1 + 003A 1E 2 push DS ; Save R1 + 003B 56 3 push SI ; Save R1 + 003C 57 4 push DI ; Save R1 + 003D 8B EC mov BP, SP ; Set up Stack Frame + + 003F C5 56 0C lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor + + ; Compute Length of string + + CLR CX ; Length = 0 + 0042 33 C9 1 xor CX, CX ; Set Register = 0 + 0044 8B F2 mov SI, DX ; DS:SI = String data + + 0046 @@DPS_Scan_it: + + 0046 80 3C 00 cmp b [SI], 0 ; Null Byte found? + 0049 74 04 je @@DPS_Got_Len ; exit loop if so + + 004B 41 inc CX ; Len++ + 004C 46 inc SI ; Point to next char + 004D EB F7 jmp s @@DPS_Scan_it ; check again... + + 004F @@DPS_Got_len: + + 004F E3 07 jcxz @DPS_Exit ; Don't Print if empty + + 0051 BB 0001 mov BX, 1 ; 1= DOS Handle for Display + 0054 B4 40 mov AH, 40h ; Write Text Function + 0056 CD 21 int 21h ; Call DOS to do it + + 0058 @DPS_Exit: + 0058 FC cld ; Reset Direction Flag + POPx DI, SI, DS, BP ; Restore Saved Registers + 0059 5F 1 pop DI ; Restore R1 + 005A 5E 2 pop SI ; Restore R1 + 005B 1F 3 pop DS ; Restore R1 + 005C 5D 4 pop BP ; Restore R1 + 005D CA 0002 ret 2 ; Exit & Clean Up Stack + + 0060 DOS_PRINTS ENDP + + + ;========================================= + ;void far pascal set_video_mode (int Mode) + ;========================================= + ; + ; Sets the Video Mode through the BIOS + ; + + PUBLIC SET_VIDEO_MODE + + 000E SVM_Stack STRUC + 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP + 0000 + 0008 00000000 DD ? ; Caller + 000C 00 00 SVM_Mode DB ?,? ; Desired Video Mode + SVM_Stack ENDS + + + 0060 SET_VIDEO_MODE PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 0060 55 1 push BP ; Save R1 + 0061 1E 2 push DS ; Save R1 + 0062 56 3 push SI ; Save R1 + 0063 57 4 push DI ; Save R1 + 0064 8B EC mov BP, SP ; Set up Stack Frame + + CLR AH ; Function 0 + 0066 32 E4 1 xor AH, AH ; Set Register = 0 + 0068 8A 46 0C mov AL, [BP].SVM_Mode ; Get Mode # + + 006B CD 10 int 10H ; Change Video Modes + + 006D @SVM_Exit: + POPx DI, SI, DS, BP ; Restore Saved Registers + 006D 5F 1 pop DI ; Restore R1 + 006E 5E 2 pop SI ; Restore R1 + 006F 1F 3 pop DS ; Restore R1 + 0070 5D 4 pop BP ; Restore R1 + 0071 CA 0002 ret 2 ; Exit & Clean Up Stack + + 0074 SET_VIDEO_MODE ENDP + + + ;=================================== + ;int far pascal scan_keyboard (void) + ;=================================== + ; + ; Function to scan keyboard for a pressed key + ; + + PUBLIC SCAN_KEYBOARD + + 0074 SCAN_KEYBOARD PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 0074 55 1 push BP ; Save R1 + Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18 +c_utils.asm Page 2 - 1 + + + 0075 1E 2 push DS ; Save R1 + 0076 56 3 push SI ; Save R1 + 0077 57 4 push DI ; Save R1 + + 0078 B4 01 mov AH, 01H ; Function #1 + 007A CD 16 INT 16H ; Call Keyboard Driver + 007C 74 0C JZ @SK_NO_KEY ; Exit if Zero flag set + + 007E B4 00 mov AH, 00H ; Remove Key from Buffer + 0080 CD 16 INT 16H ; Get Keycode in AX + + 0082 0A C0 OR AL, AL ; Low Byte Set (Ascii?) + 0084 74 06 JZ @SK_Exit ; if not, it's a F-Key + + CLR AH ; Clear ScanCode if Ascii + 0086 32 E4 1 xor AH, AH ; Set Register = 0 + 0088 EB 02 JMP s @SK_Exit ; Return Key in AX + + 008A @SK_NO_KEY: + CLR AX ; Return Nil (no Keypress) + 008A 33 C0 1 xor AX, AX ; Set Register = 0 + + 008C @SK_Exit: + 008C FC cld ; Reset Direction Flag + POPx DI, SI, DS, BP ; Restore Saved Registers + 008D 5F 1 pop DI ; Restore R1 + 008E 5E 2 pop SI ; Restore R1 + 008F 1F 3 pop DS ; Restore R1 + 0090 5D 4 pop BP ; Restore R1 + 0091 CB ret ; Exit & Clean Up Stack + + 0092 SCAN_KEYBOARD ENDP + + + ;======================================== + ;int far pascal random_int (int MaxValue) + ;======================================== + ; + ; Returns a pseudo-random number in the range of (0.. MaxInt-1) + ; + + + PUBLIC RANDOM_INT + + 0008 RI_Stack STRUC + 0000 0000 DW ? ; BP + 0002 00000000 DD ? ; Caller + 0006 0000 RI_MaxVal DW ? ; Maximum Value to Return + 1 + RI_Stack ENDS + + + 0092 RANDOM_INT PROC FAR + + 0092 55 push BP ; Preserve Important Registers + 0093 8B EC mov BP, SP ; Set up Stack Frame + + CLR BX ; BX is the data index + 0095 33 DB 1 xor BX, BX ; Set Register = 0 + CLR CX ; CX is the accumulator + 0097 33 C9 1 xor CX, CX ; Set Register = 0 + + REPT 3 + mov AX, RND_Seed[BX] ; load the initial seed + mul RND_Mult[BX] ; multiply it + div RND_ModV[BX] ; and obtain the Mod value + mov RND_Seed[BX], DX ; save that for the next time + + add CX, DX ; add it into the accumulator + inc BX + inc BX ; point to the next set of values + ENDM + 0099 8B 87 0000 R 1 mov AX, RND_Seed[BX] ; load the initial seed + 009D F7 A7 0006 R 1 mul RND_Mult[BX] ; multiply it + 00A1 F7 B7 000C R 1 div RND_ModV[BX] ; and obtain the Mod value + 00A5 89 97 0000 R 1 mov RND_Seed[BX], DX ; save that for the next time + 00A9 03 CA 1 add CX, DX ; add it into the accumulator + 00AB 43 1 inc BX + 00AC 43 1 inc BX ; point to the next set of values + 00AD 8B 87 0000 R 1 mov AX, RND_Seed[BX] ; load the initial seed + 00B1 F7 A7 0006 R 1 mul RND_Mult[BX] ; multiply it + 00B5 F7 B7 000C R 1 div RND_ModV[BX] ; and obtain the Mod value + 00B9 89 97 0000 R 1 mov RND_Seed[BX], DX ; save that for the next time + 00BD 03 CA 1 add CX, DX ; add it into the accumulator + 00BF 43 1 inc BX + 00C0 43 1 inc BX ; point to the next set of values + 00C1 8B 87 0000 R 1 mov AX, RND_Seed[BX] ; load the initial seed + 00C5 F7 A7 0006 R 1 mul RND_Mult[BX] ; multiply it + 00C9 F7 B7 000C R 1 div RND_ModV[BX] ; and obtain the Mod value + 00CD 89 97 0000 R 1 mov RND_Seed[BX], DX ; save that for the next time + 00D1 03 CA 1 add CX, DX ; add it into the accumulator + 00D3 43 1 inc BX + 00D4 43 1 inc BX ; point to the next set of values + + 00D5 8B C1 mov AX, CX ; AX = Random # + CLR DX ; DX = 0 + 00D7 33 D2 1 xor DX, DX ; Set Register = 0 + 00D9 F7 76 06 div [BP].RI_MaxVal ; DX = DX:AX / MAxVal Remainder + + 00DC 8B C2 mov AX, DX + + 00DE 5D pop BP ; Restore BP + 00DF CA 0002 ret 2 ; back to BASIC with AX holding the result + + 00E2 RANDOM_INT ENDP + + + ;================================== + ;void far pascal init_random (void) + ;================================== + ; + ; Scrambles the psuedo-random number sequence + ; (XOR's the seed value with the timer) + ; + + PUBLIC INIT_RANDOM + + 00E2 INIT_RANDOM PROC FAR + + CLR AX ; Segment = 0000 + 00E2 33 C0 1 xor AX, AX ; Set Register = 0 + 00E4 8E C0 mov ES, AX + 00E6 26: A1 046C mov AX, ES:[046Ch] ; Get Timer Lo Word + + 00EA 31 06 0000 R xor RND_Seed, AX ; Scramble 1st Seed + + 00EE CB ret ; Exit & Clean Up Stack + + 00EF INIT_RANDOM ENDP + + ;========================================= + ;int far pascal int_sqr (int X, int Round) + ;========================================= + ; + ; Returns the Integer Square Root of (X) + ; Round allows the return value to be rounded to the + ; nearest integer value by passing 0x80. Passing 0 + ; return the Integer Portion only. The rounding amound is + ; a number from 0 to 1 multiplied by 256, thus + ; 0.5 * 0x100 = 0x80! + ; + + 000C ISQ_Stack STRUC + 0000 0000 0000 DW ?,? ; BP, DI + 0004 00000000 DD ? ; Caller + 0008 0000 ISQ_Round DW ? ; Amount to Round Result * 256 + 000A 0000 ISQ_X DW ? ; "X" + ISQ_Stack ENDS + + PUBLIC INT_SQR + + 00EF INT_SQR PROC FAR + + PUSHx BP, DI ; Save BP + 00EF 55 1 push BP ; Save R1 + 00F0 57 2 push DI ; Save R1 + 00F1 8B EC mov BP, SP ; Set up Stack Frame + + 00F3 33 C0 xor AX, AX ; {xor eax,eax} + 00F5 33 D2 xor DX, DX ; {xor edx,edx} + 00F7 8B 7E 0A mov DI, [BP].ISQ_X ; {mov edi,x} + + 00FA B9 0010 mov CX, 16 ; {mov cx, 32} + + 00FD @ISQ_L: + + 00FD D1 E7 shl DI, 1 ; {shl edi,1} + 00FF D1 D2 rcl DX, 1 ; {rcl edx,1} + 0101 D1 E7 shl DI, 1 ; {shl edi,1} + 0103 D1 D2 rcl DX, 1 ; {rcl edx,1} + 0105 D1 E0 shl AX, 1 ; {shl eax,1} + 0107 8B D8 mov BX, AX ; {mov ebx,eax} + 0109 D1 E3 shl BX, 1 ; {shl ebx,1} + 010B 43 inc BX ; {inc ebx} + 010C 3B D3 cmp DX, BX ; {cmp edx,ebx} + 010E 7C 03 jl @ISQ_S + + 0110 2B D3 sub DX, BX ; {sub edx,ebx} + 0112 40 inc AX ; {inc eax} + + 0113 @ISQ_S: + 0113 E2 E8 loop @ISQ_L + + 0115 03 46 08 add ax, [BP].ISQ_Round ; {add eax,$00008000} + ; {*round* result in hi word: ie. +0 + .5} + 0118 C1 E8 08 shr ax, 8 ; {shr eax,16} {to ax (result)} + + POPx DI, BP ; Restore Registers + 011B 5F 1 pop DI ; Restore R1 + 011C 5D 2 pop BP ; Restore R1 + 011D CA 0004 ret 4 ; Exit + + 0120 INT_SQR ENDP + + ;================================= + ;int far pascal timer_count (void) + ;================================= + ; + ; Returns the current timer value as an integer/long integer + ; + + PUBLIC TIMER_COUNT + + 0120 TIMER_COUNT PROC FAR + + CLR AX ; Segment = 0000 + 0120 33 C0 1 xor AX, AX ; Set Register = 0 + 0122 8E C0 mov ES, AX + 0124 26: A1 046C mov AX, ES:[046Ch] ; Get Timer Lo Word + 0128 26: 8B 16 046E mov DX, ES:[046Eh] ; Get Timer Hi Word + 012D CB ret ; Exit & Clean Up Stack + + 012E TIMER_COUNT ENDP + + + END + Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18 +c_utils.asm Symbols 3 - 1 + + + + +Macros: + + N a m e Type + +CLR . . . . . . . . . . . . . . Proc +LOOPjz . . . . . . . . . . . . . Proc +LOOPx . . . . . . . . . . . . . Proc +POPx . . . . . . . . . . . . . . Proc +PUSHx . . . . . . . . . . . . . Proc + Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18 +c_utils.asm Symbols 4 - 1 + + + + +Structures and Unions: + + N a m e Size + Offset Type + +DP_Stack . . . . . . . . . . . . 0010 + DP_Text . . . . . . . . . . . 000C DWord +ISQ_Stack . . . . . . . . . . . 000C + ISQ_Round . . . . . . . . . . 0008 Word + ISQ_X . . . . . . . . . . . . 000A Word +RI_Stack . . . . . . . . . . . . 0008 + RI_MaxVal . . . . . . . . . . 0006 Word +SVM_Stack . . . . . . . . . . . 000E + SVM_Mode . . . . . . . . . . . 000C Byte + Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18 +c_utils.asm Symbols 5 - 1 + + + + +Segments and Groups: + + N a m e Size Length Align Combine Class + +C_UTILS_TEXT . . . . . . . . . . 16 Bit 012E Word Public 'CODE' +DGROUP . . . . . . . . . . . . . GROUP +_DATA . . . . . . . . . . . . . 16 Bit 0014 Word Public 'DATA' + Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18 +c_utils.asm Symbols 6 - 1 + + + + +Procedures, parameters and locals: + + N a m e Type Value Attr + +DOS_PRINTS . . . . . . . . . . . P Far 0039 C_UTILS_TEXT Length= 0027 Public +DOS_PRINT . . . . . . . . . . . P Far 0000 C_UTILS_TEXT Length= 0039 Public +INIT_RANDOM . . . . . . . . . . P Far 00E2 C_UTILS_TEXT Length= 000D Public +INT_SQR . . . . . . . . . . . . P Far 00EF C_UTILS_TEXT Length= 0031 Public +RANDOM_INT . . . . . . . . . . . P Far 0092 C_UTILS_TEXT Length= 0050 Public +SCAN_KEYBOARD . . . . . . . . . P Far 0074 C_UTILS_TEXT Length= 001E Public +SET_VIDEO_MODE . . . . . . . . . P Far 0060 C_UTILS_TEXT Length= 0014 Public +TIMER_COUNT . . . . . . . . . . P Far 0120 C_UTILS_TEXT Length= 000E Public + Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18 +c_utils.asm Symbols 7 - 1 + + + + +Symbols: + + N a m e Type Value Attr + +?x3 . . . . . . . . . . . . . . Text ?,?,? +?x4 . . . . . . . . . . . . . . Text ?,?,?,? +@@DPS_Got_len . . . . . . . . . L Near 004F C_UTILS_TEXT +@@DPS_Scan_it . . . . . . . . . L Near 0046 C_UTILS_TEXT +@@DP_Got_len . . . . . . . . . . L Near 0016 C_UTILS_TEXT +@@DP_Scan_it . . . . . . . . . . L Near 000D C_UTILS_TEXT +@CodeSize . . . . . . . . . . . Number 0001h +@DPS_Exit . . . . . . . . . . . L Near 0058 C_UTILS_TEXT +@DataSize . . . . . . . . . . . Number 0000h +@ISQ_L . . . . . . . . . . . . . L Near 00FD C_UTILS_TEXT +@ISQ_S . . . . . . . . . . . . . L Near 0113 C_UTILS_TEXT +@Interface . . . . . . . . . . . Number 0000h +@Model . . . . . . . . . . . . . Number 0004h +@No_Print . . . . . . . . . . . L Near 001F C_UTILS_TEXT +@SK_Exit . . . . . . . . . . . . L Near 008C C_UTILS_TEXT +@SK_NO_KEY . . . . . . . . . . . L Near 008A C_UTILS_TEXT +@SVM_Exit . . . . . . . . . . . L Near 006D C_UTILS_TEXT +@code . . . . . . . . . . . . . Text C_UTILS_TEXT +@data . . . . . . . . . . . . . Text DGROUP +@fardata? . . . . . . . . . . . Text FAR_BSS +@fardata . . . . . . . . . . . . Text FAR_DATA +@stack . . . . . . . . . . . . . Text DGROUP +CR_LF . . . . . . . . . . . . . Byte 0012 _DATA +False . . . . . . . . . . . . . Number 0000h +RND_ModV . . . . . . . . . . . . Word 000C _DATA +RND_Mult . . . . . . . . . . . . Word 0006 _DATA +RND_Seed . . . . . . . . . . . . Word 0000 _DATA +True . . . . . . . . . . . . . . Number -0001h +b . . . . . . . . . . . . . . . Text BYTE PTR +d . . . . . . . . . . . . . . . Text DWORD PTR +f . . . . . . . . . . . . . . . Text FAR PTR +nil . . . . . . . . . . . . . . Number 0000h +o . . . . . . . . . . . . . . . Text OFFSET +s . . . . . . . . . . . . . . . Text SHORT +w . . . . . . . . . . . . . . . Text WORD PTR + + 0 Warnings + 0 Errors diff --git a/src/lib/modex/demos/c/c_utils.sbr b/src/lib/modex/demos/c/c_utils.sbr new file mode 100755 index 0000000000000000000000000000000000000000..0301171bdd90f778ed3f244b37130f9388df7f0a GIT binary patch literal 1731 zcmZ8hU1(fY5dQAuK&p#UAC#&fKJ+1i$i~{%wn9$2yN#Fb?%mvb6JlMtU9-E%CfnU~ zf101hwzk#OG>vU+Qxyc!2N9n{@L3cD5qwebS;PmQL{UWW!I`<6G!~ZSyEEr}b7tn7 zf#VpY4i`@p2M@?E>mDuUymV$_FuA{&&g8tHn1VAIbvw0s`>9g<6zE0t(XKMmUJw<0 zHy?s-iluVL5`exDQx!objKacF3Q)yL8lNHdY z(+7JBZZH}JozmniXxuTJN{Wv@-hiJ^M?s}hMq&mu*DsS$~{0n-MBnhI>?z>CnI#*j%$*se|?lw^L;Am0jr`8vA;!PtUtas20*?Hi0*+i(!2Hh%{}P54 z_G#P|n2N?_722Je1Nq{j!*c#C+FFi3V9shrA1PormzFJYr&ErZQ7#snRblNA+d*;C z6T-HvU7lI$73~$+6c;V1EivB_IdG1j_Y7zZ<{aoN{XZ!7^WX&1Qo0MOv0S&_QE5Hw zm^9=@G|V+G0ZTGHjWd zH094>s_NnCv^9gq`OFt0J}$u|(Chr?lQ$-gku%FnC7^3dP43Vsqdz2BReRUM4r z&SY>OS3z^Vxw#t8%}BEo)hj%!GcZ>rq*MyiYe!nkJm^fWUJyos>YWht>1?8)m$MPs3x4WckJ5rSNp>pVkJ&l@Pnu910PcFYZ} z=06a?@BBdlx8ySgOm|rU=eI`yb$hznh;_vxm~+eqXi%#~18?D2sosvCf#gltN!GXq zJMWlTO@sHZ<$b%oe<#F2_sDL&1>fD0z, ; If DX not setup + MOV DX, Register ; then Select Register + ENDIF + IFDIFI , ; If AX not setup + MOV AX, Value ; then Get Data Value + ENDIF + OUT DX, AX ; Set I/O Register(s) +ENDM + + ; Macro to OUT a 8 bit value to an I/O Port + +OUT_8 MACRO Register, Value + IFDIFI , ; If DX not setup + MOV DX, Register ; then Select Register + ENDIF + IFDIFI , ; If AL not Setup + MOV AL, Value ; then Get Data Value + ENDIF + OUT DX, AL ; Set I/O Register +ENDM + + ; macros to PUSH and POP multiple registers + +; PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8 +; IFNB +; PUSH R1 ; Save R1 +; PUSHx R2, R3, R4, R5, R6, R7, R8 +; ENDIF +; ENDM +; +; POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8 +; IFNB +; POP R1 ; Restore R1 +; POPx R2, R3, R4, R5, R6, R7, R8 +; ENDIF +; ENDM + + ; Macro to Clear Registers to 0 + +; CLR MACRO Register, R2, R3, R4;, R5, R6 +; IFNB +; XOR Register, Register ; Set Register = 0 +; CLR R2, R3, R4;, R5, R6 +; ENDIF +; ENDM + + ; Macros to Decrement Counter & Jump on Condition + +LOOPx MACRO Register, Destination + DEC Register ; Counter-- + JNZ Destination ; Jump if not 0 +ENDM + +LOOPjz MACRO Register, Destination + DEC Register ; Counter-- + JZ Destination ; Jump if 0 +ENDM + + + ; ===== General Constants ===== + + False EQU 0 + True EQU -1 + nil EQU 0 + + b EQU BYTE PTR + w EQU WORD PTR + d EQU DWORD PTR + o EQU OFFSET + f EQU FAR PTR + s EQU SHORT + ?x1 EQU + + ; ===== VGA Register Values ===== + + VGA_Segment EQU 0A000h ; Vga Memory Segment + + ATTRIB_Ctrl EQU 03C0h ; VGA Attribute Controller + GC_Index EQU 03CEh ; VGA Graphics Controller + SC_Index EQU 03C4h ; VGA Sequencer Controller + SC_Data EQU 03C5h ; VGA Sequencer Data Port + CRTC_Index EQU 03D4h ; VGA CRT Controller + CRTC_Data EQU 03D5h ; VGA CRT Controller Data + MISC_OUTPUT EQU 03C2h ; VGA Misc Register + INPUT_1 EQU 03DAh ; Input Status #1 Register + + DAC_WRITE_ADDR EQU 03C8h ; VGA DAC Write Addr Register + DAC_READ_ADDR EQU 03C7h ; VGA DAC Read Addr Register + PEL_DATA_REG EQU 03C9h ; VGA DAC/PEL data Register R/W + + PIXEL_PAN_REG EQU 033h ; Attrib Index: Pixel Pan Reg + MAP_MASK EQU 002h ; Sequ Index: Write Map Mask reg + READ_MAP EQU 004h ; GC Index: Read Map Register + START_DISP_HI EQU 00Ch ; CRTC Index: Display Start Hi + START_DISP_LO EQU 00Dh ; CRTC Index: Display Start Lo + + MAP_MASK_PLANE1 EQU 00102h ; Map Register + Plane 1 + MAP_MASK_PLANE2 EQU 01102h ; Map Register + Plane 1 + ALL_PLANES_ON EQU 00F02h ; Map Register + All Bit Planes + + CHAIN4_OFF EQU 00604h ; Chain 4 mode Off + ASYNC_RESET EQU 00100h ; (A)synchronous Reset + SEQU_RESTART EQU 00300h ; Sequencer Restart + + LATCHES_ON EQU 00008h ; Bit Mask + Data from Latches + LATCHES_OFF EQU 0FF08h ; Bit Mask + Data from CPU + + VERT_RETRACE EQU 08h ; INPUT_1: Vertical Retrace Bit + PLANE_BITS EQU 03h ; Bits 0-1 of Xpos = Plane # + ALL_PLANES EQU 0Fh ; All Bit Planes Selected + CHAR_BITS EQU 0Fh ; Bits 0-3 of Character Data + + GET_CHAR_PTR EQU 01130h ; VGA BIOS Func: Get Char Set + ROM_8x8_Lo EQU 03h ; ROM 8x8 Char Set Lo Pointer + ROM_8x8_Hi EQU 04h ; ROM 8x8 Char Set Hi Pointer + + ; Constants Specific for these routines + + NUM_MODES EQU 8 ; # of Mode X Variations + + ; Specific Mode Data Table format... + +Mode_Data_Table STRUC + M_MiscR DB ? ; Value of MISC_OUTPUT register + M_Pages DB ? ; Maximum Possible # of pages + M_XSize DW ? ; X Size Displayed on screen + M_YSize DW ? ; Y Size Displayed on screen + M_XMax DW ? ; Maximum Possible X Size + M_YMax DW ? ; Maximum Possible Y Size + M_CRTC DW ? ; Table of CRTC register values +Mode_Data_Table ENDS + + ; ===== DGROUP STORAGE NEEDED (42 BYTES) ===== + + .DATA? + +SCREEN_WIDTH DW 0 ; Width of a line in Bytes +SCREEN_HEIGHT DW 0 ; Vertical Height in Pixels + +LAST_PAGE DW 0 ; # of Display Pages +PAGE_ADDR DW 4 DUP (0) ; Offsets to start of each page + +PAGE_SIZE DW 0 ; Size of Page in Addr Bytes + +DISPLAY_PAGE DW 0 ; Page # currently displayed +ACTIVE_PAGE DW 0 ; Page # currently active + +CURRENT_PAGE DW 0 ; Offset of current Page +CURRENT_SEGMENT DW 0 ; Segment of VGA memory + +CURRENT_XOFFSET DW 0 ; Current Display X Offset +CURRENT_YOFFSET DW 0 ; Current Display Y Offset + +CURRENT_MOFFSET DW 0 ; Current Start Offset + +MAX_XOFFSET DW 0 ; Current Display X Offset +MAX_YOFFSET DW 0 ; Current Display Y Offset + +CHARSET_LOW DW 0, 0 ; Far Ptr to Char Set: 0-127 +CHARSET_HI DW 0, 0 ; Far Ptr to Char Set: 128-255 + + .CODE + + ; ===== DATA TABLES ===== + + ; Data Tables, Put in Code Segment for Easy Access + ; (Like when all the other Segment Registers are in + ; use!!) and reduced DGROUP requirements... + + ; Bit Mask Tables for Left/Right/Character Masks + +Left_Clip_Mask DB 0FH, 0EH, 0CH, 08H + +Right_Clip_Mask DB 01H, 03H, 07H, 0FH + + ; Bit Patterns for converting character fonts + +Char_Plane_Data DB 00H,08H,04H,0CH,02H,0AH,06H,0EH + DB 01H,09H,05H,0DH,03H,0BH,07H,0FH + + ; CRTC Register Values for Various Configurations + +MODE_Single_Line: ; CRTC Setup Data for 400/480 Line modes + DW 04009H ; Cell Height (1 Scan Line) + DW 00014H ; Dword Mode off + DW 0E317H ; turn on Byte Mode + DW nil ; End of CRTC Data for 400/480 Line Mode + +MODE_Double_Line: ; CRTC Setup Data for 200/240 Line modes + DW 04109H ; Cell Height (2 Scan Lines) + DW 00014H ; Dword Mode off + DW 0E317H ; turn on Byte Mode + DW nil ; End of CRTC Data for 200/240 Line Mode + +MODE_320_Wide: ; CRTC Setup Data for 320 Horz Pixels + DW 05F00H ; Horz total + DW 04F01H ; Horz Displayed + DW 05002H ; Start Horz Blanking + DW 08203H ; End Horz Blanking + DW 05404H ; Start H Sync + DW 08005H ; End H Sync + DW nil ; End of CRTC Data for 320 Horz pixels + +MODE_360_Wide: ; CRTC Setup Data for 360 Horz Pixels + DW 06B00H ; Horz total + DW 05901H ; Horz Displayed + DW 05A02H ; Start Horz Blanking + DW 08E03H ; End Horz Blanking + DW 05E04H ; Start H Sync + DW 08A05H ; End H Sync + DW nil ; End of CRTC Data for 360 Horz pixels + +MODE_200_Tall: +MODE_400_Tall: ; CRTC Setup Data for 200/400 Line modes + DW 0BF06H ; Vertical Total + DW 01F07H ; Overflow + DW 09C10H ; V Sync Start + DW 08E11H ; V Sync End/Prot Cr0 Cr7 + DW 08F12H ; Vertical Displayed + DW 09615H ; V Blank Start + DW 0B916H ; V Blank End + DW nil ; End of CRTC Data for 200/400 Lines + +MODE_240_Tall: +MODE_480_Tall: ; CRTC Setup Data for 240/480 Line modes + DW 00D06H ; Vertical Total + DW 03E07H ; Overflow + DW 0EA10H ; V Sync Start + DW 08C11H ; V Sync End/Prot Cr0 Cr7 + DW 0DF12H ; Vertical Displayed + DW 0E715H ; V Blank Start + DW 00616H ; V Blank End + DW nil ; End of CRTC Data for 240/480 Lines + + ; Table of Display Mode Tables + +MODE_TABLE: + DW o MODE_320x200, o MODE_320x400 + DW o MODE_360x200, o MODE_360x400 + DW o MODE_320x240, o MODE_320x480 + DW o MODE_360x240, o MODE_360x480 + + ; Table of Display Mode Components + +MODE_320x200: ; Data for 320 by 200 Pixels + + DB 063h ; 400 scan Lines & 25 Mhz Clock + DB 4 ; Maximum of 4 Pages + DW 320, 200 ; Displayed Pixels (X,Y) + DW 1302, 816 ; Max Possible X and Y Sizes + + DW o MODE_320_Wide, o MODE_200_Tall + DW o MODE_Double_Line, nil + +MODE_320x400: ; Data for 320 by 400 Pixels + + DB 063h ; 400 scan Lines & 25 Mhz Clock + DB 2 ; Maximum of 2 Pages + DW 320, 400 ; Displayed Pixels X,Y + DW 648, 816 ; Max Possible X and Y Sizes + + DW o MODE_320_Wide, o MODE_400_Tall + DW o MODE_Single_Line, nil + +MODE_360x240: ; Data for 360 by 240 Pixels + + DB 0E7h ; 480 scan Lines & 28 Mhz Clock + DB 3 ; Maximum of 3 Pages + DW 360, 240 ; Displayed Pixels X,Y + DW 1092, 728 ; Max Possible X and Y Sizes + + DW o MODE_360_Wide, o MODE_240_Tall + DW o MODE_Double_Line , nil + +MODE_360x480: ; Data for 360 by 480 Pixels + + DB 0E7h ; 480 scan Lines & 28 Mhz Clock + DB 1 ; Only 1 Page Possible + DW 360, 480 ; Displayed Pixels X,Y + DW 544, 728 ; Max Possible X and Y Sizes + + DW o MODE_360_Wide, o MODE_480_Tall + DW o MODE_Single_Line , nil + +MODE_320x240: ; Data for 320 by 240 Pixels + + DB 0E3h ; 480 scan Lines & 25 Mhz Clock + DB 3 ; Maximum of 3 Pages + DW 320, 240 ; Displayed Pixels X,Y + DW 1088, 818 ; Max Possible X and Y Sizes + + DW o MODE_320_Wide, o MODE_240_Tall + DW o MODE_Double_Line, nil + +MODE_320x480: ; Data for 320 by 480 Pixels + + DB 0E3h ; 480 scan Lines & 25 Mhz Clock + DB 1 ; Only 1 Page Possible + DW 320, 480 ; Displayed Pixels X,Y + DW 540, 818 ; Max Possible X and Y Sizes + + DW o MODE_320_WIDE, o MODE_480_Tall + DW o MODE_Single_Line, nil + +MODE_360x200: ; Data for 360 by 200 Pixels + + DB 067h ; 400 scan Lines & 28 Mhz Clock + DB 3 ; Maximum of 3 Pages + DW 360, 200 ; Displayed Pixels (X,Y) + DW 1302, 728 ; Max Possible X and Y Sizes + + DW o MODE_360_Wide, MODE_200_Tall + DW o MODE_Double_Line, nil + +MODE_360x400: ; Data for 360 by 400 Pixels + + DB 067h ; 400 scan Lines & 28 Mhz Clock + DB 1 ; Maximum of 1 Pages + DW 360, 400 ; Displayed Pixels X,Y + DW 648, 816 ; Max Possible X and Y Sizes + + DW o MODE_360_Wide, MODE_400_Tall + DW o MODE_Single_Line, nil + + + ; ===== MODE X SETUP ROUTINES ===== + +;====================================================== +;SET_VGA_MODEX% (ModeType%, MaxXPos%, MaxYpos%, Pages%) +;====================================================== +; +; Sets Up the specified version of Mode X. Allows for +; the setup of multiple video pages, and a virtual +; screen which can be larger than the displayed screen +; (which can then be scrolled a pixel at a time) +; +; ENTRY: ModeType = Desired Screen Resolution (0-7) +; +; 0 = 320 x 200, 4 Pages max, 1.2:1 Aspect Ratio +; 1 = 320 x 400, 2 Pages max, 2.4:1 Aspect Ratio +; 2 = 360 x 200, 3 Pages max, 1.35:1 Aspect Ratio +; 3 = 360 x 400, 1 Page max, 2.7:1 Aspect Ratio +; 4 = 320 x 240, 3 Pages max, 1:1 Aspect Ratio +; 5 = 320 x 480, 1 Page max, 2:1 Aspect Ratio +; 6 = 360 x 240, 3 Pages max, 1.125:1 Aspect Ratio +; 7 = 360 x 480, 1 Page max, 2.25:1 Aspect Ratio +; +; MaxXpos = The Desired Virtual Screen Width +; MaxYpos = The Desired Virtual Screen Height +; Pages = The Desired # of Video Pages +; +; EXIT: AX = Success Flag: >0 = Failure / 0 = Success +; + +SVM_STACK STRUC + SVM_Table DW ? ; Offset of Mode Info Table + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DD ? ; Caller + SVM_Pages DW ? ; # of Screen Pages desired + SVM_Ysize DW ? ; Vertical Screen Size Desired + SVM_Xsize DW ? ; Horizontal Screen Size Desired + SVM_Mode DW ? ; Display Resolution Desired +SVM_STACK ENDS + + PUBLIC SET_VGA_MODEX + +SET_VGA_MODEX PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + SUB SP, 2 ; Allocate workspace + MOV BP, SP ; Set up Stack Frame + + ; Check Legality of Mode Request.... + + MOV BX, [BP].SVM_Mode ; Get Requested Mode # + CMP BX, NUM_MODES ; Is it 0..7? + JAE @SVM_BadModeSetup1 ; If Not, Error out + + SHL BX, 1 ; Scale BX + MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info + MOV [BP].SVM_Table, SI ; Save ptr for later use + + ; Check # of Requested Display Pages + + MOV CX, [BP].SVM_Pages ; Get # of Requested Pages + ;CLR CH ; Set Hi Word = 0! + mov ch,0 ; Set Hi Word = 0! + CMP CL, CS:[SI].M_Pages ; Check # Pages for mode + JA @SVM_BadModeSetup2 ; Report Error if too Many Pages + JCXZ @SVM_BadModeSetup3 ; Report Error if 0 Pages + + ; Check Validity of X Size + + AND [BP].SVM_XSize, 0FFF8h ; X size Mod 8 Must = 0 + + MOV AX, [BP].SVM_XSize ; Get Logical Screen Width + CMP AX, CS:[SI].M_XSize ; Check against Displayed X + JB @SVM_BadModeSetup4 ; Report Error if too small + CMP AX, CS:[SI].M_XMax ; Check against Max X + JA @SVM_BadModeSetup5 ; Report Error if too big + + ; Check Validity of Y Size + + MOV BX, [BP].SVM_YSize ; Get Logical Screen Height + CMP BX, CS:[SI].M_YSize ; Check against Displayed Y + JB @SVM_BadModeSetup6 ; Report Error if too small + CMP BX, CS:[SI].M_YMax ; Check against Max Y + JA @SVM_BadModeSetup7 ; Report Error if too big + + ; Enough memory to Fit it all? + + SHR AX, 1 ; # of Bytes:Line = XSize/4 + SHR AX, 1 ; # of Bytes:Line = XSize/4 + MUL CX ; AX = Bytes/Line * Pages + MUL BX ; DX:AX = Total VGA mem needed + JNO @SVM_Continue ; Exit if Total Size > 256K + + DEC DX ; Was it Exactly 256K??? + OR DX, AX ; (DX = 1, AX = 0000) + JZ @SVM_Continue ; if so, it's valid... + + jmp @SVM_Continue;0000 + +@SVM_BadModeSetup: + mov ax,8 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup1: + mov ax,1 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup2: + mov ax,2 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup3: + mov ax,3 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup4: + mov ax,4 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup5: + mov ax,5 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup6: + mov ax,6 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup7: + mov ax,7 ; Return Value = False + JMP @SVM_Exit ; Normal Exit + +@SVM_Continue: + + MOV AX, 13H ; Start with Mode 13H + INT 10H ; Let BIOS Set Mode + + OUT_16 SC_INDEX, CHAIN4_OFF ; Disable Chain 4 Mode + OUT_16 SC_INDEX, ASYNC_RESET ; (A)synchronous Reset + OUT_8 MISC_OUTPUT, CS:[SI].M_MiscR ; Set New Timing/Size + OUT_16 SC_INDEX, SEQU_RESTART ; Restart Sequencer ... + + OUT_8 CRTC_INDEX, 11H ; Select Vert Retrace End Register + INC DX ; Point to Data + IN AL, DX ; Get Value, Bit 7 = Protect + AND AL, 7FH ; Mask out Write Protect + OUT DX, AL ; And send it back + + MOV DX, CRTC_INDEX ; Vga Crtc Registers + ADD SI, M_CRTC ; SI -> CRTC Parameter Data + + ; Load Tables of CRTC Parameters from List of Tables + +@SVM_Setup_Table: + + MOV DI, CS:[SI] ; Get Pointer to CRTC Data Tbl + ADD SI, 2 ; Point to next Ptr Entry + OR DI, DI ; A nil Ptr means that we have + JZ @SVM_Set_Data ; finished CRTC programming + +@SVM_Setup_CRTC: + MOV AX, CS:[DI] ; Get CRTC Data from Table + ADD DI, 2 ; Advance Pointer + OR AX, AX ; At End of Data Table? + JZ @SVM_Setup_Table ; If so, Exit & get next Table + + OUT DX, AX ; Reprogram VGA CRTC reg + JMP s @SVM_Setup_CRTC ; Process Next Table Entry + + ; Initialize Page & Scroll info, DI = 0 + +@SVM_Set_Data: + MOV DISPLAY_PAGE, DI ; Display Page = 0 + MOV ACTIVE_PAGE, DI ; Active Page = 0 + MOV CURRENT_PAGE, DI ; Current Page (Offset) = 0 + MOV CURRENT_XOFFSET, DI ; Horz Scroll Index = 0 + MOV CURRENT_YOFFSET, DI ; Vert Scroll Index = 0 + MOV CURRENT_MOFFSET, DI ; Memory Scroll Index = 0 + + MOV AX, VGA_SEGMENT ; Segment for VGA memory + MOV CURRENT_SEGMENT, AX ; Save for Future LES's + + ; Set Logical Screen Width, X Scroll and Our Data + + MOV SI, [BP].SVM_Table ; Get Saved Ptr to Mode Info + MOV AX, [BP].SVM_Xsize ; Get Display Width + + MOV CX, AX ; CX = Logical Width + SUB CX, CS:[SI].M_XSize ; CX = Max X Scroll Value + MOV MAX_XOFFSET, CX ; Set Maximum X Scroll + + SHR AX, 1 ; Bytes = Pixels / 4 + SHR AX, 1 ; Bytes = Pixels / 4 + MOV SCREEN_WIDTH, AX ; Save Width in Pixels + + SHR AX, 1 ; Offset Value = Bytes / 2 + MOV AH, 13h ; CRTC Offset Register Index + XCHG AL, AH ; Switch format for OUT + OUT DX, AX ; Set VGA CRTC Offset Reg + + ; Setup Data table, Y Scroll, Misc for Other Routines + + MOV AX, [BP].SVM_Ysize ; Get Logical Screen Height + + MOV CX, AX ; CX = Logical Height + SUB BX, CS:[SI].M_YSize ; CX = Max Y Scroll Value + MOV MAX_YOFFSET, CX ; Set Maximum Y Scroll + + MOV SCREEN_HEIGHT, AX ; Save Height in Pixels + MUL SCREEN_WIDTH ; AX = Page Size in Bytes, + MOV PAGE_SIZE, AX ; Save Page Size + + MOV CX, [BP].SVM_Pages ; Get # of Pages + MOV LAST_PAGE, CX ; Save # of Pages + + mov bx,0 ; Page # = 0 + MOV DX, BX ; Page 0 Offset = 0 + +@SVM_Set_Pages: + + MOV PAGE_ADDR[BX], DX ; Set Page #(BX) Offset + ADD BX, 2 ; Page#++ + ADD DX, AX ; Compute Addr of Next Page + LOOPx CX, @SVM_Set_Pages ; Loop until all Pages Set + + ; Clear VGA Memory + + OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes + LES DI, d CURRENT_PAGE ; -> Start of VGA memory + + mov ax,0 ; AX = 0 + CLD ; Block Xfer Forwards + MOV CX, 8000H ; 32K * 4 * 2 = 256K + REP STOSW ; Clear dat memory! + + ; Setup Font Pointers + + MOV BH, ROM_8x8_Lo ; Ask for 8x8 Font, 0-127 + MOV AX, GET_CHAR_PTR ; Service to Get Pointer + INT 10h ; Call VGA BIOS + + MOV CHARSET_LOW, BP ; Save Char Set Offset + MOV CHARSET_LOW+2, ES ; Save Char Set Segment + + MOV BH, ROM_8x8_Hi ; Ask for 8x8 Font, 128-255 + MOV AX, GET_CHAR_PTR ; Service to Get Pointer + INT 10h ; Call VGA BIOS + + MOV CHARSET_HI, BP ; Save Char Set Offset + MOV CHARSET_HI+2, ES ; Save Char Set Segment + + MOV AX, True ; Return Success Code + +@SVM_EXIT: + ADD SP, 2 ; Deallocate workspace + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + RET 8 ; Exit & Clean Up Stack + +SET_VGA_MODEX ENDP + + +;================== +;SET_MODEX% (Mode%) +;================== +; +; Quickie Mode Set - Sets Up Mode X to Default Configuration +; +; ENTRY: ModeType = Desired Screen Resolution (0-7) +; (See SET_VGA_MODEX for list) +; +; EXIT: AX = Success Flag: 0 = Failure / -1= Success +; + +SM_STACK STRUC + DW ?,? ; BP, SI + DD ? ; Caller + SM_Mode DW ? ; Desired Screen Resolution +SM_STACK ENDS + + PUBLIC SET_MODEX + +SET_MODEX PROC FAR + + ;PUSHx BP, SI ; Preserve Important registers + push bp + push si + MOV BP, SP ; Set up Stack Frame + + mov ax,0 ; Assume Failure + MOV BX, [BP].SM_Mode ; Get Desired Mode # + CMP BX, NUM_MODES ; Is it a Valid Mode #? + JAE @SMX_Exit ; If Not, don't Bother + + PUSH BX ; Push Mode Parameter + + SHL BX, 1 ; Scale BX to word Index + MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info + + PUSH CS:[SI].M_XSize ; Push Default X Size + PUSH CS:[SI].M_Ysize ; Push Default Y size + MOV AL, CS:[SI].M_Pages ; Get Default # of Pages + mov ah,0 ; Hi Byte = 0 + PUSH AX ; Push # Pages + + CALL f SET_VGA_MODEX ; Set up Mode X! + +@SMX_Exit: + ;POPx SI, BP ; Restore Registers + pop si + pop bp + RET 2 ; Exit & Clean Up Stack + +SET_MODEX ENDP + + + ; ===== BASIC GRAPHICS PRIMITIVES ===== + +;============================ +;CLEAR_VGA_SCREEN (ColorNum%) +;============================ +; +; Clears the active display page +; +; ENTRY: ColorNum = Color Value to fill the page with +; +; EXIT: No meaningful values returned +; + +CVS_STACK STRUC + DW ?,? ; DI, BP + DD ? ; Caller + CVS_COLOR DB ?,? ; Color to Set Screen to +CVS_STACK ENDS + + PUBLIC CLEAR_VGA_SCREEN + +CLEAR_VGA_SCREEN PROC FAR + + ;PUSHx BP, DI ; Preserve Important Registers + push bp + push di + MOV BP, SP ; Set up Stack Frame + + OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + + MOV AL, [BP].CVS_COLOR ; Get Color + MOV AH, AL ; Copy for Word Write + CLD ; Block fill Forwards + + MOV CX, PAGE_SIZE ; Get Size of Page + SHR CX, 1 ; Divide by 2 for Words + REP STOSW ; Block Fill VGA memory + + ;POPx DI, BP ; Restore Saved Registers + pop di + pop bp + RET 2 ; Exit & Clean Up Stack + +CLEAR_VGA_SCREEN ENDP + + +;=================================== +;SET_POINT (Xpos%, Ypos%, ColorNum%) +;=================================== +; +; Plots a single Pixel on the active display page +; +; ENTRY: Xpos = X position to plot pixel at +; Ypos = Y position to plot pixel at +; ColorNum = Color to plot pixel with +; +; EXIT: No meaningful values returned +; + +SP_STACK STRUC + DW ?,? ; BP, DI + DD ? ; Caller + SETP_Color DB ?,? ; Color of Point to Plot + SETP_Ypos DW ? ; Y pos of Point to Plot + SETP_Xpos DW ? ; X pos of Point to Plot +SP_STACK ENDS + + PUBLIC SET_POINT + +SET_POINT PROC FAR + + ;PUSHx BP, DI ; Preserve Registers + push bp + push di + MOV BP, SP ; Set up Stack Frame + + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + + MOV AX, [BP].SETP_Ypos ; Get Line # of Pixel + MUL SCREEN_WIDTH ; Get Offset to Start of Line + + MOV BX, [BP].SETP_Xpos ; Get Xpos + MOV CX, BX ; Copy to extract Plane # from + SHR BX, 1 ; X offset (Bytes) = Xpos/4 + SHR BX, 1 ; X offset (Bytes) = Xpos/4 + ADD BX, AX ; Offset = Width*Ypos + Xpos/4 + + MOV AX, MAP_MASK_PLANE1 ; Map Mask & Plane Select Register + AND CL, PLANE_BITS ; Get Plane Bits + SHL AH, CL ; Get Plane Select Value + OUT_16 SC_Index, AX ; Select Plane + + MOV AL,[BP].SETP_Color ; Get Pixel Color + MOV ES:[DI+BX], AL ; Draw Pixel + + ;POPx DI, BP ; Restore Saved Registers + pop di + pop bp + RET 6 ; Exit and Clean up Stack + +SET_POINT ENDP + + +;========================== +;READ_POINT% (Xpos%, Ypos%) +;========================== +; +; Read the color of a pixel from the Active Display Page +; +; ENTRY: Xpos = X position of pixel to read +; Ypos = Y position of pixel to read +; +; EXIT: AX = Color of Pixel at (Xpos, Ypos) +; + +RP_STACK STRUC + DW ?,? ; BP, DI + DD ? ; Caller + RP_Ypos DW ? ; Y pos of Point to Read + RP_Xpos DW ? ; X pos of Point to Read +RP_STACK ENDS + + PUBLIC READ_POINT + +READ_POINT PROC FAR + + ;PUSHx BP, DI ; Preserve Registers + push bp + push di + MOV BP, SP ; Set up Stack Frame + + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + + MOV AX, [BP].RP_Ypos ; Get Line # of Pixel + MUL SCREEN_WIDTH ; Get Offset to Start of Line + + MOV BX, [BP].RP_Xpos ; Get Xpos + MOV CX, BX + SHR BX, 1 ; X offset (Bytes) = Xpos/4 + SHR BX, 1 ; X offset (Bytes) = Xpos/4 + ADD BX, AX ; Offset = Width*Ypos + Xpos/4 + + MOV AL, READ_MAP ; GC Read Mask Register + MOV AH, CL ; Get Xpos + AND AH, PLANE_BITS ; & mask out Plane # + OUT_16 GC_INDEX, AX ; Select Plane to read in + + mov ah,0 ; Clear Return Value Hi byte + MOV AL, ES:[DI+BX] ; Get Color of Pixel + + ;POPx DI, BP ; Restore Saved Registers + pop di + pop bp + RET 4 ; Exit and Clean up Stack + +READ_POINT ENDP + + +;====================================================== +;FILL_BLOCK (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%) +;====================================================== +; +; Fills a rectangular block on the active display Page +; +; ENTRY: Xpos1 = Left X position of area to fill +; Ypos1 = Top Y position of area to fill +; Xpos2 = Right X position of area to fill +; Ypos2 = Bottom Y position of area to fill +; ColorNum = Color to fill area with +; +; EXIT: No meaningful values returned +; + +FB_STACK STRUC + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DD ? ; Caller + FB_Color DB ?,? ; Fill Color + FB_Ypos2 DW ? ; Y pos of Lower Right Pixel + FB_Xpos2 DW ? ; X pos of Lower Right Pixel + FB_Ypos1 DW ? ; Y pos of Upper Left Pixel + FB_Xpos1 DW ? ; X pos of Upper Left Pixel +FB_STACK ENDS + + PUBLIC FILL_BLOCK + +FILL_BLOCK PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + MOV BP, SP ; Set up Stack Frame + + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + CLD ; Direction Flag = Forward + + OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select + + ; Validate Pixel Coordinates + ; If necessary, Swap so X1 <= X2, Y1 <= Y2 + + MOV AX, [BP].FB_Ypos1 ; AX = Y1 is Y1< Y2? + MOV BX, [BP].FB_Ypos2 ; BX = Y2 + CMP AX, BX + JLE @FB_NOSWAP1 + + MOV [BP].FB_Ypos1, BX ; Swap Y1 and Y2 and save Y1 + XCHG AX, BX ; on stack for future use + +@FB_NOSWAP1: + SUB BX, AX ; Get Y width + INC BX ; Add 1 to avoid 0 value + MOV [BP].FB_Ypos2, BX ; Save in Ypos2 + + MUL SCREEN_WIDTH ; Mul Y1 by Bytes per Line + ADD DI, AX ; DI = Start of Line Y1 + + MOV AX, [BP].FB_Xpos1 ; Check X1 <= X2 + MOV BX, [BP].FB_Xpos2 ; + CMP AX, BX + JLE @FB_NOSWAP2 ; Skip Ahead if Ok + + MOV [BP].FB_Xpos2, AX ; Swap X1 AND X2 and save X2 + XCHG AX, BX ; on stack for future use + + ; All our Input Values are in order, Now determine + ; How many full "bands" 4 pixels wide (aligned) there + ; are, and if there are partial bands (<4 pixels) on + ; the left and right edges. + +@FB_NOSWAP2: + MOV DX, AX ; DX = X1 (Pixel Position) + SHR DX, 1 ; DX/4 = Bytes into Line + SHR DX, 1 ; DX/4 = Bytes into Line + ADD DI, DX ; DI = Addr of Upper-Left Corner + + MOV CX, BX ; CX = X2 (Pixel Position) + SHR CX, 1 ; CX/4 = Bytes into Line + SHR CX, 1 ; CX/4 = Bytes into Line + + CMP DX, CX ; Start and end in same band? + JNE @FB_NORMAL ; if not, check for l & r edges + JMP @FB_ONE_BAND_ONLY ; if so, then special processing + +@FB_NORMAL: + SUB CX, DX ; CX = # bands -1 + MOV SI, AX ; SI = PLANE#(X1) + AND SI, PLANE_BITS ; if Left edge is aligned then + JZ @FB_L_PLANE_FLUSH ; no special processing.. + + ; Draw "Left Edge" vertical strip of 1-3 pixels... + + OUT_8 SC_Data, Left_Clip_Mask[SI] ; Set Left Edge Plane Mask + + MOV SI, DI ; SI = Copy of Start Addr (UL) + + MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw + MOV AL, [BP].FB_Color ; Get Fill Color + MOV BX, SCREEN_WIDTH ; Get Vertical increment Value + +@FB_LEFT_LOOP: + MOV ES:[SI], AL ; Fill in Left Edge Pixels + ADD SI, BX ; Point to Next Line (Below) + LOOPjz DX, @FB_LEFT_CONT ; Exit loop if all Lines Drawn + + MOV ES:[SI], AL ; Fill in Left Edge Pixels + ADD SI, BX ; Point to Next Line (Below) + LOOPx DX, @FB_LEFT_LOOP ; loop until left strip is drawn + +@FB_LEFT_CONT: + + INC DI ; Point to Middle (or Right) Block + DEC CX ; Reset CX instead of JMP @FB_RIGHT + +@FB_L_PLANE_FLUSH: + INC CX ; Add in Left band to middle block + + ; DI = Addr of 1st middle Pixel (band) to fill + ; CX = # of Bands to fill -1 + +@FB_RIGHT: + MOV SI, [BP].FB_Xpos2 ; Get Xpos2 + AND SI, PLANE_BITS ; Get Plane values + CMP SI, 0003 ; Plane = 3? + JE @FB_R_EDGE_FLUSH ; Hey, add to middle + + ; Draw "Right Edge" vertical strip of 1-3 pixels... + + OUT_8 SC_Data, Right_Clip_Mask[SI] ; Right Edge Plane Mask + + MOV SI, DI ; Get Addr of Left Edge + ADD SI, CX ; Add Width-1 (Bands) + DEC SI ; To point to top of Right Edge + + MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw + MOV AL, [BP].FB_Color ; Get Fill Color + MOV BX, SCREEN_WIDTH ; Get Vertical increment Value + +@FB_RIGHT_LOOP: + MOV ES:[SI], AL ; Fill in Right Edge Pixels + ADD SI, BX ; Point to Next Line (Below) + LOOPjz DX, @FB_RIGHT_CONT ; Exit loop if all Lines Drawn + + MOV ES:[SI], AL ; Fill in Right Edge Pixels + ADD SI, BX ; Point to Next Line (Below) + LOOPx DX, @FB_RIGHT_LOOP ; loop until left strip is drawn + +@FB_RIGHT_CONT: + + DEC CX ; Minus 1 for Middle bands + JZ @FB_EXIT ; Uh.. no Middle bands... + +@FB_R_EDGE_FLUSH: + + ; DI = Addr of Upper Left block to fill + ; CX = # of Bands to fill in (width) + + OUT_8 SC_Data, ALL_PLANES ; Write to All Planes + + MOV DX, SCREEN_WIDTH ; DX = DI Increment + SUB DX, CX ; = Screen_Width-# Planes Filled + + MOV BX, CX ; BX = Quick Refill for CX + MOV SI, [BP].FB_Ypos2 ; SI = # of Line to Fill + MOV AL, [BP].FB_Color ; Get Fill Color + +@FB_MIDDLE_LOOP: + REP STOSB ; Fill in entire line + + MOV CX, BX ; Recharge CX (Line Width) + ADD DI, DX ; Point to start of Next Line + LOOPx SI, @FB_MIDDLE_LOOP ; Loop until all lines drawn + + JMP s @FB_EXIT ; Outa here + +@FB_ONE_BAND_ONLY: + MOV SI, AX ; Get Left Clip Mask, Save X1 + AND SI, PLANE_BITS ; Mask out Row # + MOV AL, Left_Clip_Mask[SI] ; Get Left Edge Mask + MOV SI, BX ; Get Right Clip Mask, Save X2 + AND SI, PLANE_BITS ; Mask out Row # + AND AL, Right_Clip_Mask[SI] ; Get Right Edge Mask byte + + OUT_8 SC_Data, AL ; Clip For Left & Right Masks + + MOV CX, [BP].FB_Ypos2 ; Get # of Lines to draw + MOV AL, [BP].FB_Color ; Get Fill Color + MOV BX, SCREEN_WIDTH ; Get Vertical increment Value + +@FB_ONE_LOOP: + MOV ES:[DI], AL ; Fill in Pixels + ADD DI, BX ; Point to Next Line (Below) + LOOPjz CX, @FB_EXIT ; Exit loop if all Lines Drawn + + MOV ES:[DI], AL ; Fill in Pixels + ADD DI, BX ; Point to Next Line (Below) + LOOPx CX, @FB_ONE_LOOP ; loop until left strip is drawn + +@FB_EXIT: + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + RET 10 ; Exit and Clean up Stack + +FILL_BLOCK ENDP + + +;===================================================== +;DRAW_LINE (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%) +;===================================================== +; +; Draws a Line on the active display page +; +; ENTRY: Xpos1 = X position of first point on line +; Ypos1 = Y position of first point on line +; Xpos2 = X position of last point on line +; Ypos2 = Y position of last point on line +; ColorNum = Color to draw line with +; +; EXIT: No meaningful values returned +; + +DL_STACK STRUC + DW ?x1 ; DI, SI, BP + DW ?x1 ; DI, SI, BP + DW ?x1 ; DI, SI, BP + DD ? ; Caller + DL_ColorF DB ?,? ; Line Draw Color + DL_Ypos2 DW ? ; Y pos of last point + DL_Xpos2 DW ? ; X pos of last point + DL_Ypos1 DW ? ; Y pos of first point + DL_Xpos1 DW ? ; X pos of first point +DL_STACK ENDS + + PUBLIC DRAW_LINE + +DRAW_LINE PROC FAR + + ;PUSHx BP, SI, DI ; Preserve Important Registers + push bp + push si + push di + MOV BP, SP ; Set up Stack Frame + CLD ; Direction Flag = Forward + + OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select + MOV CH, [BP].DL_ColorF ; Save Line Color in CH + + ; Check Line Type + + MOV SI, [BP].DL_Xpos1 ; AX = X1 is X1< X2? + MOV DI, [BP].DL_Xpos2 ; DX = X2 + CMP SI, DI ; Is X1 < X2 + JE @DL_VLINE ; If X1=X2, Draw Vertical Line + JL @DL_NOSWAP1 ; If X1 < X2, don't swap + + XCHG SI, DI ; X2 IS > X1, SO SWAP THEM + +@DL_NOSWAP1: + + ; SI = X1, DI = X2 + + MOV AX, [BP].DL_Ypos1 ; AX = Y1 is Y1 <> Y2? + CMP AX, [BP].DL_Ypos2 ; Y1 = Y2? + JE @DL_HORZ ; If so, Draw a Horizontal Line + + JMP @DL_BREZHAM ; Diagonal line... go do it... + + ; This Code draws a Horizontal Line in Mode X where: + ; SI = X1, DI = X2, and AX = Y1/Y2 + +@DL_HORZ: + + MUL SCREEN_WIDTH ; Offset = Ypos * Screen_Width + MOV DX, AX ; CX = Line offset into Page + + MOV AX, SI ; Get Left edge, Save X1 + AND SI, PLANE_BITS ; Mask out Row # + MOV BL, Left_Clip_Mask[SI] ; Get Left Edge Mask + MOV CX, DI ; Get Right edge, Save X2 + AND DI, PLANE_BITS ; Mask out Row # + MOV BH, Right_Clip_Mask[DI] ; Get Right Edge Mask byte + + SHR AX, 1 ; Get X1 Byte # (=X1/4) + SHR CX, 1 ; Get X2 Byte # (=X2/4) + SHR AX, 1 ; Get X1 Byte # (=X1/4) + SHR CX, 1 ; Get X2 Byte # (=X2/4) + + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + ADD DI, DX ; Point to Start of Line + ADD DI, AX ; Point to Pixel X1 + + SUB CX, AX ; CX = # Of Bands (-1) to set + JNZ @DL_LONGLN ; jump if longer than one segment + + AND BL, BH ; otherwise, merge clip masks + +@DL_LONGLN: + + OUT_8 SC_Data, BL ; Set the Left Clip Mask + + MOV AL, [BP].DL_ColorF ; Get Line Color + MOV BL, AL ; BL = Copy of Line Color + STOSB ; Set Left (1-4) Pixels + + JCXZ @DL_EXIT ; Done if only one Line Segment + + DEC CX ; CX = # of Middle Segments + JZ @DL_XRSEG ; If no middle segments.... + + ; Draw Middle Segments + + OUT_8 DX, ALL_PLANES ; Write to ALL Planes + + MOV AL, BL ; Get Color from BL + REP STOSB ; Draw Middle (4 Pixel) Segments + +@DL_XRSEG: + OUT_8 DX, BH ; Select Planes for Right Clip Mask + MOV AL, BL ; Get Color Value + STOSB ; Draw Right (1-4) Pixels + + JMP s @DL_EXIT ; We Are Done... + + + ; This Code Draws A Vertical Line. On entry: + ; CH = Line Color, SI & DI = X1 + +@DL_VLINE: + + MOV AX, [BP].DL_Ypos1 ; AX = Y1 + MOV SI, [BP].DL_Ypos2 ; SI = Y2 + CMP AX, SI ; Is Y1 < Y2? + JLE @DL_NOSWAP2 ; if so, Don't Swap them + + XCHG AX, SI ; Ok, NOW Y1 < Y2 + +@DL_NOSWAP2: + + SUB SI, AX ; SI = Line Height (Y2-Y1+1) + INC SI + + ; AX = Y1, DI = X1, Get offset into Page into AX + + MUL SCREEN_WIDTH ; Offset = Y1 (AX) * Screen Width + MOV DX, DI ; Copy Xpos into DX + SHR DI, 1 ; DI = Xpos/4 + SHR DI, 1 ; DI = Xpos/4 + ADD AX, DI ; DI = Xpos/4 + ScreenWidth * Y1 + + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + ADD DI, AX ; Point to Pixel X1, Y1 + + ;Select Plane + + MOV CL, DL ; CL = Save X1 + AND CL, PLANE_BITS ; Get X1 MOD 4 (Plane #) + MOV AX, MAP_MASK_PLANE1 ; Code to set Plane #1 + SHL AH, CL ; Change to Correct Plane # + OUT_16 SC_Index, AX ; Select Plane + + MOV AL, CH ; Get Saved Color + MOV BX, SCREEN_WIDTH ; Get Offset to Advance Line By + +@DL_VLoop: + MOV ES:[DI], AL ; Draw Single Pixel + ADD DI, BX ; Point to Next Line + LOOPjz SI, @DL_EXIT ; Lines--, Exit if done + + MOV ES:[DI], AL ; Draw Single Pixel + ADD DI, BX ; Point to Next Line + LOOPx SI, @DL_VLoop ; Lines--, Loop until Done + +@DL_EXIT: + + JMP @DL_EXIT2 ; Done! + + ; This code Draws a diagonal line in Mode X + +@DL_BREZHAM: + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + + MOV AX, [BP].DL_Ypos1 ; get Y1 value + MOV BX, [BP].DL_Ypos2 ; get Y2 value + MOV CX, [BP].DL_Xpos1 ; Get Starting Xpos + + CMP BX, AX ; Y2-Y1 is? + JNC @DL_DeltaYOK ; if Y2>=Y1 then goto... + + XCHG BX, AX ; Swap em... + MOV CX, [BP].DL_Xpos2 ; Get New Starting Xpos + +@DL_DeltaYOK: + MUL SCREEN_WIDTH ; Offset = SCREEN_WIDTH * Y1 + + ADD DI, AX ; DI -> Start of Line Y1 on Page + MOV AX, CX ; AX = Xpos (X1) + SHR AX, 1 ; /4 = Byte Offset into Line + SHR AX, 1 ; /4 = Byte Offset into Line + ADD DI, AX ; DI = Starting pos (X1,Y1) + + MOV AL, 11h ; Staring Mask + AND CL, PLANE_BITS ; Get Plane # + SHL AL, CL ; and shift into place + MOV AH, [BP].DL_ColorF ; Color in Hi Bytes + + PUSH AX ; Save Mask,Color... + + MOV AH, AL ; Plane # in AH + MOV AL, MAP_MASK ; Select Plane Register + OUT_16 SC_Index, AX ; Select initial plane + + MOV AX, [BP].DL_Xpos1 ; get X1 value + MOV BX, [BP].DL_Ypos1 ; get Y1 value + MOV CX, [BP].DL_Xpos2 ; get X2 value + MOV DX, [BP].DL_Ypos2 ; get Y2 value + + MOV BP, SCREEN_WIDTH ; Use BP for Line width to + ; to avoid extra memory access + + SUB DX, BX ; figure Delta_Y + JNC @DL_DeltaYOK2 ; jump if Y2 >= Y1 + + ADD BX, DX ; put Y2 into Y1 + NEG DX ; abs(Delta_Y) + XCHG AX, CX ; and exchange X1 and X2 + +@DL_DeltaYOK2: + MOV BX, 08000H ; seed for fraction accumulator + + SUB CX, AX ; figure Delta_X + JC @DL_DrawLeft ; if negative, go left + + JMP @DL_DrawRight ; Draw Line that slopes right + +@DL_DrawLeft: + + NEG CX ; abs(Delta_X) + + CMP CX, DX ; is Delta_X < Delta_Y? + JB @DL_SteepLeft ; yes, so go do steep line + ; (Delta_Y iterations) + + ; Draw a Shallow line to the left in Mode X + +@DL_ShallowLeft: + mov ax,0 ; zero low word of Delta_Y * 10000h + SUB AX, DX ; DX:AX <- DX * 0FFFFh + SBB DX, 0 ; include carry + DIV CX ; divide by Delta_X + + MOV SI, BX ; SI = Accumulator + MOV BX, AX ; BX = Add fraction + POP AX ; Get Color, Bit mask + MOV DX, SC_Data ; Sequence controller data register + INC CX ; Inc Delta_X so we can unroll loop + + ; Loop (x2) to Draw Pixels, Move Left, and Maybe Down... + +@DL_SLLLoop: + MOV ES:[DI], AH ; set first pixel, plane data set up + LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done + + ADD SI, BX ; add numerator to accumulator + JNC @DL_SLLL2nc ; move down on carry + + ADD DI, BP ; Move Down one line... + +@DL_SLLL2nc: + DEC DI ; Left one addr + ROR AL, 1 ; Move Left one plane, back on 0 1 2 + CMP AL, 87h ; wrap?, if AL <88 then Carry set + ADC DI, 0 ; Adjust Address: DI = DI + Carry + OUT DX, AL ; Set up New Bit Plane mask + + MOV ES:[DI], AH ; set pixel + LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done + + ADD SI, BX ; add numerator to accumulator, + JNC @DL_SLLL3nc ; move down on carry + + ADD DI, BP ; Move Down one line... + +@DL_SLLL3nc: ; Now move left a pixel... + DEC DI ; Left one addr + ROR AL, 1 ; Move Left one plane, back on 0 1 2 + CMP AL, 87h ; Wrap?, if AL <88 then Carry set + ADC DI, 0 ; Adjust Address: DI = DI + Carry + OUT DX, AL ; Set up New Bit Plane mask + JMP s @DL_SLLLoop ; loop until done + +@DL_SLLExit: + JMP @DL_EXIT2 ; and exit + + ; Draw a steep line to the left in Mode X + +@DL_SteepLeft: + mov ax,0 ; zero low word of Delta_Y * 10000h + XCHG DX, CX ; Delta_Y switched with Delta_X + DIV CX ; divide by Delta_Y + + MOV SI, BX ; SI = Accumulator + MOV BX, AX ; BX = Add Fraction + POP AX ; Get Color, Bit mask + MOV DX, SC_Data ; Sequence controller data register + INC CX ; Inc Delta_Y so we can unroll loop + + ; Loop (x2) to Draw Pixels, Move Down, and Maybe left + +@DL_STLLoop: + + MOV ES:[DI], AH ; set first pixel + LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done + + ADD SI, BX ; add numerator to accumulator + JNC @DL_STLnc2 ; No carry, just move down! + + DEC DI ; Move Left one addr + ROR AL, 1 ; Move Left one plane, back on 0 1 2 + CMP AL, 87h ; Wrap?, if AL <88 then Carry set + ADC DI, 0 ; Adjust Address: DI = DI + Carry + OUT DX, AL ; Set up New Bit Plane mask + +@DL_STLnc2: + ADD DI, BP ; advance to next line. + + MOV ES:[DI], AH ; set pixel + LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done + + ADD SI, BX ; add numerator to accumulator + JNC @DL_STLnc3 ; No carry, just move down! + + DEC DI ; Move Left one addr + ROR AL, 1 ; Move Left one plane, back on 0 1 2 + CMP AL, 87h ; Wrap?, if AL <88 then Carry set + ADC DI, 0 ; Adjust Address: DI = DI + Carry + OUT DX, AL ; Set up New Bit Plane mask + +@DL_STLnc3: + ADD DI, BP ; advance to next line. + JMP s @DL_STLLoop ; Loop until done + +@DL_STLExit: + JMP @DL_EXIT2 ; and exit + + ; Draw a line that goes to the Right... + +@DL_DrawRight: + CMP CX, DX ; is Delta_X < Delta_Y? + JB @DL_SteepRight ; yes, so go do steep line + ; (Delta_Y iterations) + + ; Draw a Shallow line to the Right in Mode X + +@DL_ShallowRight: + mov ax,0 ; zero low word of Delta_Y * 10000h + SUB AX, DX ; DX:AX <- DX * 0FFFFh + SBB DX, 0 ; include carry + DIV CX ; divide by Delta_X + + MOV SI, BX ; SI = Accumulator + MOV BX, AX ; BX = Add Fraction + POP AX ; Get Color, Bit mask + MOV DX, SC_Data ; Sequence controller data register + INC CX ; Inc Delta_X so we can unroll loop + + ; Loop (x2) to Draw Pixels, Move Right, and Maybe Down... + +@DL_SLRLoop: + MOV ES:[DI], AH ; set first pixel, mask is set up + LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done.. + + ADD SI, BX ; add numerator to accumulator + JNC @DL_SLR2nc ; don't move down if carry not set + + ADD DI, BP ; Move Down one line... + +@DL_SLR2nc: ; Now move right a pixel... + ROL AL, 1 ; Move Right one addr if Plane = 0 + CMP AL, 12h ; Wrap? if AL >12 then Carry not set + ADC DI, 0 ; Adjust Address: DI = DI + Carry + OUT DX, AL ; Set up New Bit Plane mask + + MOV ES:[DI], AH ; set pixel + LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done.. + + ADD SI, BX ; add numerator to accumulator + JNC @DL_SLR3nc ; don't move down if carry not set + + ADD DI, BP ; Move Down one line... + +@DL_SLR3nc: + ROL AL, 1 ; Move Right one addr if Plane = 0 + CMP AL, 12h ; Wrap? if AL >12 then Carry not set + ADC DI, 0 ; Adjust Address: DI = DI + Carry + OUT DX, AL ; Set up New Bit Plane mask + JMP s @DL_SLRLoop ; loop till done + +@DL_SLRExit: + JMP @DL_EXIT2 ; and exit + + ; Draw a Steep line to the Right in Mode X + +@DL_SteepRight: + mov ax,0 ; zero low word of Delta_Y * 10000h + XCHG DX, CX ; Delta_Y switched with Delta_X + DIV CX ; divide by Delta_Y + + MOV SI, BX ; SI = Accumulator + MOV BX, AX ; BX = Add Fraction + POP AX ; Get Color, Bit mask + MOV DX, SC_Data ; Sequence controller data register + INC CX ; Inc Delta_Y so we can unroll loop + + ; Loop (x2) to Draw Pixels, Move Down, and Maybe Right + +@STRLoop: + MOV ES:[DI], AH ; set first pixel, mask is set up + LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done + + ADD SI, BX ; add numerator to accumulator + JNC @STRnc2 ; if no carry then just go down... + + ROL AL, 1 ; Move Right one addr if Plane = 0 + CMP AL, 12h ; Wrap? if AL >12 then Carry not set + ADC DI, 0 ; Adjust Address: DI = DI + Carry + OUT DX, AL ; Set up New Bit Plane mask + +@STRnc2: + ADD DI, BP ; advance to next line. + + MOV ES:[DI], AH ; set pixel + LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done + + ADD SI, BX ; add numerator to accumulator + JNC @STRnc3 ; if no carry then just go down... + + ROL AL, 1 ; Move Right one addr if Plane = 0 + CMP AL, 12h ; Wrap? if AL >12 then Carry not set + ADC DI, 0 ; Adjust Address: DI = DI + Carry + OUT DX, AL ; Set up New Bit Plane mask + +@STRnc3: + ADD DI, BP ; advance to next line. + JMP s @STRLoop ; loop till done + +@DL_EXIT2: + ;POPx DI, SI, BP ; Restore Saved Registers + pop di + pop si + pop bp + RET 10 ; Exit and Clean up Stack + +DRAW_LINE ENDP + + + ; ===== DAC COLOR REGISTER ROUTINES ===== + +;================================================= +;SET_DAC_REGISTER (Register%, Red%, Green%, Blue%) +;================================================= +; +; Sets a single (RGB) Vga Palette Register +; +; ENTRY: Register = The DAC # to modify (0-255) +; Red = The new Red Intensity (0-63) +; Green = The new Green Intensity (0-63) +; Blue = The new Blue Intensity (0-63) +; +; EXIT: No meaningful values returned +; + +SDR_STACK STRUC + DW ? ; BP + DD ? ; Caller + SDR_Blue DB ?,? ; Blue Data Value + SDR_Green DB ?,? ; Green Data Value + SDR_Red DB ?,? ; Red Data Value + SDR_Register DB ?,? ; Palette Register # +SDR_STACK ENDS + + PUBLIC SET_DAC_REGISTER + +SET_DAC_REGISTER PROC FAR + + PUSH BP ; Save BP + MOV BP, SP ; Set up Stack Frame + + ; Select which DAC Register to modify + + OUT_8 DAC_WRITE_ADDR, [BP].SDR_Register + + MOV DX, PEL_DATA_REG ; Dac Data Register + OUT_8 DX, [BP].SDR_Red ; Set Red Intensity + OUT_8 DX, [BP].SDR_Green ; Set Green Intensity + OUT_8 DX, [BP].SDR_Blue ; Set Blue Intensity + + POP BP ; Restore Registers + RET 8 ; Exit & Clean Up Stack + +SET_DAC_REGISTER ENDP + +;==================================================== +;GET_DAC_REGISTER (Register%, &Red%, &Green%, &Blue%) +;==================================================== +; +; Reads the RGB Values of a single Vga Palette Register +; +; ENTRY: Register = The DAC # to read (0-255) +; Red = Offset to Red Variable in DS +; Green = Offset to Green Variable in DS +; Blue = Offset to Blue Variable in DS +; +; EXIT: The values of the integer variables Red, +; Green, and Blue are set to the values +; taken from the specified DAC register. +; + +GDR_STACK STRUC + DW ? ; BP + DD ? ; Caller + GDR_Blue DW ? ; Addr of Blue Data Value in DS + GDR_Green DW ? ; Addr of Green Data Value in DS + GDR_Red DW ? ; Addr of Red Data Value in DS + GDR_Register DB ?,? ; Palette Register # +GDR_STACK ENDS + + PUBLIC GET_DAC_REGISTER + +GET_DAC_REGISTER PROC FAR + + PUSH BP ; Save BP + MOV BP, SP ; Set up Stack Frame + + ; Select which DAC Register to read in + + OUT_8 DAC_READ_ADDR, [BP].GDR_Register + + MOV DX, PEL_DATA_REG ; Dac Data Register + mov ax,0 ; Clear AX + + IN AL, DX ; Read Red Value + MOV BX, [BP].GDR_Red ; Get Address of Red% + MOV [BX], AX ; *Red% = AX + + IN AL, DX ; Read Green Value + MOV BX, [BP].GDR_Green ; Get Address of Green% + MOV [BX], AX ; *Green% = AX + + IN AL, DX ; Read Blue Value + MOV BX, [BP].GDR_Blue ; Get Address of Blue% + MOV [BX], AX ; *Blue% = AX + + POP BP ; Restore Registers + RET 8 ; Exit & Clean Up Stack + +GET_DAC_REGISTER ENDP + + +;=========================================================== +;LOAD_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%, Sync%) +;=========================================================== +; +; Sets a Block of Vga Palette Registers +; +; ENTRY: PalData = Far Pointer to Block of palette data +; StartReg = First Register # in range to set (0-255) +; EndReg = Last Register # in Range to set (0-255) +; Sync = Wait for Vertical Retrace Flag (Boolean) +; +; EXIT: No meaningful values returned +; +; NOTES: PalData is a linear array of 3 byte Palette values +; in the order: Red (0-63), Green (0-63), Blue (0-63) +; + +LDR_STACK STRUC + DW ?x1 ; BP, DS, SI + DW ?x1 ; BP, DS, SI + DW ?x1 ; BP, DS, SI + DD ? ; Caller + LDR_Sync DW ? ; Vertical Sync Flag + LDR_EndReg DB ?,? ; Last Register # + LDR_StartReg DB ?,? ; First Register # + LDR_PalData DD ? ; Far Ptr to Palette Data +LDR_STACK ENDS + + PUBLIC LOAD_DAC_REGISTERS + +LOAD_DAC_REGISTERS PROC FAR + + ;PUSHx BP, DS, SI ; Save Registers + push bp + push ds + push si + mov BP, SP ; Set up Stack Frame + + mov AX, [BP].LDR_Sync ; Get Vertical Sync Flag + or AX, AX ; is Sync Flag = 0? + jz @LDR_Load ; if so, skip call + + call f SYNC_DISPLAY ; wait for vsync + + ; Determine register #'s, size to copy, etc + +@LDR_Load: + + lds SI, [BP].LDR_PalData ; DS:SI -> Palette Data + mov DX, DAC_WRITE_ADDR ; DAC register # selector + + mov ax,0, BX ; Clear for byte loads + mov AL, [BP].LDR_StartReg ; Get Start Register + mov BL, [BP].LDR_EndReg ; Get End Register + + sub BX, AX ; BX = # of DAC registers -1 + inc BX ; BX = # of DAC registers + mov CX, BX ; CX = # of DAC registers + add CX, BX ; CX = " " * 2 + add CX, BX ; CX = " " * 3 + cld ; Block OUTs forward + out DX, AL ; set up correct register # + + ; Load a block of DAC Registers + + mov DX, PEL_DATA_REG ; Dac Data Register + + ;rep outsb ; block set DAC registers + + ;POPx SI, DS, BP ; Restore Registers + pop si + pop ds + pop bp + ret 10 ; Exit & Clean Up Stack + +LOAD_DAC_REGISTERS ENDP + + +;==================================================== +;READ_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%) +;==================================================== +; +; Reads a Block of Vga Palette Registers +; +; ENTRY: PalData = Far Pointer to block to store palette data +; StartReg = First Register # in range to read (0-255) +; EndReg = Last Register # in Range to read (0-255) +; +; EXIT: No meaningful values returned +; +; NOTES: PalData is a linear array of 3 byte Palette values +; in the order: Red (0-63), Green (0-63), Blue (0-63) +; + +RDR_STACK STRUC + DW ?x1 ; BP, ES, DI + DW ?x1 ; BP, ES, DI + DW ?x1 ; BP, ES, DI + DD ? ; Caller + RDR_EndReg DB ?,? ; Last Register # + RDR_StartReg DB ?,? ; First Register # + RDR_PalData DD ? ; Far Ptr to Palette Data +RDR_STACK ENDS + + PUBLIC READ_DAC_REGISTERS + +READ_DAC_REGISTERS PROC FAR + + ;PUSHx BP, ES, DI ; Save Registers + push bp + push es + push di + mov BP, SP ; Set up Stack Frame + + ; Determine register #'s, size to copy, etc + + les DI, [BP].RDR_PalData ; ES:DI -> Palette Buffer + mov DX, DAC_READ_ADDR ; DAC register # selector + + mov ax,0, BX ; Clear for byte loads + mov AL, [BP].RDR_StartReg ; Get Start Register + mov BL, [BP].RDR_EndReg ; Get End Register + + sub BX, AX ; BX = # of DAC registers -1 + inc BX ; BX = # of DAC registers + mov CX, BX ; CX = # of DAC registers + add CX, BX ; CX = " " * 2 + add CX, BX ; CX = " " * 3 + cld ; Block INs forward + + ; Read a block of DAC Registers + + out DX, AL ; set up correct register # + mov DX, PEL_DATA_REG ; Dac Data Register + + ;rep insb ; block read DAC registers + + ;POPx DI, ES, BP ; Restore Registers + pop di + pop es + pop bp + ret 8 ; Exit & Clean Up Stack + +READ_DAC_REGISTERS ENDP + + + ; ===== PAGE FLIPPING AND SCROLLING ROUTINES ===== + +;========================= +;SET_ACTIVE_PAGE (PageNo%) +;========================= +; +; Sets the active display Page to be used for future drawing +; +; ENTRY: PageNo = Display Page to make active +; (values: 0 to Number of Pages - 1) +; +; EXIT: No meaningful values returned +; + +SAP_STACK STRUC + DW ? ; BP + DD ? ; Caller + SAP_Page DW ? ; Page # for Drawing +SAP_STACK ENDS + + PUBLIC SET_ACTIVE_PAGE + +SET_ACTIVE_PAGE PROC FAR + + PUSH BP ; Preserve Registers + MOV BP, SP ; Set up Stack Frame + + MOV BX, [BP].SAP_Page ; Get Desired Page # + CMP BX, LAST_PAGE ; Is Page # Valid? + JAE @SAP_Exit ; IF Not, Do Nothing + + MOV ACTIVE_PAGE, BX ; Set Active Page # + + SHL BX, 1 ; Scale Page # to Word + MOV AX, PAGE_ADDR[BX] ; Get offset to Page + + MOV CURRENT_PAGE, AX ; And set for future LES's + +@SAP_Exit: + POP BP ; Restore Registers + RET 2 ; Exit and Clean up Stack + +SET_ACTIVE_PAGE ENDP + + +;================ +;GET_ACTIVE_PAGE% +;================ +; +; Returns the Video Page # currently used for Drawing +; +; ENTRY: No Parameters are passed +; +; EXIT: AX = Current Video Page used for Drawing +; + + PUBLIC GET_ACTIVE_PAGE + +GET_ACTIVE_PAGE PROC FAR + + MOV AX, ACTIVE_PAGE ; Get Active Page # + RET ; Exit and Clean up Stack + +GET_ACTIVE_PAGE ENDP + + +;=============================== +;SET_DISPLAY_PAGE (DisplayPage%) +;=============================== +; +; Sets the currently visible display page. +; When called this routine syncronizes the display +; to the vertical blank. +; +; ENTRY: PageNo = Display Page to show on the screen +; (values: 0 to Number of Pages - 1) +; +; EXIT: No meaningful values returned +; + +SDP_STACK STRUC + DW ? ; BP + DD ? ; Caller + SDP_Page DW ? ; Page # to Display... +SDP_STACK ENDS + + PUBLIC SET_DISPLAY_PAGE + +SET_DISPLAY_PAGE PROC FAR + + PUSH BP ; Preserve Registers + MOV BP, SP ; Set up Stack Frame + + MOV BX, [BP].SDP_Page ; Get Desired Page # + CMP BX, LAST_PAGE ; Is Page # Valid? + JAE @SDP_Exit ; IF Not, Do Nothing + + MOV DISPLAY_PAGE, BX ; Set Display Page # + + SHL BX, 1 ; Scale Page # to Word + MOV CX, PAGE_ADDR[BX] ; Get offset in memory to Page + ADD CX, CURRENT_MOFFSET ; Adjust for any scrolling + + ; Wait if we are currently in a Vertical Retrace + + MOV DX, INPUT_1 ; Input Status #1 Register + +@DP_WAIT0: + IN AL, DX ; Get VGA status + AND AL, VERT_RETRACE ; In Display mode yet? + JNZ @DP_WAIT0 ; If Not, wait for it + + ; Set the Start Display Address to the new page + + MOV DX, CRTC_Index ; We Change the VGA Sequencer + + MOV AL, START_DISP_LO ; Display Start Low Register + MOV AH, CL ; Low 8 Bits of Start Addr + OUT DX, AX ; Set Display Addr Low + + MOV AL, START_DISP_HI ; Display Start High Register + MOV AH, CH ; High 8 Bits of Start Addr + OUT DX, AX ; Set Display Addr High + + ; Wait for a Vertical Retrace to smooth out things + + MOV DX, INPUT_1 ; Input Status #1 Register + +@DP_WAIT1: + IN AL, DX ; Get VGA status + AND AL, VERT_RETRACE ; Vertical Retrace Start? + JZ @DP_WAIT1 ; If Not, wait for it + + ; Now Set Display Starting Address + + +@SDP_Exit: + POP BP ; Restore Registers + RET 2 ; Exit and Clean up Stack + +SET_DISPLAY_PAGE ENDP + + +;================= +;GET_DISPLAY_PAGE% +;================= +; +; Returns the Video Page # currently displayed +; +; ENTRY: No Parameters are passed +; +; EXIT: AX = Current Video Page being displayed +; + + PUBLIC GET_DISPLAY_PAGE + +GET_DISPLAY_PAGE PROC FAR + + MOV AX, DISPLAY_PAGE ; Get Display Page # + RET ; Exit & Clean Up Stack + +GET_DISPLAY_PAGE ENDP + + +;======================================= +;SET_WINDOW (DisplayPage%, Xpos%, Ypos%) +;======================================= +; +; Since a Logical Screen can be larger than the Physical +; Screen, Scrolling is possible. This routine sets the +; Upper Left Corner of the Screen to the specified Pixel. +; Also Sets the Display page to simplify combined page +; flipping and scrolling. When called this routine +; syncronizes the display to the vertical blank. +; +; ENTRY: DisplayPage = Display Page to show on the screen +; Xpos = # of pixels to shift screen right +; Ypos = # of lines to shift screen down +; +; EXIT: No meaningful values returned +; + +SW_STACK STRUC + DW ? ; BP + DD ? ; Caller + SW_Ypos DW ? ; Y pos of UL Screen Corner + SW_Xpos DW ? ; X pos of UL Screen Corner + SW_Page DW ? ; (new) Display Page +SW_STACK ENDS + + PUBLIC SET_WINDOW + +SET_WINDOW PROC FAR + + PUSH BP ; Preserve Registers + MOV BP, SP ; Set up Stack Frame + + ; Check if our Scroll Offsets are Valid + + MOV BX, [BP].SW_Page ; Get Desired Page # + CMP BX, LAST_PAGE ; Is Page # Valid? + JAE @SW_Exit ; IF Not, Do Nothing + + MOV AX, [BP].SW_Ypos ; Get Desired Y Offset + CMP AX, MAX_YOFFSET ; Is it Within Limits? + JA @SW_Exit ; if not, exit + + MOV CX, [BP].SW_Xpos ; Get Desired X Offset + CMP CX, MAX_XOFFSET ; Is it Within Limits? + JA @SW_Exit ; if not, exit + + ; Compute proper Display start address to use + + MUL SCREEN_WIDTH ; AX = YOffset * Line Width + SHR CX, 1 ; CX / 4 = Bytes into Line + SHR CX, 1 ; CX / 4 = Bytes into Line + ADD AX, CX ; AX = Offset of Upper Left Pixel + + MOV CURRENT_MOFFSET, AX ; Save Offset Info + + MOV DISPLAY_PAGE, BX ; Set Current Page # + SHL BX, 1 ; Scale Page # to Word + ADD AX, PAGE_ADDR[BX] ; Get offset in VGA to Page + MOV BX, AX ; BX = Desired Display Start + + MOV DX, INPUT_1 ; Input Status #1 Register + + ; Wait if we are currently in a Vertical Retrace + +@SW_WAIT0: + IN AL, DX ; Get VGA status + AND AL, VERT_RETRACE ; In Display mode yet? + JNZ @SW_WAIT0 ; If Not, wait for it + + ; Set the Start Display Address to the new window + + MOV DX, CRTC_Index ; We Change the VGA Sequencer + MOV AL, START_DISP_LO ; Display Start Low Register + MOV AH, BL ; Low 8 Bits of Start Addr + OUT DX, AX ; Set Display Addr Low + + MOV AL, START_DISP_HI ; Display Start High Register + MOV AH, BH ; High 8 Bits of Start Addr + OUT DX, AX ; Set Display Addr High + + ; Wait for a Vertical Retrace to smooth out things + + MOV DX, INPUT_1 ; Input Status #1 Register + +@SW_WAIT1: + IN AL, DX ; Get VGA status + AND AL, VERT_RETRACE ; Vertical Retrace Start? + JZ @SW_WAIT1 ; If Not, wait for it + + ; Now Set the Horizontal Pixel Pan values + + OUT_8 ATTRIB_Ctrl, PIXEL_PAN_REG ; Select Pixel Pan Register + + MOV AX, [BP].SW_Xpos ; Get Desired X Offset + AND AL, 03 ; Get # of Pixels to Pan (0-3) + SHL AL, 1 ; Shift for 256 Color Mode + OUT DX, AL ; Fine tune the display! + +@SW_Exit: + POP BP ; Restore Saved Registers + RET 6 ; Exit and Clean up Stack + +SET_WINDOW ENDP + + +;============= +;GET_X_OFFSET% +;============= +; +; Returns the X coordinate of the Pixel currently display +; in the upper left corner of the display +; +; ENTRY: No Parameters are passed +; +; EXIT: AX = Current Horizontal Scroll Offset +; + + PUBLIC GET_X_OFFSET + +GET_X_OFFSET PROC FAR + + MOV AX, CURRENT_XOFFSET ; Get current horz offset + RET ; Exit & Clean Up Stack + +GET_X_OFFSET ENDP + + +;============= +;GET_Y_OFFSET% +;============= +; +; Returns the Y coordinate of the Pixel currently display +; in the upper left corner of the display +; +; ENTRY: No Parameters are passed +; +; EXIT: AX = Current Vertical Scroll Offset +; + + PUBLIC GET_Y_OFFSET + +GET_Y_OFFSET PROC FAR + + MOV AX, CURRENT_YOFFSET ; Get current vertical offset + RET ; Exit & Clean Up Stack + +GET_Y_OFFSET ENDP + + +;============ +;SYNC_DISPLAY +;============ +; +; Pauses the computer until the next Vertical Retrace starts +; +; ENTRY: No Parameters are passed +; +; EXIT: No meaningful values returned +; + + PUBLIC SYNC_DISPLAY + +SYNC_DISPLAY PROC FAR + + MOV DX, INPUT_1 ; Input Status #1 Register + + ; Wait for any current retrace to end + +@SD_WAIT0: + IN AL, DX ; Get VGA status + AND AL, VERT_RETRACE ; In Display mode yet? + JNZ @SD_WAIT0 ; If Not, wait for it + + ; Wait for the start of the next vertical retrace + +@SD_WAIT1: + IN AL, DX ; Get VGA status + AND AL, VERT_RETRACE ; Vertical Retrace Start? + JZ @SD_WAIT1 ; If Not, wait for it + + RET ; Exit & Clean Up Stack + +SYNC_DISPLAY ENDP + + + ; ===== TEXT DISPLAY ROUTINES ===== + +;================================================== +;GPRINTC (CharNum%, Xpos%, Ypos%, ColorF%, ColorB%) +;================================================== +; +; Draws an ASCII Text Character using the currently selected +; 8x8 font on the active display page. It would be a simple +; exercise to make this routine process variable height fonts. +; +; ENTRY: CharNum = ASCII character # to draw +; Xpos = X position to draw Character at +; Ypos = Y position of to draw Character at +; ColorF = Color to draw text character in +; ColorB = Color to set background to +; +; EXIT: No meaningful values returned +; + +GPC_STACK STRUC + GPC_Width DW ? ; Screen Width-1 + GPC_Lines DB ?,? ; Scan lines to Decode + GPC_T_SETS DW ? ; Saved Charset Segment + GPC_T_SETO DW ? ; Saved Charset Offset + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DD ? ; Caller + GPC_ColorB DB ?,? ; Background Color + GPC_ColorF DB ?,? ; Text Color + GPC_Ypos DW ? ; Y Position to Print at + GPC_Xpos DW ? ; X position to Print at + GPC_Char DB ?,? ; Character to Print +GPC_STACK ENDS + + PUBLIC GPRINTC + +GPRINTC PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + SUB SP, 8 ; Allocate WorkSpace on Stack + MOV BP, SP ; Set up Stack Frame + + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + + MOV AX, SCREEN_WIDTH ; Get Logical Line Width + MOV BX, AX ; BX = Screen Width + DEC BX ; = Screen Width-1 + MOV [BP].GPC_Width, BX ; Save for later use + + MUL [BP].GPC_Ypos ; Start of Line = Ypos * Width + ADD DI, AX ; DI -> Start of Line Ypos + + MOV AX, [BP].GPC_Xpos ; Get Xpos of Character + MOV CX, AX ; Save Copy of Xpos + SHR AX, 1 ; Bytes into Line = Xpos/4 + SHR AX, 1 ; Bytes into Line = Xpos/4 + ADD DI, AX ; DI -> (Xpos, Ypos) + + ;Get Source ADDR of Character Bit Map & Save + + MOV AL, [BP].GPC_Char ; Get Character # + TEST AL, 080h ; Is Hi Bit Set? + JZ @GPC_LowChar ; Nope, use low char set ptr + + AND AL, 07Fh ; Mask Out Hi Bit + MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset + MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment + JMP s @GPC_Set_Char ; Go Setup Character Ptr + +@GPC_LowChar: + + MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset + MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment + +@GPC_Set_Char: + MOV [BP].GPC_T_SETS, DX ; Save Segment on Stack + + MOV AH, 0 ; Valid #'s are 0..127 + SHL AX, 1 ; * 8 Bytes Per Bitmap + SHL AX, 1 ; * 8 Bytes Per Bitmap + SHL AX, 1 ; * 8 Bytes Per Bitmap + ADD BX, AX ; BX = Offset of Selected char + MOV [BP].GPC_T_SETO, BX ; Save Offset on Stack + + AND CX, PLANE_BITS ; Get Plane # + MOV CH, ALL_PLANES ; Get Initial Plane mask + SHL CH, CL ; And shift into position + AND CH, ALL_PLANES ; And mask to lower nibble + + MOV AL, 04 ; 4-Plane # = # of initial + SUB AL, CL ; shifts to align bit mask + MOV CL, AL ; Shift Count for SHL + + ;Get segment of character map + + OUT_8 SC_Index, MAP_MASK ; Setup Plane selections + INC DX ; DX -> SC_Data + + MOV AL, 08 ; 8 Lines to Process + MOV [BP].GPC_Lines, AL ; Save on Stack + + MOV DS, [BP].GPC_T_SETS ; Point to character set + +@GPC_DECODE_CHAR_BYTE: + + MOV SI, [BP].GPC_T_SETO ; Get DS:SI = String + + MOV BH, [SI] ; Get Bit Map + INC SI ; Point to Next Line + MOV [BP].GPC_T_SETO, SI ; And save new Pointer... + + mov ax,0 ; Clear AX + + ;mov bl,0 ; Clear BL + mov bl,0 + ROL BX, CL ; BL holds left edge bits + MOV SI, BX ; Use as Table Index + AND SI, CHAR_BITS ; Get Low Bits + MOV AL, Char_Plane_Data[SI] ; Get Mask in AL + JZ @GPC_NO_LEFT1BITS ; Skip if No Pixels to set + + MOV AH, [BP].GPC_ColorF ; Get Foreground Color + OUT DX, AL ; Set up Screen Mask + MOV ES:[DI], AH ; Write Foreground color + +@GPC_NO_LEFT1BITS: + XOR AL, CH ; Invert mask for Background + JZ @GPC_NO_LEFT0BITS ; Hey, no need for this + + MOV AH, [BP].GPC_ColorB ; Get background Color + OUT DX, AL ; Set up Screen Mask + MOV ES:[DI], AH ; Write Foreground color + + ;Now Do Middle/Last Band + +@GPC_NO_LEFT0BITS: + INC DI ; Point to next Byte + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + + MOV SI, BX ; Make Lookup Pointer + AND SI, CHAR_BITS ; Get Low Bits + MOV AL, Char_Plane_Data[SI] ; Get Mask in AL + JZ @GPC_NO_MIDDLE1BITS ; Skip if no pixels to set + + MOV AH, [BP].GPC_ColorF ; Get Foreground Color + OUT DX, AL ; Set up Screen Mask + MOV ES:[DI], AH ; Write Foreground color + +@GPC_NO_MIDDLE1BITS: + XOR AL, ALL_PLANES ; Invert mask for Background + JZ @GPC_NO_MIDDLE0BITS ; Hey, no need for this + + MOV AH, [BP].GPC_ColorB ; Get background Color + OUT DX, AL ; Set up Screen Mask + MOV ES:[DI], AH ; Write Foreground color + +@GPC_NO_MIDDLE0BITS: + XOR CH, ALL_PLANES ; Invert Clip Mask + CMP CL, 4 ; Aligned by 4? + JZ @GPC_NEXT_LINE ; If so, Exit now.. + + INC DI ; Point to next Byte + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + + MOV SI, BX ; Make Lookup Pointer + AND SI, CHAR_BITS ; Get Low Bits + MOV AL, Char_Plane_Data[SI] ; Get Mask in AL + JZ @GPC_NO_RIGHT1BITS ; Skip if No Pixels to set + + MOV AH, [BP].GPC_ColorF ; Get Foreground Color + OUT DX, AL ; Set up Screen Mask + MOV ES:[DI], AH ; Write Foreground color + +@GPC_NO_RIGHT1BITS: + + XOR AL, CH ; Invert mask for Background + JZ @GPC_NO_RIGHT0BITS ; Hey, no need for this + + MOV AH, [BP].GPC_ColorB ; Get background Color + OUT DX, AL ; Set up Screen Mask + MOV ES:[DI], AH ; Write Foreground color + +@GPC_NO_RIGHT0BITS: + DEC DI ; Adjust for Next Line Advance + +@GPC_NEXT_LINE: + ADD DI, [BP].GPC_Width ; Point to Next Line + XOR CH, CHAR_BITS ; Flip the Clip mask back + + DEC [BP].GPC_Lines ; Count Down Lines + JZ @GPC_EXIT ; Ok... Done! + + JMP @GPC_DECODE_CHAR_BYTE ; Again! Hey! + +@GPC_EXIT: + ADD SP, 08 ; Deallocate stack workspace + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + RET 10 ; Exit and Clean up Stack + +GPRINTC ENDP + + +;========================================== +;TGPRINTC (CharNum%, Xpos%, Ypos%, ColorF%) +;========================================== +; +; Transparently draws an ASCII Text Character using the +; currently selected 8x8 font on the active display page. +; +; ENTRY: CharNum = ASCII character # to draw +; Xpos = X position to draw Character at +; Ypos = Y position of to draw Character at +; ColorF = Color to draw text character in +; +; EXIT: No meaningful values returned +; + +TGP_STACK STRUC + TGP_Width DW ? ; Screen Width-1 + TGP_Lines DB ?,? ; Scan lines to Decode + TGP_T_SETS DW ? ; Saved Charset Segment + TGP_T_SETO DW ? ; Saved Charset Offset + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DD ? ; Caller + TGP_ColorF DB ?,? ; Text Color + TGP_Ypos DW ? ; Y Position to Print at + TGP_Xpos DW ? ; X position to Print at + TGP_Char DB ?,? ; Character to Print +TGP_STACK ENDS + + PUBLIC TGPRINTC + +TGPRINTC PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + SUB SP, 8 ; Allocate WorkSpace on Stack + MOV BP, SP ; Set up Stack Frame + + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + + MOV AX, SCREEN_WIDTH ; Get Logical Line Width + MOV BX, AX ; BX = Screen Width + DEC BX ; = Screen Width-1 + MOV [BP].TGP_Width, BX ; Save for later use + + MUL [BP].TGP_Ypos ; Start of Line = Ypos * Width + ADD DI, AX ; DI -> Start of Line Ypos + + MOV AX, [BP].TGP_Xpos ; Get Xpos of Character + MOV CX, AX ; Save Copy of Xpos + SHR AX, 1 ; Bytes into Line = Xpos/4 + SHR AX, 1 ; Bytes into Line = Xpos/4 + ADD DI, AX ; DI -> (Xpos, Ypos) + + ;Get Source ADDR of Character Bit Map & Save + + MOV AL, [BP].TGP_Char ; Get Character # + TEST AL, 080h ; Is Hi Bit Set? + JZ @TGP_LowChar ; Nope, use low char set ptr + + AND AL, 07Fh ; Mask Out Hi Bit + MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset + MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment + JMP s @TGP_Set_Char ; Go Setup Character Ptr + +@TGP_LowChar: + + MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset + MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment + +@TGP_Set_Char: + MOV [BP].TGP_T_SETS, DX ; Save Segment on Stack + + MOV AH, 0 ; Valid #'s are 0..127 + SHL AX, 1 ; * 8 Bytes Per Bitmap + SHL AX, 1 ; * 8 Bytes Per Bitmap + SHL AX, 1 ; * 8 Bytes Per Bitmap + ADD BX, AX ; BX = Offset of Selected char + MOV [BP].TGP_T_SETO, BX ; Save Offset on Stack + + AND CX, PLANE_BITS ; Get Plane # + MOV CH, ALL_PLANES ; Get Initial Plane mask + SHL CH, CL ; And shift into position + AND CH, ALL_PLANES ; And mask to lower nibble + + MOV AL, 04 ; 4-Plane # = # of initial + SUB AL, CL ; shifts to align bit mask + MOV CL, AL ; Shift Count for SHL + + ;Get segment of character map + + OUT_8 SC_Index, MAP_MASK ; Setup Plane selections + INC DX ; DX -> SC_Data + + MOV AL, 08 ; 8 Lines to Process + MOV [BP].TGP_Lines, AL ; Save on Stack + + MOV DS, [BP].TGP_T_SETS ; Point to character set + +@TGP_DECODE_CHAR_BYTE: + + MOV SI, [BP].TGP_T_SETO ; Get DS:SI = String + + MOV BH, [SI] ; Get Bit Map + INC SI ; Point to Next Line + MOV [BP].TGP_T_SETO, SI ; And save new Pointer... + + MOV AH, [BP].TGP_ColorF ; Get Foreground Color + + mov bl,0 ; Clear BL + ROL BX, CL ; BL holds left edge bits + MOV SI, BX ; Use as Table Index + AND SI, CHAR_BITS ; Get Low Bits + MOV AL, Char_Plane_Data[SI] ; Get Mask in AL + JZ @TGP_NO_LEFT1BITS ; Skip if No Pixels to set + + OUT DX, AL ; Set up Screen Mask + MOV ES:[DI], AH ; Write Foreground color + + ;Now Do Middle/Last Band + +@TGP_NO_LEFT1BITS: + + INC DI ; Point to next Byte + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + + MOV SI, BX ; Make Lookup Pointer + AND SI, CHAR_BITS ; Get Low Bits + MOV AL, Char_Plane_Data[SI] ; Get Mask in AL + JZ @TGP_NO_MIDDLE1BITS ; Skip if no pixels to set + + OUT DX, AL ; Set up Screen Mask + MOV ES:[DI], AH ; Write Foreground color + +@TGP_NO_MIDDLE1BITS: + XOR CH, ALL_PLANES ; Invert Clip Mask + CMP CL, 4 ; Aligned by 4? + JZ @TGP_NEXT_LINE ; If so, Exit now.. + + INC DI ; Point to next Byte + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + + MOV SI, BX ; Make Lookup Pointer + AND SI, CHAR_BITS ; Get Low Bits + MOV AL, Char_Plane_Data[SI] ; Get Mask in AL + JZ @TGP_NO_RIGHT1BITS ; Skip if No Pixels to set + + OUT DX, AL ; Set up Screen Mask + MOV ES:[DI], AH ; Write Foreground color + +@TGP_NO_RIGHT1BITS: + + DEC DI ; Adjust for Next Line Advance + +@TGP_NEXT_LINE: + ADD DI, [BP].TGP_Width ; Point to Next Line + XOR CH, CHAR_BITS ; Flip the Clip mask back + + DEC [BP].TGP_Lines ; Count Down Lines + JZ @TGP_EXIT ; Ok... Done! + + JMP @TGP_DECODE_CHAR_BYTE ; Again! Hey! + +@TGP_EXIT: + ADD SP, 08 ; Deallocate stack workspace + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + RET 8 ; Exit and Clean up Stack + +TGPRINTC ENDP + + +;=============================================================== +;PRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%) +;=============================================================== +; +; Routine to quickly Print a null terminated ASCII string on the +; active display page up to a maximum length. +; +; ENTRY: String = Far Pointer to ASCII string to print +; MaxLen = # of characters to print if no null found +; Xpos = X position to draw Text at +; Ypos = Y position of to draw Text at +; ColorF = Color to draw text in +; ColorB = Color to set background to +; +; EXIT: No meaningful values returned +; + +PS_STACK STRUC + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DD ? ; Caller + PS_ColorB DW ? ; Background Color + PS_ColorF DW ? ; Text Color + PS_Ypos DW ? ; Y Position to Print at + PS_Xpos DW ? ; X position to Print at + PS_Len DW ? ; Maximum Length of string to print + PS_Text DW ?,? ; Far Ptr to Text String +PS_STACK ENDS + + PUBLIC PRINT_STR + +PRINT_STR PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + MOV BP, SP ; Set up Stack Frame + +@PS_Print_It: + + MOV CX, [BP].PS_Len ; Get Remaining text Length + JCXZ @PS_Exit ; Exit when out of text + + LES DI, d [BP].PS_Text ; ES:DI -> Current Char in Text + MOV AL, ES:[DI] ; AL = Text Character + AND AX, 00FFh ; Clear High Word + JZ @PS_Exit ; Exit if null character + + DEC [BP].PS_Len ; Remaining Text length-- + INC [BP].PS_Text ; Point to Next text char + + ; Set up Call to GPRINTC + + PUSH AX ; Set Character Parameter + MOV BX, [BP].PS_Xpos ; Get Xpos + PUSH BX ; Set Xpos Parameter + ADD BX, 8 ; Advance 1 Char to Right + MOV [BP].PS_Xpos, BX ; Save for next time through + + MOV BX, [BP].PS_Ypos ; Get Ypos + PUSH BX ; Set Ypos Parameter + + MOV BX, [BP].PS_ColorF ; Get Text Color + PUSH BX ; Set ColorF Parameter + + MOV BX, [BP].PS_ColorB ; Get Background Color + PUSH BX ; Set ColorB Parameter + + CALL f GPRINTC ; Print Character! + JMP s @PS_Print_It ; Process next character + +@PS_Exit: + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + RET 14 ; Exit and Clean up Stack + +PRINT_STR ENDP + + +;================================================================ +;TPRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%) +;================================================================ +; +; Routine to quickly transparently Print a null terminated ASCII +; string on the active display page up to a maximum length. +; +; ENTRY: String = Far Pointer to ASCII string to print +; MaxLen = # of characters to print if no null found +; Xpos = X position to draw Text at +; Ypos = Y position of to draw Text at +; ColorF = Color to draw text in +; +; EXIT: No meaningful values returned +; + +TPS_STACK STRUC + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DD ? ; Caller + TPS_ColorF DW ? ; Text Color + TPS_Ypos DW ? ; Y Position to Print at + TPS_Xpos DW ? ; X position to Print at + TPS_Len DW ? ; Maximum Length of string to print + TPS_Text DW ?,? ; Far Ptr to Text String +TPS_STACK ENDS + + PUBLIC TPRINT_STR + +TPRINT_STR PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + MOV BP, SP ; Set up Stack Frame + +@TPS_Print_It: + + MOV CX, [BP].TPS_Len ; Get Remaining text Length + JCXZ @TPS_Exit ; Exit when out of text + + LES DI, d [BP].TPS_Text ; ES:DI -> Current Char in Text + MOV AL, ES:[DI] ; AL = Text Character + AND AX, 00FFh ; Clear High Word + JZ @TPS_Exit ; Exit if null character + + DEC [BP].TPS_Len ; Remaining Text length-- + INC [BP].TPS_Text ; Point to Next text char + + ; Set up Call to TGPRINTC + + PUSH AX ; Set Character Parameter + MOV BX, [BP].TPS_Xpos ; Get Xpos + PUSH BX ; Set Xpos Parameter + ADD BX, 8 ; Advance 1 Char to Right + MOV [BP].TPS_Xpos, BX ; Save for next time through + + MOV BX, [BP].TPS_Ypos ; Get Ypos + PUSH BX ; Set Ypos Parameter + + MOV BX, [BP].TPS_ColorF ; Get Text Color + PUSH BX ; Set ColorF Parameter + + CALL f TGPRINTC ; Print Character! + JMP s @TPS_Print_It ; Process next character + +@TPS_Exit: + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + RET 12 ; Exit and Clean up Stack + +TPRINT_STR ENDP + + +;=========================================== +;SET_DISPLAY_FONT(SEG FontData, FontNumber%) +;=========================================== +; +; Allows the user to specify their own font data for +; wither the lower or upper 128 characters. +; +; ENTRY: FontData = Far Pointer to Font Bitmaps +; FontNumber = Which half of set this is +; = 0, Lower 128 characters +; = 1, Upper 128 characters +; +; EXIT: No meaningful values returned +; + +SDF_STACK STRUC + DW ? ; BP + DD ? ; Caller + SDF_Which DW ? ; Hi Table/Low Table Flag + SDF_Font DD ? ; Far Ptr to Font Table +SDF_STACK ENDS + + PUBLIC SET_DISPLAY_FONT + +SET_DISPLAY_FONT PROC FAR + + PUSH BP ; Preserve Registers + MOV BP, SP ; Set up Stack Frame + + LES DI, [BP].SDF_Font ; Get Far Ptr to Font + + MOV SI, o CHARSET_LOW ; Assume Lower 128 chars + TEST [BP].SDF_Which, 1 ; Font #1 selected? + JZ @SDF_Set_Font ; If not, skip ahead + + MOV SI, o CHARSET_HI ; Ah, really it's 128-255 + +@SDF_Set_Font: + MOV [SI], DI ; Set Font Pointer Offset + MOV [SI+2], ES ; Set Font Pointer Segment + + POP BP ; Restore Registers + RET 6 ; We are Done.. Outa here + +SET_DISPLAY_FONT ENDP + + + ; ===== BITMAP (SPRITE) DISPLAY ROUTINES ===== + +;====================================================== +;DRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%) +;====================================================== +; +; Draws a variable sized Graphics Bitmap such as a +; picture or an Icon on the current Display Page in +; Mode X. The Bitmap is stored in a linear byte array +; corresponding to (0,0) (1,0), (2,0) .. (Width, Height) +; This is the same linear manner as mode 13h graphics. +; +; ENTRY: Image = Far Pointer to Bitmap Data +; Xpos = X position to Place Upper Left pixel at +; Ypos = Y position to Place Upper Left pixel at +; Width = Width of the Bitmap in Pixels +; Height = Height of the Bitmap in Pixels +; +; EXIT: No meaningful values returned +; + +DB_STACK STRUC + DB_LineO DW ? ; Offset to Next Line + DB_PixCount DW ? ; (Minimum) # of Pixels/Line + DB_Start DW ? ; Addr of Upper Left Pixel + DB_PixSkew DW ? ; # of bytes to Adjust EOL + DB_SkewFlag DW ? ; Extra Pix on Plane Flag + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DD ? ; Caller + DB_Height DW ? ; Height of Bitmap in Pixels + DB_Width DW ? ; Width of Bitmap in Pixels + DB_Ypos DW ? ; Y position to Draw Bitmap at + DB_Xpos DW ? ; X position to Draw Bitmap at + DB_Image DD ? ; Far Pointer to Graphics Bitmap +DB_STACK ENDS + + PUBLIC DRAW_BITMAP + +DRAW_BITMAP PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + SUB SP, 10 ; Allocate workspace + MOV BP, SP ; Set up Stack Frame + + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + CLD ; Direction Flag = Forward + + MOV AX, [BP].DB_Ypos ; Get UL Corner Ypos + MUL SCREEN_WIDTH ; AX = Offset to Line Ypos + + MOV BX, [BP].DB_Xpos ; Get UL Corner Xpos + MOV CL, BL ; Save Plane # in CL + SHR BX, 1 ; Xpos/4 = Offset Into Line + SHR BX, 1 ; Xpos/4 = Offset Into Line + + ADD DI, AX ; ES:DI -> Start of Line + ADD DI, BX ; ES:DI -> Upper Left Pixel + MOV [BP].DB_Start, DI ; Save Starting Addr + + ; Compute line to line offset + + MOV BX, [BP].DB_Width ; Get Width of Image + MOV DX, BX ; Save Copy in DX + SHR BX, 1 ; /4 = width in bands + SHR BX, 1 ; /4 = width in bands + MOV AX, SCREEN_WIDTH ; Get Screen Width + SUB AX, BX ; - (Bitmap Width/4) + + MOV [BP].DB_LineO, AX ; Save Line Width offset + MOV [BP].DB_PixCount, BX ; Minimum # pix to copy + + AND DX, PLANE_BITS ; Get "partial band" size (0-3) + MOV [BP].DB_PixSkew, DX ; Also End of Line Skew + MOV [BP].DB_SkewFlag, DX ; Save as Flag/Count + + AND CX, PLANE_BITS ; CL = Starting Plane # + MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select + SHL AH, CL ; Select correct Plane + OUT_16 SC_Index, AX ; Select Plane... + MOV BH, AH ; BH = Saved Plane Mask + MOV BL, 4 ; BL = Planes to Copy + +@DB_COPY_PLANE: + + LDS SI, [BP].DB_Image ; DS:SI-> Source Image + MOV DX, [BP].DB_Height ; # of Lines to Copy + MOV DI, [BP].DB_Start ; ES:DI-> Dest pos + +@DB_COPY_LINE: + MOV CX, [BP].DB_PixCount ; Min # to copy + + TEST CL, 0FCh ; 16+PixWide? + JZ @DB_COPY_REMAINDER ; Nope... + + ; Pixel Copy loop has been unrolled to x4 + +@DB_COPY_LOOP: + MOVSB ; Copy Bitmap Pixel + ADD SI, 3 ; Skip to Next Byte in same plane + MOVSB ; Copy Bitmap Pixel + ADD SI, 3 ; Skip to Next Byte in same plane + MOVSB ; Copy Bitmap Pixel + ADD SI, 3 ; Skip to Next Byte in same plane + MOVSB ; Copy Bitmap Pixel + ADD SI, 3 ; Skip to Next Byte in same plane + + SUB CL, 4 ; Pixels to Copy=-4 + TEST CL, 0FCh ; 4+ Pixels Left? + JNZ @DB_COPY_LOOP ; if so, do another block + +@DB_COPY_REMAINDER: + JCXZ @DB_NEXT_LINE ; Any Pixels left on line + +@DB_COPY2: + MOVSB ; Copy Bitmap Pixel + ADD SI,3 ; Skip to Next Byte in same plane + LOOPx CX, @DB_COPY2 ; Pixels to Copy--, Loop until done + +@DB_NEXT_LINE: + + ; any Partial Pixels? (some planes only) + + OR CX, [BP].DB_SkewFlag ; Get Skew Count + JZ @DB_NEXT2 ; if no partial pixels + + MOVSB ; Copy Bitmap Pixel + DEC DI ; Back up to align + DEC SI ; Back up to align + +@DB_NEXT2: + ADD SI, [BP].DB_PixSkew ; Adjust Skew + ADD DI, [BP].DB_LineO ; Set to Next Display Line + LOOPx DX, @DB_COPY_LINE ; Lines to Copy--, Loop if more + + ; Copy Next Plane.... + + DEC BL ; Planes to Go-- + JZ @DB_Exit ; Hey! We are done + + ROL BH, 1 ; Next Plane in line... + OUT_8 SC_Data, BH ; Select Plane + + CMP AL, 12h ; Carry Set if AL=11h + ADC [BP].DB_Start, 0 ; Screen Addr =+Carry + INC w [BP].DB_Image ; Start @ Next Byte + + SUB [BP].DB_SkewFlag, 1 ; Reduce Planes to Skew + ADC [BP].DB_SkewFlag, 0 ; Back to 0 if it was -1 + + JMP s @DB_COPY_PLANE ; Go Copy the Next Plane + +@DB_Exit: + ADD SP, 10 ; Deallocate workspace + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + RET 12 ; Exit and Clean up Stack + +DRAW_BITMAP ENDP + + +;======================================================= +;TDRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%) +;======================================================= +; +; Transparently Draws a variable sized Graphics Bitmap +; such as a picture or an Icon on the current Display Page +; in Mode X. Pixels with a value of 0 are not drawn, +; leaving the previous "background" contents intact. +; +; The Bitmap format is the same as for the DRAW_BITMAP function. +; +; ENTRY: Image = Far Pointer to Bitmap Data +; Xpos = X position to Place Upper Left pixel at +; Ypos = Y position to Place Upper Left pixel at +; Width = Width of the Bitmap in Pixels +; Height = Height of the Bitmap in Pixels +; +; EXIT: No meaningful values returned +; + +TB_STACK STRUC + TB_LineO DW ? ; Offset to Next Line + TB_PixCount DW ? ; (Minimum) # of Pixels/Line + TB_Start DW ? ; Addr of Upper Left Pixel + TB_PixSkew DW ? ; # of bytes to Adjust EOL + TB_SkewFlag DW ? ; Extra Pix on Plane Flag + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DD ? ; Caller + TB_Height DW ? ; Height of Bitmap in Pixels + TB_Width DW ? ; Width of Bitmap in Pixels + TB_Ypos DW ? ; Y position to Draw Bitmap at + TB_Xpos DW ? ; X position to Draw Bitmap at + TB_Image DD ? ; Far Pointer to Graphics Bitmap +TB_STACK ENDS + + PUBLIC TDRAW_BITMAP + +TDRAW_BITMAP PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + SUB SP, 10 ; Allocate workspace + MOV BP, SP ; Set up Stack Frame + + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + CLD ; Direction Flag = Forward + + MOV AX, [BP].TB_Ypos ; Get UL Corner Ypos + MUL SCREEN_WIDTH ; AX = Offset to Line Ypos + + MOV BX, [BP].TB_Xpos ; Get UL Corner Xpos + MOV CL, BL ; Save Plane # in CL + SHR BX, 1 ; Xpos/4 = Offset Into Line + SHR BX, 1 ; Xpos/4 = Offset Into Line + + ADD DI, AX ; ES:DI -> Start of Line + ADD DI, BX ; ES:DI -> Upper Left Pixel + MOV [BP].TB_Start, DI ; Save Starting Addr + + ; Compute line to line offset + + MOV BX, [BP].TB_Width ; Get Width of Image + MOV DX, BX ; Save Copy in DX + SHR BX, 1 ; /4 = width in bands + SHR BX, 1 ; /4 = width in bands + MOV AX, SCREEN_WIDTH ; Get Screen Width + SUB AX, BX ; - (Bitmap Width/4) + + MOV [BP].TB_LineO, AX ; Save Line Width offset + MOV [BP].TB_PixCount, BX ; Minimum # pix to copy + + AND DX, PLANE_BITS ; Get "partial band" size (0-3) + MOV [BP].TB_PixSkew, DX ; Also End of Line Skew + MOV [BP].TB_SkewFlag, DX ; Save as Flag/Count + + AND CX, PLANE_BITS ; CL = Starting Plane # + MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select + SHL AH, CL ; Select correct Plane + OUT_16 SC_Index, AX ; Select Plane... + MOV BH, AH ; BH = Saved Plane Mask + MOV BL, 4 ; BL = Planes to Copy + +@TB_COPY_PLANE: + + LDS SI, [BP].TB_Image ; DS:SI-> Source Image + MOV DX, [BP].TB_Height ; # of Lines to Copy + MOV DI, [BP].TB_Start ; ES:DI-> Dest pos + + ; Here AH is set with the value to be considered + ; "Transparent". It can be changed! + + MOV AH, 0 ; Value to Detect 0 + +@TB_COPY_LINE: + MOV CX, [BP].TB_PixCount ; Min # to copy + + TEST CL, 0FCh ; 16+PixWide? + JZ @TB_COPY_REMAINDER ; Nope... + + ; Pixel Copy loop has been unrolled to x4 + +@TB_COPY_LOOP: + LODSB ; Get Pixel Value in AL + ADD SI, 3 ; Skip to Next Byte in same plane + CMP AL, AH ; It is "Transparent"? + JE @TB_SKIP_01 ; Skip ahead if so + MOV ES:[DI], AL ; Copy Pixel to VGA screen + +@TB_SKIP_01: + LODSB ; Get Pixel Value in AL + ADD SI, 3 ; Skip to Next Byte in same plane + CMP AL, AH ; It is "Transparent"? + JE @TB_SKIP_02 ; Skip ahead if so + MOV ES:[DI+1], AL ; Copy Pixel to VGA screen + +@TB_SKIP_02: + LODSB ; Get Pixel Value in AL + ADD SI, 3 ; Skip to Next Byte in same plane + CMP AL, AH ; It is "Transparent"? + JE @TB_SKIP_03 ; Skip ahead if so + MOV ES:[DI+2], AL ; Copy Pixel to VGA screen + +@TB_SKIP_03: + LODSB ; Get Pixel Value in AL + ADD SI, 3 ; Skip to Next Byte in same plane + CMP AL, AH ; It is "Transparent"? + JE @TB_SKIP_04 ; Skip ahead if so + MOV ES:[DI+3], AL ; Copy Pixel to VGA screen + +@TB_SKIP_04: + ADD DI, 4 ; Adjust Pixel Write Location + SUB CL, 4 ; Pixels to Copy=-4 + TEST CL, 0FCh ; 4+ Pixels Left? + JNZ @TB_COPY_LOOP ; if so, do another block + +@TB_COPY_REMAINDER: + JCXZ @TB_NEXT_LINE ; Any Pixels left on line + +@TB_COPY2: + LODSB ; Get Pixel Value in AL + ADD SI, 3 ; Skip to Next Byte in same plane + CMP AL, AH ; It is "Transparent"? + JE @TB_SKIP_05 ; Skip ahead if so + MOV ES:[DI], AL ; Copy Pixel to VGA screen + +@TB_SKIP_05: + INC DI ; Advance Dest Addr + LOOPx CX, @TB_COPY2 ; Pixels to Copy--, Loop until done + +@TB_NEXT_LINE: + + ; any Partial Pixels? (some planes only) + + OR CX, [BP].TB_SkewFlag ; Get Skew Count + JZ @TB_NEXT2 ; if no partial pixels + + LODSB ; Get Pixel Value in AL + DEC SI ; Backup to Align + CMP AL, AH ; It is "Transparent"? + JE @TB_NEXT2 ; Skip ahead if so + MOV ES:[DI], AL ; Copy Pixel to VGA screen + +@TB_NEXT2: + ADD SI, [BP].TB_PixSkew ; Adjust Skew + ADD DI, [BP].TB_LineO ; Set to Next Display Line + LOOPx DX, @TB_COPY_LINE ; Lines to Copy--, Loop if More + + ;Copy Next Plane.... + + DEC BL ; Planes to Go-- + JZ @TB_Exit ; Hey! We are done + + ROL BH, 1 ; Next Plane in line... + OUT_8 SC_Data, BH ; Select Plane + + CMP AL, 12h ; Carry Set if AL=11h + ADC [BP].TB_Start, 0 ; Screen Addr =+Carry + INC w [BP].TB_Image ; Start @ Next Byte + + SUB [BP].TB_SkewFlag, 1 ; Reduce Planes to Skew + ADC [BP].TB_SkewFlag, 0 ; Back to 0 if it was -1 + + JMP @TB_COPY_PLANE ; Go Copy the next Plane + +@TB_Exit: + ADD SP, 10 ; Deallocate workspace + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + RET 12 ; Exit and Clean up Stack + +TDRAW_BITMAP ENDP + + + ; ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES ===== + +;================================== +;COPY_PAGE (SourcePage%, DestPage%) +;================================== +; +; Duplicate on display page onto another +; +; ENTRY: SourcePage = Display Page # to Duplicate +; DestPage = Display Page # to hold copy +; +; EXIT: No meaningful values returned +; + +CP_STACK STRUC + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DD ? ; Caller + CP_DestP DW ? ; Page to hold copied image + CP_SourceP DW ? ; Page to Make copy from +CP_STACK ENDS + + PUBLIC COPY_PAGE + +COPY_PAGE PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + MOV BP, SP ; Set up Stack Frame + CLD ; Block Xfer Forwards + + ; Make sure Page #'s are valid + + MOV AX, [BP].CP_SourceP ; Get Source Page # + CMP AX, LAST_PAGE ; is it > Max Page #? + JAE @CP_Exit ; if so, abort + + MOV BX, [BP].CP_DestP ; Get Destination Page # + CMP BX, LAST_PAGE ; is it > Max Page #? + JAE @CP_Exit ; if so, abort + + CMP AX, BX ; Pages #'s the same? + JE @CP_Exit ; if so, abort + + ; Setup DS:SI and ES:DI to Video Pages + + SHL BX, 1 ; Scale index to Word + MOV DI, PAGE_ADDR[BX] ; Offset to Dest Page + + MOV BX, AX ; Index to Source page + SHL BX, 1 ; Scale index to Word + MOV SI, PAGE_ADDR[BX] ; Offset to Source Page + + MOV CX, PAGE_SIZE ; Get size of Page + MOV AX, CURRENT_SEGMENT ; Get Video Mem Segment + MOV ES, AX ; ES:DI -> Dest Page + MOV DS, AX ; DS:SI -> Source Page + + ; Setup VGA registers for Mem to Mem copy + + OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on + OUT_16 SC_Index, ALL_PLANES_ON ; Copy all Planes + + ; Note.. Do *NOT* use MOVSW or MOVSD - they will + ; Screw with the latches which are 8 bits x 4 + + REP MOVSB ; Copy entire Page! + + ; Reset VGA for normal memory access + + OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = off + +@CP_Exit: + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + RET 4 ; Exit and Clean up Stack + +COPY_PAGE ENDP + + +;========================================================================== +;COPY_BITMAP (SourcePage%, X1%, Y1%, X2%, Y2%, DestPage%, DestX1%, DestY1%) +;========================================================================== +; +; Copies a Bitmap Image from one Display Page to Another +; This Routine is Limited to copying Images with the same +; Plane Alignment. To Work: (X1 MOD 4) must = (DestX1 MOD 4) +; Copying an Image to the Same Page is supported, but results +; may be defined when the when the rectangular areas +; (X1, Y1) - (X2, Y2) and (DestX1, DestY1) - +; (DestX1+(X2-X1), DestY1+(Y2-Y1)) overlap... +; No Paramter checking to done to insure that +; X2 >= X1 and Y2 >= Y1. Be Careful... +; +; ENTRY: SourcePage = Display Page # with Source Image +; X1 = Upper Left Xpos of Source Image +; Y1 = Upper Left Ypos of Source Image +; X2 = Lower Right Xpos of Source Image +; Y2 = Lower Right Ypos of Source Image +; DestPage = Display Page # to copy Image to +; DestX1 = Xpos to Copy UL Corner of Image to +; DestY1 = Ypos to Copy UL Corner of Image to +; +; EXIT: AX = Success Flag: 0 = Failure / -1= Success +; + +CB_STACK STRUC + CB_Height DW ? ; Height of Image in Lines + CB_Width DW ? ; Width of Image in "bands" + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DD ? ; Caller + CB_DestY1 DW ? ; Destination Ypos + CB_DestX1 DW ? ; Destination Xpos + CB_DestP DW ? ; Page to Copy Bitmap To + CB_Y2 DW ? ; LR Ypos of Image + CB_X2 DW ? ; LR Xpos of Image + CB_Y1 DW ? ; UL Ypos of Image + CB_X1 DW ? ; UL Xpos of Image + CB_SourceP DW ? ; Page containing Source Bitmap +CB_STACK ENDS + + PUBLIC COPY_BITMAP + +COPY_BITMAP PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + SUB SP, 4 ; Allocate WorkSpace on Stack + MOV BP, SP ; Set up Stack Frame + + ; Prep Registers (and keep jumps short!) + + MOV ES, CURRENT_SEGMENT ; ES -> VGA Ram + CLD ; Block Xfer Forwards + + ; Make sure Parameters are valid + + MOV BX, [BP].CB_SourceP ; Get Source Page # + CMP BX, LAST_PAGE ; is it > Max Page #? + JAE @CB_Abort ; if so, abort + + MOV CX, [BP].CB_DestP ; Get Destination Page # + CMP CX, LAST_PAGE ; is it > Max Page #? + JAE @CB_Abort ; if so, abort + + MOV AX, [BP].CB_X1 ; Get Source X1 + XOR AX, [BP].CB_DestX1 ; Compare Bits 0-1 + AND AX, PLANE_BITS ; Check Plane Bits + JNZ @CB_Abort ; They should cancel out + + ; Setup for Copy processing + + OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select + OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on + + ; Compute Info About Images, Setup ES:SI & ES:DI + + MOV AX, [BP].CB_Y2 ; Height of Bitmap in lines + SUB AX, [BP].CB_Y1 ; is Y2 - Y1 + 1 + INC AX ; (add 1 since were not 0 based) + MOV [BP].CB_Height, AX ; Save on Stack for later use + + MOV AX, [BP].CB_X2 ; Get # of "Bands" of 4 Pixels + MOV DX, [BP].CB_X1 ; the Bitmap Occupies as X2-X1 + SHR AX, 1 ; Get X2 Band (X2 / 4) + SHR DX, 1 ; Get X1 Band (X1 / 4) + SHR AX, 1 ; Get X2 Band (X2 / 4) + SHR DX, 1 ; Get X1 Band (X1 / 4) + SUB AX, DX ; AX = # of Bands - 1 + INC AX ; AX = # of Bands + MOV [BP].CB_Width, AX ; Save on Stack for later use + + SHL BX, 1 ; Scale Source Page to Word + MOV SI, PAGE_ADDR[BX] ; SI = Offset of Source Page + MOV AX, [BP].CB_Y1 ; Get Source Y1 Line + MUL SCREEN_WIDTH ; AX = Offset to Line Y1 + ADD SI, AX ; SI = Offset to Line Y1 + MOV AX, [BP].CB_X1 ; Get Source X1 + SHR AX, 1 ; X1 / 4 = Byte offset + SHR AX, 1 ; X1 / 4 = Byte offset + ADD SI, AX ; SI = Byte Offset to (X1,Y1) + + MOV BX, CX ; Dest Page Index to BX + SHL BX, 1 ; Scale Source Page to Word + MOV DI, PAGE_ADDR[BX] ; DI = Offset of Dest Page + MOV AX, [BP].CB_DestY1 ; Get Dest Y1 Line + MUL SCREEN_WIDTH ; AX = Offset to Line Y1 + ADD DI, AX ; DI = Offset to Line Y1 + MOV AX, [BP].CB_DestX1 ; Get Dest X1 + SHR AX, 1 ; X1 / 4 = Byte offset + SHR AX, 1 ; X1 / 4 = Byte offset + ADD DI, AX ; DI = Byte Offset to (D-X1,D-Y1) + + MOV CX, [BP].CB_Width ; CX = Width of Image (Bands) + DEC CX ; CX = 1? + JE @CB_Only_One_Band ; 0 Means Image Width of 1 Band + + MOV BX, [BP].CB_X1 ; Get Source X1 + AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 00?) + JZ @CB_Check_Right ; if so, check right alignment + JNZ @CB_Left_Band ; not aligned? well.. + +@CB_Abort: + mov ax,0 ; Return False (Failure) + JMP @CB_Exit ; and Finish Up + + ; Copy when Left & Right Clip Masks overlap... + +@CB_Only_One_Band: + MOV BX, [BP].CB_X1 ; Get Left Clip Mask + AND BX, PLANE_BITS ; Mask out Row # + MOV AL, Left_Clip_Mask[BX] ; Get Left Edge Mask + MOV BX, [BP].CB_X2 ; Get Right Clip Mask + AND BX, PLANE_BITS ; Mask out Row # + AND AL, Right_Clip_Mask[BX] ; Get Right Edge Mask byte + + OUT_8 SC_Data, AL ; Clip For Left & Right Masks + + MOV CX, [BP].CB_Height ; CX = # of Lines to Copy + MOV DX, SCREEN_WIDTH ; DX = Width of Screen + mov bx,0 ; BX = Offset into Image + +@CB_One_Loop: + MOV AL, ES:[SI+BX] ; Load Latches + MOV ES:[DI+BX], AL ; Unload Latches + ADD BX, DX ; Advance Offset to Next Line + LOOPjz CX, @CB_One_Done ; Exit Loop if Finished + + MOV AL, ES:[SI+BX] ; Load Latches + MOV ES:[DI+BX], AL ; Unload Latches + ADD BX, DX ; Advance Offset to Next Line + LOOPx CX, @CB_One_Loop ; Loop until Finished + +@CB_One_Done: + JMP @CB_Finish ; Outa Here! + + ; Copy Left Edge of Bitmap + +@CB_Left_Band: + + OUT_8 SC_Data, Left_Clip_Mask[BX] ; Set Left Edge Plane Mask + + MOV CX, [BP].CB_Height ; CX = # of Lines to Copy + MOV DX, SCREEN_WIDTH ; DX = Width of Screen + mov bx,0 ; BX = Offset into Image + +@CB_Left_Loop: + MOV AL, ES:[SI+BX] ; Load Latches + MOV ES:[DI+BX], AL ; Unload Latches + ADD BX, DX ; Advance Offset to Next Line + LOOPjz CX, @CB_Left_Done ; Exit Loop if Finished + + MOV AL, ES:[SI+BX] ; Load Latches + MOV ES:[DI+BX], AL ; Unload Latches + ADD BX, DX ; Advance Offset to Next Line + LOOPx CX, @CB_Left_Loop ; Loop until Finished + +@CB_Left_Done: + INC DI ; Move Dest Over 1 band + INC SI ; Move Source Over 1 band + DEC [BP].CB_Width ; Band Width-- + + ; Determine if Right Edge of Bitmap needs special copy + +@CB_Check_Right: + MOV BX, [BP].CB_X2 ; Get Source X2 + AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 11?) + CMP BL, 03h ; Plane = 3? + JE @CB_Copy_Middle ; Copy the Middle then! + + ; Copy Right Edge of Bitmap + +@CB_Right_Band: + + OUT_8 SC_Data, Right_Clip_Mask[BX] ; Set Right Edge Plane Mask + + DEC [BP].CB_Width ; Band Width-- + MOV CX, [BP].CB_Height ; CX = # of Lines to Copy + MOV DX, SCREEN_WIDTH ; DX = Width of Screen + MOV BX, [BP].CB_Width ; BX = Offset to Right Edge + +@CB_Right_Loop: + MOV AL, ES:[SI+BX] ; Load Latches + MOV ES:[DI+BX], AL ; Unload Latches + ADD BX, DX ; Advance Offset to Next Line + LOOPjz CX, @CB_Right_Done ; Exit Loop if Finished + + MOV AL, ES:[SI+BX] ; Load Latches + MOV ES:[DI+BX], AL ; Unload Latches + ADD BX, DX ; Advance Offset to Next Line + LOOPx CX, @CB_Right_Loop ; Loop until Finished + +@CB_Right_Done: + + ; Copy the Main Block of the Bitmap + +@CB_Copy_Middle: + + MOV CX, [BP].CB_Width ; Get Width Remaining + JCXZ @CB_Finish ; Exit if Done + + OUT_8 SC_Data, ALL_PLANES ; Copy all Planes + + MOV DX, SCREEN_WIDTH ; Get Width of Screen minus + SUB DX, CX ; Image width (for Adjustment) + MOV AX, [BP].CB_Height ; AX = # of Lines to Copy + MOV BX, CX ; BX = Quick REP reload count + MOV CX, ES ; Move VGA Segment + MOV DS, CX ; Into DS + + ; Actual Copy Loop. REP MOVSB does the work + +@CB_Middle_Copy: + MOV CX, BX ; Recharge Rep Count + REP MOVSB ; Move Bands + LOOPjz AX, @CB_Finish ; Exit Loop if Finished + + ADD SI, DX ; Adjust DS:SI to Next Line + ADD DI, DX ; Adjust ES:DI to Next Line + + MOV CX, BX ; Recharge Rep Count + REP MOVSB ; Move Bands + + ADD SI, DX ; Adjust DS:SI to Next Line + ADD DI, DX ; Adjust ES:DI to Next Line + LOOPx AX, @CB_Middle_Copy ; Copy Lines until Done + +@CB_Finish: + OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = on + +@CB_Exit: + ADD SP, 04 ; Deallocate stack workspace + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + RET 16 ; Exit and Clean up Stack + +COPY_BITMAP ENDP + + END ; End of Code Segment diff --git a/src/lib/modex/demos/c/modex.bi b/src/lib/modex/demos/c/modex.bi new file mode 100755 index 00000000..6b1d7afe --- /dev/null +++ b/src/lib/modex/demos/c/modex.bi @@ -0,0 +1,63 @@ + + ' ===== SCREEN RESOLUTIONS ===== + +CONST Mode320x200 = 0, Mode320x400 = 1 +CONST Mode360x200 = 2, Mode360x400 = 3 +CONST Mode320x240 = 4, Mode320x480 = 5 +CONST Mode360x240 = 6, Mode360x480 = 7 + + ' ===== MODE X SETUP ROUTINES ===== + +DECLARE FUNCTION SET.VGA.MODEX% ALIAS "SET_VGA_MODEX" (BYVAL ModeType%, BYVAL MaxXpos%, BYVAL MaxYpos%, BYVAL Pages%) +DECLARE FUNCTION SET.MODEX% ALIAS "SET_MODEX" (BYVAL Mode%) + + ' ===== BASIC GRAPHICS PRIMITIVES ===== + +DECLARE SUB CLEAR.VGA.SCREEN ALIAS "CLEAR_VGA_SCREEN" (BYVAL ColorNum%) +DECLARE SUB SET.POINT ALIAS "SET_POINT" (BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorNum%) +DECLARE FUNCTION READ.POINT% ALIAS "READ_POINT" (BYVAL Xpos%, BYVAL Ypos%) +DECLARE SUB FILL.BLOCK ALIAS "FILL_BLOCK" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%) +DECLARE SUB DRAW.LINE ALIAS "DRAW_LINE" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%) + + ' ===== DAC COLOR REGISTER ROUTINES ===== + +DECLARE SUB SET.DAC.REGISTER ALIAS "SET_DAC_REGISTER" (BYVAL RegNo%, BYVAL Red%, BYVAL Green%, BYVAL Blue%) +DECLARE SUB GET.DAC.REGISTER ALIAS "GET_DAC_REGISTER" (BYVAL RegNo%, Red%, Green%, Blue%) +DECLARE SUB LOAD.DAC.REGISTERS ALIAS "LOAD_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%, BYVAL VSync%) +DECLARE SUB READ.DAC.REGISTERS ALIAS "READ_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%) + + + ' ===== PAGE FLIPPING AND SCROLLING ROUTINES ===== + +DECLARE SUB SET.ACTIVE.PAGE ALIAS "SET_ACTIVE_PAGE" (BYVAL PageNo%) +DECLARE FUNCTION GET.ACTIVE.PAGE% ALIAS "GET_ACTIVE_PAGE" +DECLARE SUB SET.DISPLAY.PAGE ALIAS "SET_DISPLAY_PAGE" (BYVAL PageNo%) +DECLARE FUNCTION GET.DISPLAY.PAGE% ALIAS "GET_DISPLAY_PAGE" +DECLARE SUB SET.WINDOW ALIAS "SET_WINDOW" (BYVAL DisplayPage%, BYVAL XOffset%, BYVAL YOffset%) +DECLARE FUNCTION GET.X.OFFSET% ALIAS "GET_X_OFFSET" () +DECLARE FUNCTION GET.Y.OFFSET% ALIAS "GET_Y_OFFSET" () +DECLARE SUB SYNC.DISPLAY ALIAS "SYNC_DISPLAY" + + ' ===== TEXT DISPLAY ROUTINES ===== + +DECLARE SUB GPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%) +DECLARE SUB TGPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%) +DECLARE SUB PRINT.STR ALIAS "PRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%) +DECLARE SUB TPRINT.STR ALIAS "TPRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%) +DECLARE SUB SET.DISPLAY.FONT ALIAS "SET_DISPLAY_FONT" (SEG FontData AS ANY, BYVAL FontNumber%) + + ' ===== BITMAP (SPRITE) DISPLAY ROUTINES ===== + +DECLARE SUB DRAW.BITMAP ALIAS "DRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%) +DECLARE SUB TDRAW.BITMAP ALIAS "TDRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%) + + ' ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES ===== + +DECLARE SUB COPY.PAGE ALIAS "COPY_PAGE" (BYVAL SourcePage%, BYVAL DestPage%) +DECLARE SUB COPY.BITMAP ALIAS "COPY_BITMAP" (BYVAL SourcePage%, BYVAL X1%, BYVAL Y1%, BYVAL X2%, BYVAL Y2%, BYVAL DestPage%, BYVAL DestX1%, BYVAL DestY1%) + + + + + + diff --git a/src/lib/modex/demos/c/modex.h b/src/lib/modex/demos/c/modex.h new file mode 100755 index 00000000..1381abb6 --- /dev/null +++ b/src/lib/modex/demos/c/modex.h @@ -0,0 +1,76 @@ + +#ifndef __MODEX_H +#define __MODEX_H + + /* ===== SCREEN RESOLUTIONS ===== */ + +#define Mode_320x200 0 +#define Mode_320x400 1 +#define Mode_360x200 2 +#define Mode_360x400 3 +#define Mode_320x240 4 +#define Mode_320x480 5 +#define Mode_360x240 6 +#define Mode_360x480 7 + + /* ===== MODE X SETUP ROUTINES ===== */ + +int far pascal set_vga_modex (int Mode, int MaxXpos, int MaxYpos, int Pages); +int far pascal set_modex (int Mode); + + /* ===== BASIC GRAPHICS PRIMITIVES ===== */ + +void far pascal clear_vga_screen (int Color); +void far pascal set_point (int Xpos, int Ypos, int Color); +int far pascal read_point (int Xpos, int Ypos); +void far pascal fill_block (int Xpos1, int Ypos1, int Xpos2, int Ypos2, + int Color); +void far pascal draw_line (int Xpos1, int Ypos1, int Xpos2, int Ypos2, + int Color); + + /* ===== DAC COLOR REGISTER ROUTINES ===== */ + +void far pascal set_dac_register (int RegNo, int Red, int Green, int Blue); +void far pascal get_dac_register (int RegNo, int* Red, int* Green, int* Blue); +void far pascal load_dac_registers (char far *PalData, int StartReg, + int EndReg, int VSync); +void far pascal readd_dac_registers (char far *PalData, int StartReg, + int EndReg); + + /* ===== PAGE FLIPPING AND SCROLLING ROUTINES ===== */ + +void far pascal set_active_page (int PageNo); +int far pascal get_active_page (void); +void far pascal set_display_page (int PageNo); +int far pascal get_display_page (void); +void far pascal set_window (int DisplayPage, int XOffset, int YOffset); +int far pascal get_x_offset (void); +int far pascal get_y_offset (void); +void far pascal sync_display (void); + + /* ===== TEXT DISPLAY ROUTINES ===== */ + +void far pascal gprintc (int CharNum, int Xpos, int Ypos, int ColorF, + int ColorB); +void far pascal tgprintc (int CharNum, int Xpos, int Ypos, int ColorF); +void far pascal print_str (char far *Text, int MaxLen, int Xpos, int Ypos, + int ColorF, int ColorB); +void far pascal tprint_str (char far *Text, int MaxLen, int Xpos, int Ypos, + int ColorF); +void far pascal set_display_font (char far *FontData, int FontNumber); + + /* ===== BITMAP (SPRITE) DISPLAY ROUTINES ===== */ + +void far pascal draw_bitmap (char far *Image, int Xpos, int Ypos, + int Width, int Height); +void far pascal tdraw_bitmap (char far *Image, int Xpos, int Ypos, + int Width, int Height); + + /* ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES ===== */ + +void far pascal copy_page (int SourcePage, int DestPage); +void far pascal copy_bitmap (int SourcePage, int X1, int Y1, int X2, int Y2, + int DestPage, int DestX1, int DestY1); + + +#endif diff --git a/src/lib/modex/demos/c/utls-asm.bat b/src/lib/modex/demos/c/utls-asm.bat new file mode 100755 index 00000000..d996978f --- /dev/null +++ b/src/lib/modex/demos/c/utls-asm.bat @@ -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 index 00000000..59f63610 --- /dev/null +++ b/src/lib/modex/demos/c/w.sh @@ -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 index 00000000..dfe9a3e0 --- /dev/null +++ b/src/lib/modex/demos/c/x-demo.c @@ -0,0 +1,786 @@ +/* X-DEMO.C - a Mode "X" Demo */ +/* By Matt Pritchard, 14 Apr, 1993 */ + +#include +#include + +#include "modex.h" +#include "c_utils.h" + +#define MAX_SHAPES 32 +#define MAX_SPRITES 64 + + /* routines in this file */ + +void demo_res (int, int, int); +int get_key (void); +void error_out (char*); +void load_shapes (void); +int int_sqrt (int, int); +void page_demo (void); + + /* Structures for Sprites */ + +struct Shape +{ + unsigned char Image[512]; + int X_Width; + int Y_Width; +} Img [MAX_SHAPES]; + +struct Sprite +{ + int X_pos; + int Y_pos; + int X_Dir; + int Y_Dir; + int Shape; + int Last_X [2]; + int Last_Y [2]; +} Obj [MAX_SPRITES]; + + + /* MAIN */ + + +int main(int argc, char *argv[]) +{ + + /* if (argc > 0) + { + while (argc > 0) + { + dos_print ("Unknown Argument: "); + dos_print (makefp argv[argc]); + argc--; + } + return (0); + + } + */ + + init_random (); + + load_shapes (); + + demo_res ( Mode_320x200, 320, 200 ); + demo_res ( Mode_320x400, 320, 400 ); + + demo_res ( Mode_360x200, 360, 200 ); + demo_res ( Mode_360x400, 360, 400 ); + + demo_res ( Mode_320x240, 320, 240 ); + demo_res ( Mode_320x480, 320, 480 ); + + demo_res ( Mode_360x240, 360, 240 ); + demo_res ( Mode_360x480, 360, 480 ); + + page_demo (); + + set_video_mode (3); + dos_print ("This Mode X Demo is Finished"); + return (0); + +} + + + /* Demonstrate a given resolution */ + + +void demo_res (int Screen_Mode, int X_max, int Y_max) +{ + +char *Error1 = "Failure while calling SET_MODEX"; +char *Error2 = "Failure during READ_PIXEL test"; + +char *Abort_Msg = "Demo aborted by User"; + +char *Demo_Msg = " This is a MODE X demo "; +char *Scrn_Msg = "Screen Resolution is by "; +char *Cont_Msg = "Press to Continue"; + +char *Line_Msg = "LINE TEST"; +char *Fill_Msg = "FILL TEST"; +char *Pixel_Msg = "PIXEL TEST"; + +char Text[10]; + +int x1, y1, x2, y2 = 0; +int x, y, z = 0; +int X_Center, gap = 0; + + + if (set_modex (Screen_Mode) == 0) + { + error_out (Error1); + } + + X_Center = X_max / 2; + + x1 = 10; + y1 = 10; + x2 = X_max - 1; + y2 = Y_max - 1; + + for (z = 0; z <= 3; z++) + { + y = 31 - z -z; + draw_line (x1+z, y1+z, x2-z, y1+z, y); + draw_line (x1+z, y1+z, x1+z, y2-z, y); + draw_line (x1+z, y2-z, x2-z, y2-z, y); + draw_line (x2-z, y1+z, x2-z, y2-z, y); + } + + for (x = 0; x < (X_max / 10); x++) + { + tgprintc (48 + ((x+1) % 10), x*10+1, 1, 9 + ((x/8) % 7) ); + draw_line (x*10+9, 0, x*10+9, 3, c_bWHITE); + } + + for (y = 0; y < (Y_max / 10); y++) + { + tgprintc (48 + ((y+1) % 10), 1, y*10+1, 9 + ((y/10) % 7) ); + draw_line (0, y*10+9, 3, y*10+9, c_bWHITE); + } + + for (x = 0; x <= 63; x++) + { + z = 15 + (x * 3 / 4); + set_dac_register (64+x, z, z, z); + set_dac_register (128+x, 0, z, z); + + draw_line (103-x, 60, 40+x, 123, 64+x); + draw_line (40, 60+x, 103, 123-x, 128+x); + + } + + tprint_str (Line_Msg, 9, 37, 130, c_BLUE); + + y = 60; + gap = 0; + for (x = 0; x <= 9; x++) + { + fill_block (120, y, 120+x, y+gap, 64+x); + fill_block (140 - (15-x), y, 150+x, y+gap, 230+x); + fill_block (170 - (15-x), y, 170, y+gap, 128+x); + y = y + gap + 2; + gap++; + } + + tprint_str (Fill_Msg, 9, 110, 46, c_GREEN); + + for (x = 190; x <= 250; x+=2) + { + for (y = 60; y <= 122; y+=2) + { + z = (x+x+y+y) & 0xff; + set_point (x, y, z); + } + } + + tprint_str (Pixel_Msg, 10, 182, 130, c_RED); + + for (x = 190; x <= 250; x+=2) + { + for (y = 60; y <= 122; y+=2) + { + z = (x+x+y+y) & 0xff; + if (read_point(x, y) != z) + { + error_out (Error2); + } + } + } + + print_str (Demo_Msg, 23, X_Center - 92, 20, c_bRED, c_BLUE); + + x = X_Center - 124; + print_str (Scrn_Msg, 28, x, 30, c_bGREEN, c_BLACK); + + sprintf (Text, "%3d", X_max); + print_str (Text, 3, x+168, 30, c_bPURPLE, c_BLACK); + + sprintf (Text, "%3d", Y_max); + print_str (Text, 3, x + 224, 30, c_bWHITE, c_BLACK); + + for (x = 0; x <= 15; x++) + { + set_dac_register (230+x, 63-x*4, 0, 15+x*3); + draw_line (30+x, Y_max-6-x, X_max-20-x, Y_max-6-x, 230+x); + } + + tprint_str (Cont_Msg, 27, X_Center - 103, Y_max-18, c_YELLOW); + + if (get_key () == Ky_ESC) + { + error_out (Abort_Msg); + } + + return ; + +} + + + /* Wait for a Keystroke */ + + +int get_key(void) +{ + +int c = 0; + + while (c == 0) + { + c = scan_keyboard (); + } + + return (c); + +} + + + /* Error Handling Routine */ + + +void error_out (char * text) +{ + + set_video_mode (3); + dos_print (text); + exit (EXIT_SUCCESS); + +} + + + /* Routine to generate random sprites */ + + +void load_shapes () +{ + +unsigned char Grid[33][33]; + +char *Error1 = "Bad Shape Selected Error"; + +int Shape; +int x, y, z; +int Style, Color; +int X_Width, Y_Width, Center, S_Width; +int Hollow_X, Hollow_Y; + + for (Shape = 0; Shape < MAX_SHAPES; Shape++) + { + for (y = 0; y <= 32; y++) + { + for (x = 0; x <= 32; x++) + { + Grid[x][y] = c_BLACK; + } + } + + Style = random_int (6); + Color = 1 + random_int (15); + + switch (Style) + + { + /* SOLID BOXES */ + + case 0: + + { + do + { + X_Width = 3 + random_int(30); + Y_Width = 3 + random_int(30); + + } while ( (X_Width * Y_Width) >= 512); + + for (x = 1; x <= X_Width; x++) + { + for (y = 1; y <= Y_Width; y++) + { + Grid[x][y] = Color; + } + } + + break; + + } + /* HOLLOW BOXES */ + + case 1: + + { + do { + X_Width = 6 + random_int(27); + Y_Width = 6 + random_int(27); + } while ( (X_Width * Y_Width) >= 512); + + for (y = 1; y <= Y_Width; y++) + { + for (x = 1; x <= X_Width; x++) + { + Grid[x][y] = Color; + } + } + + Hollow_X = 1 + random_int ((X_Width / 2) -1); + Hollow_Y = 1 + random_int ((Y_Width / 2) -1); + + for (y = Hollow_Y+1; y <= Y_Width-Hollow_Y; y++) + { + for (x = Hollow_X+1; x <= X_Width-Hollow_X; x++) + { + Grid[x][y] = c_BLACK; + } + } + + break; + + } + + /* SOLID DIAMOND */ + + case 2: + + { + + X_Width = 3 + 2 * random_int(10); + Y_Width = X_Width; + Center = X_Width / 2; + + for (y = 0; y <= Center; y++) + { + for (x = 0; x <= y; x++) + { + Grid [Center-x+1][y+1] = Color; + Grid [Center+x+1][y+1] = Color; + Grid [Center-x+1][Y_Width-y] = Color; + Grid [Center+x+1][Y_Width-y] = Color; + } + } + + break; + + } + + /* HOLLOW DIAMOND */ + + case 3: + + { + + X_Width = 3 + 2 * random_int(10); + Y_Width = X_Width; + Center = X_Width / 2; + S_Width = random_int (Center); + + for (y = 0; y <= Center; y++) + { + for (x = 0; x <= y; x++) + { + if ( x+(Center-y) >= S_Width ) + { + Grid [Center-x+1][y+1] = Color; + Grid [Center+x+1][y+1] = Color; + Grid [Center-x+1][Y_Width-y] = Color; + Grid [Center+x+1][Y_Width-y] = Color; + } + } + } + + break; + + } + + /* BALL */ + + case 4: + + { + + X_Width = 7 + 2 * random_int (8); + Y_Width = X_Width; + Center = 1 + X_Width / 2; + + for (y = 1; y <= Y_Width; y++) + { + for (x = 1; x <= X_Width; x++) + { + z = int_sqrt(Center-x, Center-y); + if (z < Center) + { + Grid[x][y] = 150 + Color * 2 + z * 3; + } + } + } + + break; + } + + /* HOLLOW BALLS */ + + case 5: + + { + X_Width = 7 + 2 * random_int (8); + Y_Width = X_Width; + Center = 1 + X_Width / 2; + S_Width = random_int (X_Width); + + for (y = 1; y <= Y_Width; y++) + { + for (x = 1; x <= X_Width; x++) + { + z = int_sqrt(Center-x, Center-y); + if ( (z < Center) && (z >= S_Width) ) + { + Grid[x][y] = 150 + Color * 2 + z * 3; + } + } + } + + + break; + } + + default: + + { + error_out (Error1); + break; + + } + + } + + z = 0; + for (y = 1; y <= Y_Width; y++) + { + for (x = 1; x <= X_Width; x++) + { + Img[Shape].Image[z] = Grid[x][y]; + z++; + } + } + + Img[Shape].X_Width = X_Width; + Img[Shape].Y_Width = Y_Width; + + } + + return; +} + + + /* Quickie Psuedo Integer Square Root Routine */ + + +int int_sqrt ( int x, int y ) +{ + +int Sqr_Table[12] = {1, 4, 9, 6, 25, 36, 49, 64, 81, 100, 121, 144}; + +int r, d; + + d = (x * x) + (y * y); + r = 0; + + while ( d >= Sqr_Table[r] ) + { + r++; + } + + return (r); + +} + + + /* The Bit Sprite Demo */ + + +void page_demo () +{ + +char *Error1 = "Failure during SET_VGA_MODEX (0, 320, 200, 2) call"; + +int Last_Objects[2], Visible_Objects; + +int Screen_X = 384; +int Screen_Y = 224; + +int x, y, z; +int c, dc; +int x1, y1, x2, y2; + +int Sprite_X, Sprite_Y; +int Current_Page; +int New_X, New_Y; + +int View_X, View_Y, View_Max, View_Cnt, View_XD, View_YD; +int Set_Color, Prev_Color, S_Dir, P_Dir; + +int Demo_Running = True; +int redo, code; + +int pee; +pee = set_vga_modex(Mode_320x200, Screen_X, Screen_Y, 3); + if ( pee > 0) + { + set_video_mode (3); + dos_print (Error1); + fprintf(stdout, "return value is %d\n", pee); + //error_out (Error1); + exit (EXIT_SUCCESS); + } + + set_active_page (0); + clear_vga_screen (c_BLACK); + + print_str ("This is a Test of the Following Functions:", 99, 10, 9, c_bWHITE, c_BLACK); + + draw_line (10, 18, 350, 18, c_YELLOW); + print_str ("SET_ACTIVE_PAGE", 99, 10, 20, c_bBLUE, c_BLACK); + print_str ("SET_DISPLAY_PAGE", 99, 10, 30, c_GREEN, c_BLACK); + print_str ("SET_DAC_REGISTER", 99, 10, 40, c_RED, c_BLACK); + print_str ("CLEAR_VGA_SCREEN", 99, 10, 50, c_CYAN, c_BLACK); + + print_str ("TDRAW_BITMAP", 99, 10, 60, c_PURPLE, c_BLACK); + print_str ("COPY_PAGE", 99, 10, 70, c_GREEN, c_BLACK); + print_str ("COPY_BITMAP", 99, 10, 80, c_CYAN, c_BLACK); + + print_str ("GPRINTC", 99, 10, 90, c_BLUE, c_BLACK); + print_str ("TGPRINTC", 99, 10, 100, c_GREEN, c_BLACK); + print_str ("SET_WINDOW", 99, 10, 110, c_RED, c_BLACK); + + print_str ("VIRTUAL SCREEN SIZES", 20, 190, 20, c_bBLUE, c_BLACK); + print_str (" SMOOTH SCROLLING", 20, 190, 30, c_GREEN, c_BLACK); + print_str (" SPRITE ANIMATION", 20, 190, 40, c_CYAN, c_BLACK); + print_str (" PAGE FLIPPING", 20, 190, 50, c_RED, c_BLACK); + print_str (" COLOR CYCLING", 20, 190, 60, c_PURPLE, c_BLACK); + + for (x = 0; x <=60; x++) + { + set_dac_register (50 + x, 3 + x, 0, 60 - x); + set_dac_register (150 + x, 3 + x, 0, 60 - x); + } + + c = 0; + dc = 1; + for (x = 0; x <= (Screen_X / 2); x++) + { + draw_line (Screen_X / 2 - 1, Screen_Y / 4, x, Screen_Y - 1, c + 50); + draw_line (Screen_X / 2, Screen_Y / 4, Screen_X - x - 1, Screen_Y - 1, c + 50); + c+= dc; + if ((c == 0) || (c == 60) ) { dc = -dc;} + } + + tprint_str ("Press to Continue", 99, 72, 190, c_bWHITE); + tprint_str ("< > = Faster < > = Slower", 99, 72, 204, c_bGREEN); + tprint_str ("< > = Fewer Shapes < > = More Shapes", 99, 32, 218, c_bCYAN); + + tgprintc (43, 80, 204, c_YELLOW); + tgprintc (45, 200, 204, c_YELLOW); + + tgprintc (25, 40, 218, c_YELLOW); + tgprintc (24, 200, 218, c_YELLOW); + + copy_page (0, 1); + copy_page (0, 2); + + for (x = 0; x < MAX_SPRITES; x++) + { + do { + Obj[x].X_Dir = random_int(7) - 3; + Obj[x].Y_Dir = random_int(7) - 3; + } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) ); + + Obj[x].Shape = x % MAX_SHAPES; + + Sprite_X = Img[Obj[x].Shape].X_Width; + Sprite_Y = Img[Obj[x].Shape].Y_Width; + + Obj[x].X_pos = 1 + random_int(Screen_X - Sprite_X - 2); + Obj[x].Y_pos = 1 + random_int(Screen_Y - Sprite_Y - 2); + + Obj[x].Last_X[0] = Obj[x].X_pos; + Obj[x].Last_X[1] = Obj[x].X_pos; + Obj[x].Last_Y[0] = Obj[x].Y_pos; + Obj[x].Last_Y[1] = Obj[x].Y_pos; + + } + + Current_Page = 0; + + View_X = 0; + View_Y = 0; + View_Max = 3; + View_Cnt = 0; + View_XD = 1; + View_YD = 1; + + Set_Color = 3; + S_Dir = 1; + Prev_Color = 0; + P_Dir = 1; + + Visible_Objects = MAX_SPRITES / 2; + Last_Objects[0] = 0; + Last_Objects[1] = 0; + + while (Demo_Running) + { + + set_active_page (Current_Page); + + /* Erase Old Images */ + + for (x = 0; x <= Last_Objects[Current_Page]; x++) + { + z = 2; + y = Obj[x].Shape; + x1 = Obj[x].Last_X[Current_Page]; + y1 = Obj[x].Last_Y[Current_Page]; + x2 = x1 + Img[y].X_Width -1; + y2 = y1 + Img[y].Y_Width -1; + + x1 = x1 & 0xfffc; + x2 = x2 | 0x0003; + + copy_bitmap (z, x1, y1, x2, y2, Current_Page, x1, y1); + } + + /* Draw new images */ + + for (x = 0; x <= Visible_Objects; x++) + { + Sprite_X = Img[Obj[x].Shape].X_Width; + Sprite_Y = Img[Obj[x].Shape].Y_Width; + + /* Move Sprite */ + + do + { + redo = False; + New_X = Obj[x].X_pos + Obj[x].X_Dir; + + if (( New_X < 0 ) || (New_X + Sprite_X > Screen_X) ) + { + Obj[x].X_Dir = -Obj[x].X_Dir; + if (random_int(20) == 1) + { + do + { + Obj[x].X_Dir = random_int(7) - 3; + Obj[x].Y_Dir = random_int(7) - 3; + } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) ); + redo = True; + } + } + } while (redo); + Obj[x].X_pos = Obj[x].X_pos + Obj[x].X_Dir; + + + do + { + redo = False; + New_Y = Obj[x].Y_pos + Obj[x].Y_Dir; + + if ( (New_Y < 0) || (New_Y + Sprite_Y > Screen_Y) ) + { + Obj[x].Y_Dir = -Obj[x].Y_Dir; + if (random_int(20) == 1) + { + do + { + Obj[x].X_Dir = random_int(7) - 3; + Obj[x].Y_Dir = random_int(7) - 3; + } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) ); + redo = True; + } + } + } while (redo); + + Obj[x].Y_pos = Obj[x].Y_pos + Obj[x].Y_Dir; + + /* Draw Sprite */ + + tdraw_bitmap ((char far*) &Img[Obj[x].Shape], Obj[x].X_pos, Obj[x].Y_pos, Sprite_X, Sprite_Y); + + Obj[x].Last_X[Current_Page] = Obj[x].X_pos; + Obj[x].Last_Y[Current_Page] = Obj[x].Y_pos; + + } + + Last_Objects[Current_Page] = Visible_Objects; + + + /* Pan Screen Back & Forth */ + + View_Cnt++; + if (View_Cnt >= View_Max) + { + View_X+= View_XD; + if ( (View_X == 0) || (View_X == 39) ) {View_XD = -View_XD;} + if (View_XD < 0) + { + View_Y+= View_YD; + if ( (View_Y == 0) || (View_Y == 39) ) {View_YD = -View_YD;} + } + + set_window (Current_Page, View_X, View_Y); + + View_Cnt = 0; + } + else + { + set_display_page (Current_Page); + } + + /* Cycle Colors */ + + set_dac_register (50 + Prev_Color, 3 + Prev_Color, 0, 60 - Prev_Color); + set_dac_register (50 + Set_Color, Set_Color, 10, 63 - Set_Color); + + set_dac_register (150 + Prev_Color, 3 + Prev_Color, 0, 60 - Prev_Color); + set_dac_register (150 + Set_Color, 63, 63, Set_Color); + + Set_Color+= S_Dir; + if ( (Set_Color == 60) || (Set_Color == 0) ) {S_Dir = -S_Dir;} + + Prev_Color+= P_Dir; + if ( (Prev_Color == 60) || (Prev_Color == 0) ) {P_Dir = -P_Dir;} + + /* Check for Keystroke */ + + Current_Page = Current_Page ^ 0x01; + + code = scan_keyboard (); + + if (code == Ky_ESC) {Demo_Running = False;} + + if (code == Ky_Plus) + { + if (View_Max < 12) {View_Max++;} + } + + if (code == Ky_Minus) + { + if (View_Max > 1) {View_Max--;} + if (View_Cnt >= View_Max) {View_Cnt = 0;} + } + + if (code == Ky_Up) + { + if (Visible_Objects < MAX_SPRITES-1) {Visible_Objects++;} + } + + if (code == Ky_Down) + { + if (Visible_Objects > 0) {Visible_Objects--;} + } + + } + +} diff --git a/src/lib/modex/demos/c/x-demo.dsk b/src/lib/modex/demos/c/x-demo.dsk new file mode 100755 index 0000000000000000000000000000000000000000..5573e71a90522ffd46c36a16b5c9ba8abd65ca3e GIT binary patch literal 195 zcmWG3ElSE)a8_{6&nro-C{b|B%t=*{VqoMI5@(cRVBq@7IGX`T8!-UE2HDAKJ5*pa z6Ho-Z3gyjI;~eAX Z@8{_2YG9z}91y_3NB}Z0{Qu9u001}XCCdN+ literal 0 HcmV?d00001 diff --git a/src/lib/modex/demos/c/x-demo.exe b/src/lib/modex/demos/c/x-demo.exe new file mode 100755 index 0000000000000000000000000000000000000000..b4fee9143d4174b8284b8a72f43c7593c13fc714 GIT binary patch literal 58495 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 AdU4bE`&n$yUztV`N19Bt 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 literal 0 HcmV?d00001 diff --git a/src/lib/modex/demos/c/x-demo.prj b/src/lib/modex/demos/c/x-demo.prj new file mode 100755 index 0000000000000000000000000000000000000000..b3f307e5c005eb0b7ef8346090f3cdce82a31210 GIT binary patch literal 4936 zcmeI$`BNKZ7zgm@O#-A~Db}Nfw(zQ}_80=Bauknk*rZIHEXjm)%vh?^ge_7F!4T>l z@OE_UwDlkGZoTpR$>V2jsg6f4{|Q@fTN|J6hQZWn+>pdFF zGM12<3?&mgjCe|J8s2Hh1`>;xE))D#<)*OnGqRDO&sm~_W_-wW#%wuk`cVx&{n+#q z(@$AJUzwR-n|{OE=?J@#jXgMD=X4+Bn?8h^^o@5Cd^A2n?_t41qfs8UdpqfwsF4 zjU$>svH+T@$G?)Za;34oZc!Z%x5j_STNA(HtB&tt=r@=E| z57-O#foFlEj;R2Zpb9uav+(i`mR?+9ioD$eJ;89m)92L&{C!$rv)5Pp!1EZPXA;q- zg7_Js=gBMv2vu>#TxPH7%pCl%eN zuWoa9t&vJ!u>TfMNGhRlP!C0CK{vD*$ zV6l^&zn|iZ`uaTjg}vUNe<>xk&dhBgKTK@r=ZL%qA*IGRqom2s?fhTa!owL6P8;Ki ziDcZ6T4H1@|1O5LbGM+>no{loOI=Wr{lDP)*+HjvdQHlcJ?)+Zc)#6Z&hcCcu6&+Ce?(xLp9X6no_$}sdi8; j|AzcU&}^xtPP&3>Ff}z%Bdwy9w1SpXJvFd%1!v2jT`({0 literal 0 HcmV?d00001 diff --git a/src/lib/modex/demos/c/x.exe b/src/lib/modex/demos/c/x.exe new file mode 100755 index 0000000000000000000000000000000000000000..7742d145c591d471d2e9b79e0fe99083a3d669f2 GIT binary patch literal 41090 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 JvY09JKLIz`z5M_H literal 0 HcmV?d00001 diff --git a/src/lib/modex/demos/chardemo.exe b/src/lib/modex/demos/chardemo.exe new file mode 100755 index 0000000000000000000000000000000000000000..4015bdf14e1d4067c4c2d9321f00accdf71fe452 GIT binary patch literal 13066 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 RBhN(+NB$^IcBSvV{T~&EV%Y!y literal 0 HcmV?d00001 diff --git a/src/lib/modex/demos/pascal/test5.pas b/src/lib/modex/demos/pascal/test5.pas new file mode 100755 index 00000000..7cc56bbb --- /dev/null +++ b/src/lib/modex/demos/pascal/test5.pas @@ -0,0 +1,488 @@ +{ ModeX Turbo Pascal Demo Program } +{ Converted to Turbo Pascal by Scott Wyatt } +{ Original program written in QuickBasic by Matt Prichard } +{ Released to the Public Domain } +{ } +{ Thanks to Matt Prichard for his *EXCELLENT* ModeX Library } +{ Additional Comments by Matt Pritchard } + +Uses Crt; + +{$L modex2.obj} { This file is the external ModeX Library .OBJ } +{$F+} + + { Mode Setting Routines } + +Function SET_VGA_MODEX (Mode,MaxXpos,MaxYpos,Pages : integer) : integer; external; +Function SET_MODEX (Mode:integer) : Integer; external; + + { Graphics Primitives } + +Procedure CLEAR_VGA_SCREEN (Color:integer); external; +Procedure SET_POINT (Xpos,Ypos,Color : integer); external; +Function READ_POINT (Xpos,Ypos:integer) : integer; external; +Procedure FILL_BLOCK (Xpos1,Ypos1,Xpos2,Ypos2,Color:integer); external; +Procedure DRAW_LINE (Xpos1,Ypos1,Xpos2,Ypos2,Color:integer); external; + + { VGA DAC Routines } + +Procedure SET_DAC_REGISTER (RegNo,Red,Green,Blue:integer); external; +Procedure GET_DAC_REGISTER (RegNo,Red,Green,Blue:integer); external; + + { Page and Window Control Routines } + +Procedure SET_ACTIVE_PAGE (PageNo:integer); external; +Function GET_ACTIVE_PAGE : integer; external; +Procedure SET_DISPLAY_PAGE (PageNo:integer); external; +Function GET_DISPLAY_PAGE : integer; external; +Procedure SET_WINDOW (DisplayPage,XOffset,YOffset : integer); external; +Function GET_X_OFFSET : integer; external; +Function GET_Y_OFFSET : integer; external; +Procedure SYNC_DISPLAY; external; + + { Text Display Routines } + +Procedure GPRINTC (CharNum,Xpos,Ypos,ColorF,ColorB:integer); external; +Procedure TGPRINTC ( CharNum,Xpos,Ypos,ColorF : integer); external; +Procedure PRINT_STR (Var Text;MaxLen,Xpos,Ypos,ColorF,ColorB:integer); external; +Procedure TPRINT_STR (Var Text;MaxLen,Xpos,Ypos,ColorF:integer); external; +Procedure SET_DISPLAY_FONT (Var FontData;FontNumber:integer); external; + + { Sprite and VGA memory -> Vga memory Copy Routines } + +Procedure DRAW_BITMAP (Var Image;Xpos,Ypos,Width,Height:integer); external; +Procedure TDRAW_BITMAP (Var Image;Xpos,Ypos,Width,Height:integer); external; +Procedure COPY_PAGE (SourcePage,DestPage:integer); external; +Procedure COPY_BITMAP (SourcePage,X1,Y1,X2,Y2,DestPage,DestX1,DestY1:integer); external; + +{$F-} + + +TYPE Sprite = Record + Xpos : INTEGER; + Ypos : INTEGER; + XDir : INTEGER; + YDir : INTEGER; + Shape : INTEGER; + LastX : INTEGER; + LastY : INTEGER; + END; + + +CONST MaxShapes = 32; + Circle_16 : Array[1..16,1..16] of byte = + (( 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0), + ( 0, 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0), + ( 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0), + ( 0, 0, 20, 20, 20, 20, 0, 0, 0, 0, 20, 20, 20, 20, 0, 0), + ( 0, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 0), + ( 0, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20, 0), + ( 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20), + ( 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20), + ( 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20), + ( 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20), + ( 0, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20, 0), + ( 0, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 0), + ( 0, 0, 20, 20, 20, 20, 0, 0, 0, 0, 20, 20, 20, 20, 0, 0), + ( 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0), + ( 0, 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0), + ( 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0)); + Square_16 : Array[1..16,1..16] of byte = + (( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21), + ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21), + ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21), + ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21), + ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21), + ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21), + ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21), + ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21), + ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21), + ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21), + ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21), + ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21), + ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21), + ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21), + ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21), + ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21)); + Diamond : Array[1..8,1..8] of byte = + (( 0, 0, 0, 22, 22, 0, 0, 0), + ( 0, 0, 22, 22, 22, 22, 0, 0), + ( 0, 22, 22, 0, 0, 22, 22, 0), + ( 22, 22, 0, 0, 0, 0, 22, 22), + ( 22, 22, 0, 0, 0, 0, 22, 22), + ( 0, 22, 22, 0, 0, 22, 22, 0), + ( 0, 0, 22, 22, 22, 22, 0, 0), + ( 0, 0, 0, 22, 22, 0, 0, 0)); + Rectangle : Array[1..8,1..3] of byte = + (( 23, 23, 23), + ( 23, 23, 23), + ( 23, 23, 23), + ( 23, 23, 23), + ( 23, 23, 23), + ( 23, 23, 23), + ( 23, 23, 23), + ( 23, 23, 23)); + + { Global Variables ? } + +Var + XCenter,X1,Y1,X2,Y2,Z,Colr,XChars,YChars,X,Y,N,Gap : Integer; + s : string; + s1 : Array[1..35] of Char; + ch : Char; + obj : Array[1..64] of Sprite; + ScreenX,ScreenY : Integer; + c, dc, SpriteX, SpriteY, CurrentPage, LastPage : Integer; + SetColor, SDir, PrevColor, PDir : Byte; + XView, YView : Integer; + XView_Change, YView_Change : Integer; + Right : Boolean; + Number_Of_Shapes : Byte; + + + { Error Handler - Returns to Text Mode & Displays Error } + +Procedure ERROR_OUT(s : string); + Begin + asm + mov ah,0 + mov al,3 + int 10h + end; + WriteLn(s); + Halt(0); +END; + + { Routine to Print a PASCAL string using Print_Str } + +Procedure Print_Text(s : string; X,Y,BColor,FColor : integer); +Var + s1 : Array[1..135] of Char; + i : byte; +Begin + For i := 1 to Length(s) DO + s1[i] := s[i]; + Print_Str(s1,Length(s),X,Y,BColor,FColor); +End; + + { Routine to Transparently Print a PASCAL string using TPrint_Str } + +Procedure TPrint_Text(s : string; X,Y,Color : integer); +Var + s1 : Array[1..135] of Char; + i : byte; +Begin + For i := 1 to Length(s) DO + s1[i] := s[i]; + TPrint_Str(s1,Length(s),X,Y,Color); +End; + + { Routines to show test patterns for a given mode } + +Procedure Demo_Res(Mode, Xmax, Ymax : integer); +Begin + + Str(mode,s); + If Set_ModeX(Mode) = 0 Then + Error_Out('Unable to SET_MODEX '+s); + Clear_VGA_Screen(0); + + XCenter := Xmax div 2; + X1 := 10; + Y1 := 10; + X2 := Xmax - 1; + Y2 := Ymax - 1; + + FOR Z := 0 TO 3 DO + Begin + Colr := 31 - Z * 2; + Draw_Line(X1 + Z, Y1 + Z, X2 - Z, Y1 + Z, Colr); + Draw_Line(X1 + Z, Y1 + Z, X1 + Z, Y2 - Z, Colr); + Draw_Line(X1 + Z, Y2 - Z, X2 - Z, Y2 - Z, Colr); + Draw_Line(X2 - Z, Y1 + Z, X2 - Z, Y2 - Z, Colr); + End; + + XChars := Xmax div 10; + YChars := Ymax div 10; + + FOR X := 0 TO XChars - 1 DO + Begin + TGPRINTC(48 + ((X + 1) MOD 10), X * 10 + 1, 1, 9 + ((X div 8) MOD 7)); + DRAW_LINE(X * 10 + 9, 0, X * 10 + 9, 3, 15); + End; + FOR Y := 0 TO YChars - 1 DO + Begin + TGPRINTC(48 + ((Y + 1) MOD 10), 1, Y * 10 + 1, 9 + ((Y div 10) MOD 7)); + DRAW_LINE(0, Y * 10 + 9, 3, Y * 10 + 9, 15); + End; + + { Test Line Drawing } + + FOR X := 0 TO 63 DO + Begin + N := 15 + ((X * 3) div 4); + SET_DAC_REGISTER(64 + X, N, N, N); + SET_DAC_REGISTER(128 + X, 0, N, N); + DRAW_LINE(103 - X, 60, 40 + X, 123, 64 + X); + DRAW_LINE(40, 60 + X, 103, 123 - X, 128 + X); + End; + s := 'Line Test'; + PRINT_Text(s,37,130,1,0); + + { Test Block Fills } + + Y := 60; + Gap := 0; + FOR X := 0 TO 9 DO + Begin + FILL_BLOCK(120, Y, 120 + X, Y + Gap, 64 + X); + FILL_BLOCK(140 - (15 - X), Y, 150 + X, Y + Gap, 230 + X); + FILL_BLOCK(170 - (15 - X), Y, 170, Y + Gap, 128 + X); + Y := Y + Gap + 2; + Gap := Gap + 1; + End; + s := 'Fill Test'; + Print_Text(s,110, 46, 2,0); + + { Test Pixel Write and Read } + + FOR X := 190 TO 250 DO + FOR Y := 60 TO 122 DO + SET_POINT( X, Y, X + Y + X + Y); + + s := 'Pixel Test'; + Print_Text(s,182, 130, 3,0); + + FOR X := 190 TO 250 DO + FOR Y := 60 TO 122 DO + IF READ_POINT(X, Y) <> ((X + Y + X + Y) AND 255) THEN + WriteLn('READ_PIXEL Failure'); + + { Display rest of screen } + + s := ' This is a MODE X demo '; + Print_Text(s,XCenter - (Length(s) * 4), 20, 3, 1); + s := 'Screen Resolution is by '; + X := XCenter - (Length(s) * 4); + Print_Text(s,X,30,4,0); + Str(XMax,s); + Print_Text(s, X + 8 * 21, 30, 8, 0); + Str(YMax,s); + Print_Text(s, X + 8 * 28, 30, 15, 0); + + FOR X := 0 TO 15 DO + Begin + SET_DAC_REGISTER( 230 + X, 63 - X * 4, 0, 15 + X * 3); + DRAW_LINE(30 + X, Ymax - 6 - X, Xmax - 20 - X, Ymax - 6 - X, 230 + X); + End; + s := 'Press to Continue'; + For x := 1 to length(s) DO + s1[x] := s[x]; + TPrint_Str(s1, length(s), XCenter - (26 * 4), Ymax - 18, 5); + + Ch := ReadKey; + IF Ch = #27 Then + Error_Out('Abort'); + +End; + + + { Initialize Sprites for Sprite Demo } + +Procedure Init_Sprites; +Var i : byte; +Begin + For i := 1 to 64 DO + Begin + Obj[i].XPos := Random(300)+10; + Obj[i].YPos := Random(200)+20; + Obj[i].XDir := Random(10)-5; + Obj[i].YDir := Random(10)-5; + If (Obj[i].XDir = 0) AND (Obj[i].YDir = 0) Then + Begin + Obj[i].XDir := Random(5) + 1; + Obj[i].YDir := Random(5) + 1; + End; + Obj[i].Shape := Random(4)+1; + Obj[i].LastX := obj[i].XPos; + Obj[i].LastY := obj[i].YPos; + End; +End; + +Procedure Set_Sprites(number : byte); +Var i : Byte; +Begin + For i := 1 to number DO + Begin + obj[i].LastX := obj[i].XPos; + obj[i].LastY := obj[i].YPos; + obj[i].XPos := obj[i].XPos + obj[i].XDir; + obj[i].YPos := obj[i].YPos + obj[i].YDir; + If (obj[i].XPos > 335) OR (obj[i].XPos < 5 ) Then + obj[i].XDir := -(obj[i].XDir); + If (obj[i].YPos > 220) OR (obj[i].YPos < 5) Then + obj[i].YDir := -(obj[i].YDir); + End; + For i := 1 to number DO + Case obj[i].Shape of + 1 : TDraw_Bitmap(Circle_16,obj[i].XPos,obj[i].YPos,16,16); + 2 : TDraw_Bitmap(Square_16,obj[i].XPos,obj[i].YPos,16,16); + 3 : TDraw_Bitmap(Diamond,obj[i].XPos,obj[i].YPos,8,8); + 4 : TDraw_Bitmap(Rectangle,obj[i].XPos,obj[i].YPos,3,8); + End; +End; + +Procedure Remove_Sprites(p,number : byte); +Var i : byte; +Begin + For i := 1 to number DO + Copy_Bitmap(2,obj[i].LastX,obj[i].LastY,obj[i].LastX+16,obj[i].LastY+16,p,Obj[i].LastX,Obj[i].LastY); +End; + +Procedure Page_Demo; +Begin + Number_Of_Shapes := 64; + XView_Change := 1; + YView_Change := 1; + XView := 1; + YView := 1; + Right := TRUE; + ScreenX := 360; + ScreenY := 240; + PrevColor := 0; + SetColor := 3; + SDir := 1; + PDir := 1; + Str(0,s); + + IF SET_VGA_MODEX(0, ScreenX, ScreenY, 3) = 0 THEN + ERROR_OUT('Unable to SET_VGA_MODEX' + S); + + SET_ACTIVE_PAGE(0); + CLEAR_VGA_SCREEN(0); + PRINT_TEXT('This is a Test of the Following Functions:', 10, 9, 15, 0); + DRAW_LINE( 10, 18, 350, 18, 4); + Print_Text('SET_ACTIVE_PAGE', 10, 20, 1, 0); + Print_Text('SET_DISPLAY_PAGE', 10, 30, 3,0); + Print_Text('SET_DAC_REGISTER', 10, 40, 3, 0); + Print_Text('CLEAR_VGA_SCREEN', 10, 50, 13, 0); + Print_Text('TDRAW_BITMAP', 10, 60, 14, 0); + Print_Text('COPY_PAGE', 10, 70, 3, 0); + Print_Text('COPY_BITMAP', 10, 80, 13, 0); + Print_Text('GPRINTC', 10, 90, 1, 0); + Print_Text('TGPRINTC', 10, 100, 3, 0); + Print_Text('SYNC_DISPLAY', 10, 110, 3, 0); + Print_Text('SET_WINDOW', 10, 120, 14, 0); + Print_Text('VIRTUAL SCREEN SIZES', 190, 20, 1, 0); + Print_Text(' SMOOTH SCROLLING', 190, 30, 3, 0); + Print_Text(' SPRITE ANIMATION', 190, 40, 13, 0); + Print_Text(' PAGE FLIPPING', 190, 50, 3, 0); + Print_Text(' COLOR CYCLING', 190, 60, 14, 0); + + FOR X := 0 TO 60 DO + Begin + SET_DAC_REGISTER( 50 + X, 3 + X, 0, 60 - X); + SET_DAC_REGISTER( 150 + X, 3 + X, 0, 60 - X); + End; + + c := 0; + DC := 1; + FOR X := 0 TO ScreenX div 2 DO + Begin + DRAW_LINE( ScreenX div 2 - 1, ScreenY div 4, X, ScreenY - 1, c + 50); + DRAW_LINE( ScreenX div 2, ScreenY div 4, ScreenX - X - 1, ScreenY - 1, c + 50); + c := c + DC; + IF (c = 0) OR (c = 60) THEN DC := -DC; + End; + + TPrint_Text('Press to Continue', 82, 190, 15); + TPrint_Text('<+> = Fewer Shapes <-> = More Shapes', 32, 204, 12); + COPY_PAGE( 0, 1); + COPY_PAGE( 0, 2); + + Ch := #0; + CurrentPage := 1; + LastPage := 0; + Set_Sprites(Number_Of_Shapes); + For c := 1 to 4 DO + Set_Dac_Register(19+c,63-(c*10),0,0); + + While Ch <> #27 DO + Begin + Set_Active_Page(currentpage); + Set_Sprites(Number_Of_Shapes); + If Right Then + Begin + XView := XView + XView_Change; + If (XView > 38) OR (XView < 2) Then + Begin + XView_Change := -(XView_Change); + Right := FALSE; + End; + End + Else + Begin + YView := YView + YView_Change; + If (YView > 38) OR (YView < 2) Then + Begin + YView_Change := -(YView_Change); + Right := TRUE; + End; + End; + + Set_Window(currentpage,XView,YView); + Set_Display_Page(currentpage); + Set_Dac_Register(50 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor); + Set_Dac_Register(50 + SetColor, SetColor, 10, 63 - SetColor); + Set_Dac_Register(150 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor); + Set_Dac_Register(150 + SetColor, 63, 63, SetColor); + SetColor := SetColor + SDir; + IF (SetColor = 60) OR (SetColor = 0) THEN SDir := -SDir; + PrevColor := PrevColor + PDir; + IF (PrevColor = 60) OR (PrevColor = 0) THEN PDir := -PDir; + Remove_Sprites(lastpage,Number_Of_Shapes); + + If Keypressed Then + Begin + Ch := ReadKey; + Case Ch of + '-' : If Number_Of_Shapes > 1 Then + Begin + c := Number_Of_Shapes; + Copy_Bitmap(2,obj[c].XPos,obj[c].YPos,obj[c].XPos+16,obj[c].YPos+16, + currentpage,obj[c].XPos,obj[c].YPos); + Dec(Number_Of_Shapes); + End; + '+' : If Number_Of_Shapes < 64 Then Inc(Number_Of_Shapes); + End; + End; + lastpage := (lastpage+1) MOD 2; + currentpage := (currentpage+1) MOD 2; + End; +END; + + { MAIN ROUTINE - Run Through Demos and Exit } + +Begin + + Randomize; + Init_Sprites; + + Demo_Res(0, 320, 200); + Demo_Res(1, 320, 400); + Demo_Res(2, 360, 200); + Demo_Res(3, 360, 400); + Demo_Res(4, 320, 240); + Demo_Res(5, 320, 480); + Demo_Res(6, 360, 240); + Demo_Res(7, 360, 480); + Page_Demo; + + asm + mov ah,0 + mov al,3 + int 10h + end; + WriteLn('THIS MODE X DEMO IS FINISHED'); + +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 index 00000000..b04876ad --- /dev/null +++ b/src/lib/modex/demos/qb45/make-lib.bat @@ -0,0 +1,5 @@ +ECHO ... Building MODEX.QLB for QUICKBASIC 4.5 +LIB MODEX -+MODEX,, +LIB MODEX -+UTILS,, +DEL MODEX.BAK +LINK /Q MODEX+UTILS, MODEX.QLB, NUL, C:\QB45\BQLB45.LIB; diff --git a/src/lib/modex/demos/qb45/modex.bi b/src/lib/modex/demos/qb45/modex.bi new file mode 100755 index 00000000..6b1d7afe --- /dev/null +++ b/src/lib/modex/demos/qb45/modex.bi @@ -0,0 +1,63 @@ + + ' ===== SCREEN RESOLUTIONS ===== + +CONST Mode320x200 = 0, Mode320x400 = 1 +CONST Mode360x200 = 2, Mode360x400 = 3 +CONST Mode320x240 = 4, Mode320x480 = 5 +CONST Mode360x240 = 6, Mode360x480 = 7 + + ' ===== MODE X SETUP ROUTINES ===== + +DECLARE FUNCTION SET.VGA.MODEX% ALIAS "SET_VGA_MODEX" (BYVAL ModeType%, BYVAL MaxXpos%, BYVAL MaxYpos%, BYVAL Pages%) +DECLARE FUNCTION SET.MODEX% ALIAS "SET_MODEX" (BYVAL Mode%) + + ' ===== BASIC GRAPHICS PRIMITIVES ===== + +DECLARE SUB CLEAR.VGA.SCREEN ALIAS "CLEAR_VGA_SCREEN" (BYVAL ColorNum%) +DECLARE SUB SET.POINT ALIAS "SET_POINT" (BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorNum%) +DECLARE FUNCTION READ.POINT% ALIAS "READ_POINT" (BYVAL Xpos%, BYVAL Ypos%) +DECLARE SUB FILL.BLOCK ALIAS "FILL_BLOCK" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%) +DECLARE SUB DRAW.LINE ALIAS "DRAW_LINE" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%) + + ' ===== DAC COLOR REGISTER ROUTINES ===== + +DECLARE SUB SET.DAC.REGISTER ALIAS "SET_DAC_REGISTER" (BYVAL RegNo%, BYVAL Red%, BYVAL Green%, BYVAL Blue%) +DECLARE SUB GET.DAC.REGISTER ALIAS "GET_DAC_REGISTER" (BYVAL RegNo%, Red%, Green%, Blue%) +DECLARE SUB LOAD.DAC.REGISTERS ALIAS "LOAD_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%, BYVAL VSync%) +DECLARE SUB READ.DAC.REGISTERS ALIAS "READ_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%) + + + ' ===== PAGE FLIPPING AND SCROLLING ROUTINES ===== + +DECLARE SUB SET.ACTIVE.PAGE ALIAS "SET_ACTIVE_PAGE" (BYVAL PageNo%) +DECLARE FUNCTION GET.ACTIVE.PAGE% ALIAS "GET_ACTIVE_PAGE" +DECLARE SUB SET.DISPLAY.PAGE ALIAS "SET_DISPLAY_PAGE" (BYVAL PageNo%) +DECLARE FUNCTION GET.DISPLAY.PAGE% ALIAS "GET_DISPLAY_PAGE" +DECLARE SUB SET.WINDOW ALIAS "SET_WINDOW" (BYVAL DisplayPage%, BYVAL XOffset%, BYVAL YOffset%) +DECLARE FUNCTION GET.X.OFFSET% ALIAS "GET_X_OFFSET" () +DECLARE FUNCTION GET.Y.OFFSET% ALIAS "GET_Y_OFFSET" () +DECLARE SUB SYNC.DISPLAY ALIAS "SYNC_DISPLAY" + + ' ===== TEXT DISPLAY ROUTINES ===== + +DECLARE SUB GPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%) +DECLARE SUB TGPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%) +DECLARE SUB PRINT.STR ALIAS "PRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%) +DECLARE SUB TPRINT.STR ALIAS "TPRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%) +DECLARE SUB SET.DISPLAY.FONT ALIAS "SET_DISPLAY_FONT" (SEG FontData AS ANY, BYVAL FontNumber%) + + ' ===== BITMAP (SPRITE) DISPLAY ROUTINES ===== + +DECLARE SUB DRAW.BITMAP ALIAS "DRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%) +DECLARE SUB TDRAW.BITMAP ALIAS "TDRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%) + + ' ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES ===== + +DECLARE SUB COPY.PAGE ALIAS "COPY_PAGE" (BYVAL SourcePage%, BYVAL DestPage%) +DECLARE SUB COPY.BITMAP ALIAS "COPY_BITMAP" (BYVAL SourcePage%, BYVAL X1%, BYVAL Y1%, BYVAL X2%, BYVAL Y2%, BYVAL DestPage%, BYVAL DestX1%, BYVAL DestY1%) + + + + + + diff --git a/src/lib/modex/demos/qb45/modex.qlb b/src/lib/modex/demos/qb45/modex.qlb new file mode 100755 index 0000000000000000000000000000000000000000..90122c134b3116f960cfd35a3f2d6144bfa2a819 GIT binary patch literal 9739 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 ((X + Y + X + Y) AND 255) THEN + ERROR.OUT "READ.PIXEL Failure" + END IF + NEXT Y + NEXT X + + + + Msg$ = " This is a MODE X demo " + PRINT.TEXT Msg$, XCenter - (LEN(Msg$) * 4), 20, c.bRED, c.BLUE + Msg$ = "Screen Resolution is by " + Xp = XCenter - (LEN(Msg$) * 4) + PRINT.TEXT Msg$, Xp, 30, c.bGREEN, c.BLACK + + PRINT.TEXT LTRIM$(STR$(Xmax)), Xp + 8 * 21, 30, c.bPURPLE, c.BLACK + PRINT.TEXT LTRIM$(STR$(Ymax)), Xp + 8 * 28, 30, c.bWHITE, c.BLACK + + FOR X = 0 TO 15 + SET.DAC.REGISTER 230 + X, 63 - X * 4, 0, 15 + X * 3 + DRAW.LINE 30 + X, Ymax - 6 - X, Xmax - 20 - X, Ymax - 6 - X, 230 + X + NEXT X + TPRINT.TEXT "Press to Continue", XCenter - (26 * 4), Ymax - 18, c.YELLOW + + X = GET.KEY% + IF X = KyESC THEN ERROR.OUT "ABORT" + +END SUB + +SUB ERROR.OUT (Message$) + + SET.VIDEO.MODE 3 + DOS.PRINT Message$ + END + +END SUB + +FUNCTION GET.KEY% + + DO + X = SCAN.KEYBOARD + LOOP UNTIL X + + GET.KEY% = X + +END FUNCTION + +SUB LOAD.SHAPES + +DIM Grid(1 TO 32, 1 TO 32) + + FOR Shape = 0 TO MaxShapes - 1 + + FOR Y = 1 TO 32 + FOR X = 1 TO 32 + Grid(X, Y) = 0 + NEXT X + NEXT Y + + Style = RANDOM.INT(6) + Colour = 1 + RANDOM.INT(15) + + SELECT CASE Style + + CASE 0: ' Solid Box + + DO + xWidth = 3 + RANDOM.INT(30) + yWidth = 3 + RANDOM.INT(30) + LOOP UNTIL ((xWidth * yWidth) <= 512) + + FOR Y = 1 TO yWidth + FOR X = 1 TO xWidth + Grid(X, Y) = Colour + NEXT X + NEXT Y + + CASE 1: ' Hollow Box + + DO + xWidth = 5 + RANDOM.INT(28) + yWidth = 5 + RANDOM.INT(28) + LOOP UNTIL ((xWidth * yWidth) <= 512) + + FOR Y = 1 TO yWidth + FOR X = 1 TO xWidth + Grid(X, Y) = Colour + NEXT X + NEXT Y + + HollowX = 1 + RANDOM.INT(xWidth \ 2 - 1) + HollowY = 1 + RANDOM.INT(yWidth \ 2 - 1) + + FOR Y = HollowY + 1 TO yWidth - HollowY + FOR X = HollowX + 1 TO xWidth - HollowX + Grid(X, Y) = nil + NEXT X + NEXT Y + + CASE 2: ' Solid Diamond + + xWidth = 3 + 2 * RANDOM.INT(10) + yWidth = xWidth + Centre = xWidth \ 2 + + FOR Y = 0 TO Centre + FOR X = 0 TO Y + Grid(Centre - X + 1, Y + 1) = Colour + Grid(Centre + X + 1, Y + 1) = Colour + Grid(Centre - X + 1, yWidth - Y) = Colour + Grid(Centre + X + 1, yWidth - Y) = Colour + NEXT X + NEXT Y + + + CASE 3: ' Hollow Diamond + + + xWidth = 3 + 2 * RANDOM.INT(10) + yWidth = xWidth + Centre = xWidth \ 2 + sWidth = RANDOM.INT(Centre) + + FOR Y = 0 TO Centre + FOR X = 0 TO Y + IF X + (Centre - Y) >= sWidth THEN + Grid(Centre - X + 1, Y + 1) = Colour + Grid(Centre + X + 1, Y + 1) = Colour + Grid(Centre - X + 1, yWidth - Y) = Colour + Grid(Centre + X + 1, yWidth - Y) = Colour + END IF + NEXT X + NEXT Y + + CASE 4: ' Ball + + xWidth = 7 + 2 * RANDOM.INT(8) + yWidth = xWidth + Centre = 1 + xWidth \ 2 + + FOR Y = 1 TO yWidth + FOR X = 1 TO xWidth + D = SQR(((Centre - X) * (Centre - X)) + ((Centre - Y) * (Centre - Y))) + IF D < Centre THEN Grid(X, Y) = 150 + Colour * 2 + D * 3 + NEXT X + NEXT Y + + CASE 5: ' Ball + + + xWidth = 7 + 2 * RANDOM.INT(8) + yWidth = xWidth + Centre = 1 + xWidth \ 2 + sWidth = RANDOM.INT(xWidth) + + FOR Y = 1 TO yWidth + FOR X = 1 TO xWidth + D = SQR(((Centre - X) * (Centre - X)) + ((Centre - Y) * (Centre - Y))) + IF D < Centre AND D >= sWidth THEN Grid(X, Y) = 150 + Colour * 2 + D * 3 + NEXT X + NEXT Y + + END SELECT + + Img(Shape).xWidth = xWidth + Img(Shape).yWidth = yWidth + + A$ = STRING$(xWidth * yWidth, nil) + + c = 1 + FOR Y = 1 TO yWidth + FOR X = 1 TO xWidth + MID$(A$, c, 1) = CHR$(Grid(X, Y)) + c = c + 1 + NEXT X + NEXT Y + + Img(Shape).ImgData = A$ + + + NEXT Shape + +END SUB + +SUB PAGE.DEMO + +CONST MaxSprites = 64 + +DIM Obj(MaxSprites) AS Sprite +DIM LastX(MaxSprites, 1), LastY(MaxSprites, 1) +DIM LastObjects(1) + + ScreenX = 360: ScreenY = 240 + + IF SET.VGA.MODEX%(Mode320x200, ScreenX, ScreenY, 3) = 0 THEN + ERROR.OUT "Unable to SET_VGA_MODEX" + STR$(Mode) + END IF + + SET.ACTIVE.PAGE 0 + + CLEAR.VGA.SCREEN c.BLACK + + PRINT.TEXT "This is a Test of the Following Functions:", 10, 9, c.bWHITE, c.BLACK + + DRAW.LINE 10, 18, 350, 18, c.YELLOW + PRINT.TEXT "SET_ACTIVE_PAGE", 10, 20, c.bBLUE, c.BLACK + PRINT.TEXT "SET_DISPLAY_PAGE", 10, 30, c.GREEN, c.BLACK + PRINT.TEXT "SET_DAC_REGISTER", 10, 40, c.RED, c.BLACK + PRINT.TEXT "CLEAR_VGA_SCREEN", 10, 50, c.CYAN, c.BLACK + + PRINT.TEXT "TDRAW_BITMAP", 10, 60, c.PURPLE, c.BLACK + PRINT.TEXT "COPY_PAGE", 10, 70, c.GREEN, c.BLACK + PRINT.TEXT "COPY_BITMAP", 10, 80, c.CYAN, c.BLACK + + PRINT.TEXT "GPRINTC", 10, 90, c.BLUE, c.BLACK + PRINT.TEXT "TGPRINTC", 10, 100, c.GREEN, c.BLACK + PRINT.TEXT "SET_WINDOW", 10, 110, c.RED, c.BLACK + + PRINT.TEXT "VIRTUAL SCREEN SIZES", 190, 20, c.bBLUE, c.BLACK + PRINT.TEXT " SMOOTH SCROLLING", 190, 30, c.GREEN, c.BLACK + PRINT.TEXT " SPRITE ANIMATION", 190, 40, c.CYAN, c.BLACK + PRINT.TEXT " PAGE FLIPPING", 190, 50, c.RED, c.BLACK + PRINT.TEXT " COLOR CYCLING", 190, 60, c.PURPLE, c.BLACK + + + FOR X = 0 TO 60 + SET.DAC.REGISTER 50 + X, 3 + X, 0, 60 - X + SET.DAC.REGISTER 150 + X, 3 + X, 0, 60 - X + NEXT X + + c = 0: DC = 1 + FOR X = 0 TO ScreenX \ 2 + DRAW.LINE ScreenX \ 2 - 1, ScreenY \ 4, X, ScreenY - 1, c + 50 + DRAW.LINE ScreenX \ 2, ScreenY \ 4, ScreenX - X - 1, ScreenY - 1, c + 50 + c = c + DC + IF c = 0 OR c = 60 THEN DC = -DC + NEXT X + + TPRINT.TEXT "Press to Continue", 72, 190, c.bWHITE + TPRINT.TEXT "< > = Faster < > = Slower", 72, 204, c.bGREEN + TPRINT.TEXT "< > = Fewer Shapes < > = More Shapes", 32, 218, c.bCYAN + + TGPRINTC 43, 80, 204, c.YELLOW + TGPRINTC 45, 200, 204, c.YELLOW + + TGPRINTC 25, 40, 218, c.YELLOW + TGPRINTC 24, 200, 218, c.YELLOW + + COPY.PAGE 0, 1 + COPY.PAGE 0, 2 + + FOR X = 1 TO MaxSprites + DO + Obj(X).XDir = RANDOM.INT(7) - 3 + Obj(X).YDir = RANDOM.INT(7) - 3 + LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0) + + Obj(X).Shape = X MOD MaxShapes + + SpriteX = Img(Obj(X).Shape).xWidth + SpriteY = Img(Obj(X).Shape).yWidth + + Obj(X).Xpos = 1 + RANDOM.INT(ScreenX - SpriteX - 2) + Obj(X).Ypos = 1 + RANDOM.INT(ScreenY - SpriteY - 2) + + LastX(X, 0) = Obj(X).Xpos + LastX(X, 1) = Obj(X).Xpos + LastY(X, 0) = Obj(X).Ypos + LastY(X, 1) = Obj(X).Ypos + NEXT X + + CurrentPage = 0 + + 'View Shift... + + ViewX = 0 + ViewY = 0 + ViewMax = 3 + ViewCnt = 0 + ViewXD = 1 + ViewYD = 1 + + SetColor = 3: SDir = 1 + PrevColor = 0: PDir = 1 + + VisObjects = MaxSprites \ 2 + LastObjects(0) = 0 + LastObjects(1) = 0 + +DRAW.LOOP: + + + SET.ACTIVE.PAGE CurrentPage + + ' Erase Old Images + + FOR X = 1 TO LastObjects(CurrentPage) + + X1 = LastX(X, CurrentPage) AND &HFFFC + Y1 = LastY(X, CurrentPage) + X2 = ((LastX(X, CurrentPage) + Img(Obj(X).Shape).xWidth)) OR 3 + Y2 = Y1 + Img(Obj(X).Shape).yWidth - 1 + + COPY.BITMAP 2, X1, Y1, X2, Y2, CurrentPage, X1, Y1 + + NEXT X + + ' Draw new images + + FOR X = 1 TO VisObjects + + SpriteX = Img(Obj(X).Shape).xWidth + SpriteY = Img(Obj(X).Shape).yWidth + + ' Move Sprite + +REDOX: + NewX = Obj(X).Xpos + Obj(X).XDir + IF NewX < 0 OR NewX + SpriteX > ScreenX THEN + Obj(X).XDir = -Obj(X).XDir + IF RANDOM.INT(20) = 1 THEN + DO + Obj(X).XDir = RANDOM.INT(7) - 3 + Obj(X).YDir = RANDOM.INT(7) - 3 + LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0) + GOTO REDOX + END IF + END IF + Obj(X).Xpos = Obj(X).Xpos + Obj(X).XDir + +REDOY: + NewY = Obj(X).Ypos + Obj(X).YDir + IF NewY < 0 OR NewY + SpriteY > ScreenY THEN + Obj(X).YDir = -Obj(X).YDir + IF RANDOM.INT(20) = 1 THEN + DO + Obj(X).XDir = RANDOM.INT(7) - 3 + Obj(X).YDir = RANDOM.INT(7) - 3 + LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0) + GOTO REDOY + END IF + END IF + Obj(X).Ypos = Obj(X).Ypos + Obj(X).YDir + + 'Draw Sprite + + TDRAW.BITMAP Img(Obj(X).Shape), Obj(X).Xpos, Obj(X).Ypos, SpriteX, SpriteY + + LastX(X, CurrentPage) = Obj(X).Xpos + LastY(X, CurrentPage) = Obj(X).Ypos + + NEXT X + + LastObjects(CurrentPage) = VisObjects + + ' Pan Screen Back & Forth + + ViewCnt = ViewCnt + 1 + IF ViewCnt >= ViewMax THEN + ViewX = ViewX + ViewXD + IF ViewX = 0 OR ViewX = 39 THEN ViewXD = -ViewXD + IF ViewXD < 0 THEN + ViewY = ViewY + ViewYD + IF ViewY = 0 OR ViewY = 39 THEN ViewYD = -ViewYD + END IF + + SET.WINDOW CurrentPage, ViewX, ViewY + + ViewCnt = 0 + ELSE + SET.DISPLAY.PAGE CurrentPage + END IF + + ' Cycle Colors + + SET.DAC.REGISTER 50 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor + SET.DAC.REGISTER 50 + SetColor, SetColor, 10, 63 - SetColor + + SET.DAC.REGISTER 150 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor + SET.DAC.REGISTER 150 + SetColor, 63, 63, SetColor + + SetColor = SetColor + SDir + IF SetColor = 60 OR SetColor = 0 THEN SDir = -SDir + + PrevColor = PrevColor + PDir + IF PrevColor = 60 OR PrevColor = 0 THEN PDir = -PDir + + CurrentPage = 1 - CurrentPage + + Code = SCAN.KEYBOARD + + IF Code = False THEN GOTO DRAW.LOOP + + IF Code = KyPlus THEN + IF ViewMax < 12 THEN ViewMax = ViewMax + 1 + GOTO DRAW.LOOP + END IF + + IF Code = KyMinus THEN + IF ViewMax > 1 THEN ViewMax = ViewMax - 1 + IF ViewCnt >= ViewMax THEN ViewCnt = 0 + GOTO DRAW.LOOP + END IF + + IF Code = KyUp THEN + IF VisObjects < MaxSprites THEN VisObjects = VisObjects + 1 + GOTO DRAW.LOOP + END IF + + IF Code = KyDown THEN + IF VisObjects > 1 THEN VisObjects = VisObjects - 1 + GOTO DRAW.LOOP + END IF + + +END SUB + +SUB PRINT.TEXT (Text$, Xpos, Ypos, ColorF, ColorB) + + IF LEN(Text$) = 0 THEN EXIT SUB + PRINT.STR VARSEG(Text$), SADD(Text$), LEN(Text$), Xpos, Ypos, ColorF, ColorB + + +END SUB + +SUB TPRINT.TEXT (Text$, Xpos, Ypos, ColorF) + + IF LEN(Text$) = 0 THEN EXIT SUB + + TPRINT.STR VARSEG(Text$), SADD(Text$), LEN(Text$), Xpos, Ypos, ColorF + +END SUB + diff --git a/src/lib/modex/demos/qb45/test6a.exe b/src/lib/modex/demos/qb45/test6a.exe new file mode 100755 index 0000000000000000000000000000000000000000..e61d038796159e3fdb7d12c95525a9dafb87995f GIT binary patch literal 40544 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 + push R1 ; Save R1 + PUSHx R2, R3, R4, R5, R6, R7, R8 + ENDIF +ENDM + +POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8 + IFNB + pop R1 ; Restore R1 + POPx R2, R3, R4, R5, R6, R7, R8 + ENDIF +ENDM + + ; Macro to Clear a Register to 0 + +CLR MACRO Register + xor Register, Register ; Set Register = 0 +ENDM + + ; Macros to Decrement Counter & Jump on Condition + +LOOPx MACRO Register, Destination + dec Register ; Counter-- + jnz Destination ; Jump if not 0 +ENDM + +LOOPjz MACRO Register, Destination + dec Register ; Counter-- + jz Destination ; Jump if 0 +ENDM + + + ; ==== General Constants ==== + + False EQU 0 + True EQU -1 + nil EQU 0 + + b EQU BYTE PTR + w EQU WORD PTR + d EQU DWORD PTR + o EQU OFFSET + f EQU FAR PTR + s EQU SHORT + ?x4 EQU + ?x3 EQU + + +IFDEF FARSTRINGS + + EXTRN stringaddress:far + EXTRN stringlength:far + +ENDIF + + + .Data + + EVEN + +RND_Seed DW 7397, 29447, 802 +RND_Mult DW 179, 183, 182 +RND_ModV DW 32771, 32779, 32783 + +CR_LF DB 13, 10 ; the CRLF data + + .Code + +;================= +;DOS_PRINT (Text$) +;================= +; +; Prints Text Directly to DOS console w/ CR/LF +; + + PUBLIC DOS_PRINT + +DP_Stack STRUC + DW ?x4 ; DI, SI, DS, BP + DD ? ; Caller + DP_Text DW ? ; Address of Text$ Descriptor +DP_Stack ENDS + + +DOS_PRINT PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + mov BP, SP ; Set up Stack Frame + + mov SI, [BP].DP_Text ; Get Addr of Text$ descriptor + +IFDEF FARSTRINGS + push SI ; Push Addr of BC7 Decriptor Ptr + call stringaddress ; Get Address + Len of string!!! + ; DX:AX = Addr CX = Len + mov DS, DX ; DS = DX = Segment of string + mov DX, AX ; DX = AX = Offset of String +ELSE + mov CX, [SI] ; put its length into CX + mov DX, [SI+02] ; now DS:DX points to the String +ENDIF + + jcxz @No_Print ; Don't Print if empty + + mov BX, 1 ; 1= DOS Handle for Display + mov AH, 40h ; Write Text Function + int 21h ; Call DOS to do it + +@No_Print: + mov AX, SEG DGROUP ; Restore DGroup + mov DS, AX + + mov DX, o CR_LF ; Get Addr of CR/LF pair + mov CX, 2 ; 2 Characters to Write + mov BX, 1 ; 1= DOS Handle for Display + + mov AH, 40h ; Write Text Function + int 21h ; Call DOS to do it + + cld ; Reset Direction Flag + POPx DI, SI, DS, BP ; Restore Saved Registers + ret 2 ; Exit & Clean Up Stack + +DOS_PRINT ENDP + + +;================== +;DOS_PRINTS (Text$) +;================== +; +; Print Text$ Directly to DOS console +; without a trailing CR/LF +; + + PUBLIC DOS_PRINTS + +DOS_PRINTS PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + mov BP, SP ; Set up Stack Frame + + mov SI, [BP].DP_Text ; Get Addr of Text$ descriptor + +IFDEF FARSTRINGS + push SI ; Push Addr of BC7 Decriptor Ptr + call stringaddress ; Get Address + Len of string!!! + ; DX:AX = Addr CX = Len + mov DS, DX ; DS = DX = Segment of string + mov DX, AX ; DX = AX = Offset of String +ELSE + mov CX, [SI] ; put its length into CX + mov DX, [SI+02] ; now DS:DX points to the String +ENDIF + + jcxz @DPS_Exit ; Don't Print if empty + + mov BX, 1 ; 1= DOS Handle for Display + mov AH, 40h ; Write Text Function + int 21h ; Call DOS to do it + +@DPS_Exit: + cld ; Reset Direction Flag + POPx DI, SI, DS, BP ; Restore Saved Registers + ret 2 ; Exit & Clean Up Stack + +DOS_PRINTS ENDP + + +;====================== +;SET_VIDEO_MODE (Mode%) +;====================== +; +; Sets the Video Mode through the BIOS +; + + PUBLIC SET_VIDEO_MODE + +SVM_Stack STRUC + DW ?x4 ; DI, SI, DS, BP + DD ? ; Caller + SVM_Mode DB ?,? ; Desired Video Mode +SVM_Stack ENDS + + +SET_VIDEO_MODE PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + mov BP, SP ; Set up Stack Frame + + CLR AH ; Function 0 + mov AL, [BP].SVM_Mode ; Get Mode # + + int 10H ; Change Video Modes + +@SVM_Exit: + POPx DI, SI, DS, BP ; Restore Saved Registers + ret 2 ; Exit & Clean Up Stack + +SET_VIDEO_MODE ENDP + + +;============== +;SCAN_KEYBOARD% +;============== +; +; Function to scan keyboard for a pressed key +; + + PUBLIC SCAN_KEYBOARD + +SCAN_KEYBOARD PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + + mov AH, 01H ; Function #1 + int 16H ; Call Keyboard Driver + jz @SK_NO_KEY ; Exit if Zero flag set + + mov AH, 00H ; Remove Key from Buffer + int 16H ; Get Keycode in AX + + or AL, AL ; Low Byte Set (Ascii?) + jz @SK_Exit ; if not, it's a F-Key + + CLR AH ; Clear ScanCode if Ascii + jmp s @SK_Exit ; Return Key in AX + +@SK_NO_KEY: + CLR AX ; Return Nil (no Keypress) + +@SK_Exit: + cld ; Reset Direction Flag + POPx DI, SI, DS, BP ; Restore Saved Registers + ret ; Exit & Clean Up Stack + +SCAN_KEYBOARD ENDP + + +;==================== +;RANDOM_INT (MaxInt%) +;==================== +; +; Returns a pseudo-random number in the range of (0.. MaxInt-1) +; + + + PUBLIC RANDOM_INT + +RI_Stack STRUC + DW ? ; BP + DD ? ; Caller + RI_MaxVal DW ? ; Maximum Value to Return + 1 +RI_Stack ENDS + + +RANDOM_INT PROC FAR + + push BP ; Preserve Important Registers + mov BP, SP ; Set up Stack Frame + + CLR BX ; BX is the data index + CLR CX ; CX is the accumulator + +REPT 3 + mov AX, RND_Seed[BX] ; load the initial seed + mul RND_Mult[BX] ; multiply it + div RND_ModV[BX] ; and obtain the Mod value + mov RND_Seed[BX], DX ; save that for the next time + + add CX, DX ; add it into the accumulator + inc BX + inc BX ; point to the next set of values +ENDM + + mov AX, CX ; AX = Random # + CLR DX ; DX = 0 + div [BP].RI_MaxVal ; DX = DX:AX / MAxVal Remainder + + mov AX, DX + + pop BP ; Restore BP + ret 2 ; back to BASIC with AX holding the result + +RANDOM_INT ENDP + + +;=========== +;INIT_RANDOM +;=========== +; +; Scrambles the psuedo-random number sequence +; (XOR's the seed value with the timer) +; + + PUBLIC INIT_RANDOM + +INIT_RANDOM PROC FAR + + clr AX ; Segment = 0000 + mov ES, AX + mov AX, ES:[046Ch] ; Get Timer Lo Word + + xor RND_Seed, AX ; Scramble 1st Seed + + ret ; Exit & Clean Up Stack + +INIT_RANDOM ENDP + + +;==================== +;INT_SQR (X%, Round%) +;==================== +; +; Returns the Integer Square Root of (X) +; Round allows the return value to be rounded to the +; nearest integer value by passing 0x80. Passing 0 +; return the Integer Portion only. The rounding amound is +; a number from 0 to 1 multiplied by 256, thus +; 0.5 * 0x100 = 0x80! +; + +ISQ_Stack STRUC + DW ?,? ; BP, DI + DD ? ; Caller + ISQ_Round DW ? ; Amount to Round Result * 256 + ISQ_X DW ? ; "X" +ISQ_Stack ENDS + + PUBLIC INT_SQR + +INT_SQR PROC FAR + + PUSHx BP, DI ; Save BP + mov BP, SP ; Set up Stack Frame + + xor AX, AX ; {xor eax,eax} + xor DX, DX ; {xor edx,edx} + mov DI, [BP].ISQ_X ; {mov edi,x} + + mov CX, 16 ; {mov cx, 32} + +@ISQ_L: + + shl DI, 1 ; {shl edi,1} + rcl DX, 1 ; {rcl edx,1} + shl DI, 1 ; {shl edi,1} + rcl DX, 1 ; {rcl edx,1} + shl AX, 1 ; {shl eax,1} + mov BX, AX ; {mov ebx,eax} + shl BX, 1 ; {shl ebx,1} + inc BX ; {inc ebx} + cmp DX, BX ; {cmp edx,ebx} + jl @ISQ_S + + sub DX, BX ; {sub edx,ebx} + inc AX ; {inc eax} + +@ISQ_S: + loop @ISQ_L + + add ax, [BP].ISQ_Round ; {add eax,$00008000} + ; {*round* result in hi word: ie. +0.5} + shr ax, 8 ; {shr eax,16} {to ax (result)} + + POPx DI, BP ; Restore Registers + ret 4 ; Exit + +INT_SQR ENDP + + +;============ +;TIMER_COUNT& +;============ +; +; Returns the current timer value as an integer/long integer +; + + + PUBLIC TIMER_COUNT + +TIMER_COUNT PROC FAR + + clr AX ; Segment = 0000 + mov ES, AX ; use ES to get at data + mov AX, ES:[046Ch] ; Get Timer Lo Word + mov DX, ES:[046Eh] ; Get Timer Hi Word + ret ; Exit & Return value in DX:AX + +TIMER_COUNT ENDP + + + END diff --git a/src/lib/modex/demos/qb45/utils.bi b/src/lib/modex/demos/qb45/utils.bi new file mode 100755 index 00000000..aeafeef4 --- /dev/null +++ b/src/lib/modex/demos/qb45/utils.bi @@ -0,0 +1,51 @@ + + ' Misc Constants + +CONST True = -1, False = 0, nil = 0 + + ' Keyboard Codes: Extended + +CONST KyF1 = &H3B00, KyF2 = &H3C00, KyF3 = &H3D00, KyF4 = &H3E00, KyF5 = &H3F00 +CONST KyF6 = &H4000, KyF7 = &H4100, KyF8 = &H4200, KyF9 = &H4300, KyF10 = &H4400 + +CONST KyUp = &H4800, KyLeft = &H4B00, KyRight = &H4D00, KyDown = &H5000 +CONST KySLeft = &HCB00, KySRight = &HCD00, KySUp = &HC800, KySDown = &HD000 + +CONST KyHome = &H4700, KyPgUp = &H4900, KyEnd = &H4F00, KyPgDn = &H5100 +CONST KySHome = &HC700, KySPgUp = &HC900, KySEnd = &HCF00, KySPgDn = &HD100 + +CONST KyIns = &H5200, KyDel = &H5300, KyRvsTab = &H8F00 +CONST KySIns = &HC200, KySDel = &HC300 + +CONST KyAltA = &H1E00, KyAltB = &H3000, KyAltC = &H2E00, KyAltD = &H2000 +CONST KyAltE = &H1200, KyAltF = &H2100, KyAltG = &H2200, KyAltH = &H2300 +CONST KyAltI = &H1700, KyAltJ = &H2400, KyAltK = &H2500, KyAltL = &H2600 +CONST KyAltM = &H3200, KyAltN = &H3100, KyAltO = &H1800, KyAltP = &H1900 +CONST KyAltQ = &H1000, KyAltR = &H1300, KyAltS = &H1F00, KyAltT = &H1400 +CONST KyAltU = &H1600, KyAltV = &H2F00, KyAltW = &H1100, KyAltX = &H2D00 +CONST KyAltY = &H1500, KyAltZ = &H2C00 + + ' Keyboard Codes: Ascii + +CONST KyBS = 8, KyTab = 9, KyCR = 13, KyESC = &H1B, KyClr = &H7F +CONST KyPlus = 45, KyMinus = 43 + + ' Color Constants + +CONST c.BLACK = 0, c.BLUE = 1, c.GREEN = 2, c.CYAN = 3 +CONST c.RED = 4, c.PURPLE = 5, c.BROWN = 6, c.WHITE = 7 +CONST c.GREY = 8, c.bBLUE = 9, c.bGREEN = 10, c.bCYAN = 11 +CONST c.bRED = 12, c.bPURPLE = 13, c.YELLOW = 14, c.bWHITE = 15 +CONST c.BRIGHT = 8 + + ' From UTILS.ASM + +DECLARE SUB DOS.PRINT ALIAS "DOS_PRINT" (Text$) +DECLARE SUB DOS.PRINTS ALIAS "DOS_PRINTS" (Text$) +DECLARE SUB SET.VIDEO.MODE ALIAS "SET_VIDEO_MODE" (BYVAL Mode%) +DECLARE FUNCTION SCAN.KEYBOARD% ALIAS "SCAN_KEYBOARD" +DECLARE FUNCTION RANDOM.INT ALIAS "RANDOM_INT" (BYVAL MaxInt%) +DECLARE SUB INIT.RANDOM ALIAS "INIT_RANDOM" +DECLARE FUNCTION TIMER.COUNT& ALIAS "TIMER_COUNT" +DECLARE FUNCTION INT.SQR ALIAS "INT_SQR" (BYVAL X%, BYVAL Round%) + diff --git a/src/lib/modex/demos/rom_8x8.fnt b/src/lib/modex/demos/rom_8x8.fnt new file mode 100755 index 0000000000000000000000000000000000000000..708a4f924815cedc3c5e179b42a7cc9d9c492625 GIT binary patch literal 1024 zcmYLIv1%hR5FJwF8j-jZ*rdt_40l(kSRBY_q!RI=OQFJ*5!~J;?(YN6A8>zgZD7H$ zl}MQ;#%yJGAywF7(cT+v;KsRcaNHt(pu$~WyMl)8=J9c}9nL?U|BNw)!Z}yyN?(1sVqU(r_lx_* z;`^cA+!V)SakF`7yVSK0baFON^RpA6R$5nu#x>{2(f!NIkLh$u^M&!=#30pHRh8oq zHspA%Nkd?xER_@#u}zjGx~}U4b?F9o35^S=RtnGI*k$1mn2E`IpKb3GexA6jgX#d( zM9r=tTkt=Yl`K+UPLB$(m&}q! zOTT5a-|y={41hjH>YXc{>oHF7hIw`#bMPId+q-agn?`Nl^7)gS6K0HSk-#1#(1k*o zsOR8(@a`b&LwagnQ+jS1Y7X!FCurlFrtv1{v%o|8xC^sv%e@fWVQK3c#zL2$y)^hxh42f59a)vzx6a@ZkcEDUF0PO NT(pwbM1+VY(Lc=|finOA literal 0 HcmV?d00001 diff --git a/src/lib/modex/demos/spaceage.fnt b/src/lib/modex/demos/spaceage.fnt new file mode 100755 index 0000000000000000000000000000000000000000..029bae4effb181a29f61b17c588cd848bc04e82a GIT binary patch literal 1024 zcmYLHJ!|7Y5SbOEUxqr5pFqLs>t~iV;RY!1j zs1T!jZ)J0X<+nTE^JYaBxj=YYL5MSiNTH5);!SAhnReQ4LLJYv6KTJliL?`M0<-sY zlBTX3z-|rM$^0|Re0Tq_dU}1IKT>}gC!1%R#!H_*=J(g9)x-T=89OV>Qc7Q0<$+~s zT?B^K+E5~)uWJ_Y^?HqizX~+}2c+5i7$wSfTjM6OHRDgBC36-M>lO%e$Zv$loio%!zj=P}rObnQjD6ug80Nsfe_-MHKA77r{sZ_H5+LHR z+TvT2QYL`;Fy2UiFu>AN=7IUiA5jg2X2e2eWB~Ob0QN8~c`@PQf5`LWp@9I#X99p= h7cUiYAi$&vVG}~bcO~qr4Z(-d%J<)JrH}|U`3JE0#Z>?R literal 0 HcmV?d00001 diff --git a/src/lib/modex/demos/system.fnt b/src/lib/modex/demos/system.fnt new file mode 100755 index 0000000000000000000000000000000000000000..9a1965ebfe5bd67bea71c313ef7ef2f78aa6fbb7 GIT binary patch literal 1024 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 Ix?}Ob0HE06asU7T literal 0 HcmV?d00001 diff --git a/src/lib/modex/fontedit/charsets.cs b/src/lib/modex/fontedit/charsets.cs new file mode 100755 index 0000000000000000000000000000000000000000..97fe608ff81e4b78105a52984687b21a8a166ff7 GIT binary patch literal 2144 zcmZuxJ!l+96n;6MS4UXnt-=-}41|Eng%sK1kQZ45l?FE{#|SwoHp$@#voXtha@dX{ zQYfmTCagt@!<7qF0>fazkYW)cg-{{Pq!F&fRpE+dlJCu4ehhhcyPv){@Bht-sFQSU z?`Ur=rF3mP9s`G~&wl*=$?EXx>WcWGqImeQw?g*Kn|B$j<8L9yRdu}o^5y<<<={3R zJ91BVemh_^&-b1i&-V^qIlB4L%_JF3?W2uH8ylZp>f!4Cv;EZ}DLZpBtEjiQ;#L-W z6c4L7u75%mXAG#CsbTFza*OjM2!4p3-Wj(2t#=j~I%LJ8fw*LYP9bC>57Rj1{9ZA7Mt z6KS4Onx_vgng8 z5ChN7E_A{E#u-DcG5iJBS|ct9q$P*ET4SFcHJ_hw-p*IT;K*e|=JU&VGnr1~~8H#+(P@Jm%Ot$eFuBJd>w6;$lt( zZ_xR{Vt$gPB+U&6Ju11bu*7}I%|Ck}`V-5W(=w<`MO-ZROI!i+W5yLm>$%e<4W%p) z7`$kjGQ>J~AGk9ZCWI)&)d=%cYd-+8T!t)QpYs5Kexkqot2Z4Fs z`R41b%`e0!UwyeH{!fS&ZY*{lZ@m|a$Iauzf)uuYju0V`tBS9351aLIx zKoYE`puPCvqHV#G^>wrnw9VmR)6&9HxV5`0DPT3nNkt;8{TC0{5AmfyPur=6UpQ=s zxYo!wnILk%u4}5ni%GGJ-#Ow4ghL)og!7>;E{stKtVwWvI2Xw*@hE4KQLFRa)0hVH z{}+J}BY08(?-3mP)Jab%MT$7DR|L0b_`tuYN6S;-uczYEpKvZ!rX1M!Z2JyuC%E7IvA=GDa(`>QD+soN|ACXgvqk-8t6F z`g+b`2YrteKAa~bA0JsVwj+xV5RCQLr_l%|@VE1Ph*N`Wpk_V#vYyv-u06L(E9KAY zn$Pj}eir>RM^&{1s#<$J!mwX3n@lF#&_nC>86X2k^*$bR_5;^75OWrqIpVS%j_3Kj zU$BjM*bnsZ?9kg;v}e&js#Nd~5GEQhM;P#a24hIyzo+2B|8*@NyU3c zKhoDl(t4iF`zI7CEZbYo-&2HyY)=?K#(E3@obyW5K^Oq{Pa2IdqU?;31F1O*Ao42S zpH^MH76I4}Zg!5~0c~&l{;AHgn)NV{g3yP^a9{fpdzW07LSf8BB*6Q(VGO|>EaR=u c@7}+=v9)<$+}Yd`AAF4Uy(KWY!FGSkU-|#d0ssI2 literal 0 HcmV?d00001 diff --git a/src/lib/modex/fontedit/csedit.doc b/src/lib/modex/fontedit/csedit.doc new file mode 100755 index 00000000..97ff07e0 --- /dev/null +++ b/src/lib/modex/fontedit/csedit.doc @@ -0,0 +1,196 @@ + +CSEDIT - A Simple Font Editor by Matt Pritchard + + +CSEDIT is distributed with MODEXnnn.ZIP, the general purpose MODE X +Library for VGA Graphics. + +WHAT YOU NEED TO RUN CSEDIT: + + * A Vga Monitor + * A Microsoft Compatible Mouse + + A Mouse is most definitely required, as the keyboard is used for + nothing except entering file names. + +FILES NEEDED IN THE CURRENT DIRECTORY: + + CSEDIT.EXE - The Font Editor Program + CHARSETS.CS - The Font Editor's Internal Fonts + PALETTE.CS - The Font Editor's Palette + MOUSEIMG.CS - The Font Editor's Mouse Pointer + +SAMPLE FONT FILE THAT SHOULD BE INCLUDED: + + SYSTEM.FNT - The Font used by CSEDIT.EXE + INVERSE.FNT - An Inverted version of SYSTEM.FNT + SPACEAGE.FNT - A Futuristic, Tech style font + ROM_8X8.FNT - The Lower 128 characters from the VGA BIOS Rom + +WHAT IT EDITS: + + 8 by 8 character fonts, 128 characters at a time. 2 fonts at a time. + +HOW IT WORKS/FEATURES: + + CSEDIT allows the user to edit 2 different font groups at a time, + which may be loaded and saved separately. + + A enlarged character grid allows the user to edit individual pixels + on a selected character. + + The Following operations can be performed on a single character or + simultaneously on a selected block of characters. + + * Shift the selected character(s) in any direction + with or without clipping at the edges. + * Vertically Flip the selected character(s) + * Horizontally Flip the selected character(s) + * Rotate the selected character(s) 90 Degrees Clockwise + * Rotate the selected character(s) 90 Degrees Counterclockwise + * Clear the selected character(s) + * Invert the selected character(s) + * XOR the selected character(s) with other character(s) + * AND the selected character(s) with other character(s) + * OR the selected character(s) with other character(s) + * Copy the selected character(s) to another position or font. + + An UNDO feature allows the reversal of the most recent operation. + +DESCRIPTION OF OBJECTS/FEATURES FROM THE TOP DOWN: + + Character Grid: (RED) Box in Upper Left corner of screen. This is + where you edit an individual character. The Left Button sets the + pixel the mouse pointer is on, while the Right Button clears that + pixel. + + Scroll Buttons: The Four Scroll Buttons are labeled with directional + arrows, and arranged in a diamond pattern. Left Clicking on a + directional button will scroll the currently selected character + in that direction, with the pixels on the edge rolling off and + appearing on the other size. Right Clicking will prevent the + pixels from rolling to the other side. + + Vertical Flip Button: + Horizontal Flip Button: Clicking these buttons will flip the pattern + of the currently selected character(s) around the indicated axis. + i.e. the top row will be swapped with the bottom row, etc. or the + left row column will be swapped with right column, etc. + depending upon which button you push. + + Invert Button: Clicking this button causes all pixels in the selected + character(s) to flip flop between on and off. + + Clear Button: Clicking this button erases the selected characters + + Rotate Buttons: Clicking these buttons will rotate the pattern in the + selected character(s) 90 degrees in the indicated direction. + + XOR Button: Clicking this button will let you XOR the currently + selected character(s) with other character(s) in either font. + The Button will turn RED, indicating that it is waiting for + you to click on the desired character (or upper left corner + of the desired block of characters) in either the Red or Green + Character Set Displays. Clicking anywhere else will abort this + process without doing anything. If you click on (any of) the + selected character(s) the operation is aborted. If a block is + selected and the character you click on is in a position where + it can't represent the upper left corner of a block of the same + size, then the operation is not performed. + + AND Button & OR Button: These buttons work just like the XOR Button + except that the Binary operation performed is either an AND or OR + depending upon which button you have selected. + + COPY Button: This button lets you copy a character or selected block + of characters to another area in the current font or the other + font. After clicking, the button turns RED and works much like + the XOR Button. Clicking on a valid position in either font + window will copy the selected character(s) to that location. + + MODE Button: Clicking this button toggles the editor between BLOCK + mode and CHARACTER mode. The current mode is displayed on a plate + at the top of the screen, just to the right of the enlarged + character grid. In character mode the plate will read "CHAR" and + the currently selected character is displayed just to the right + of the plate. In Block mode the plate will read "BLOCK" and the + enlarged character grid is disabled. + + UNDO Button: Clicking this Button will UNDO or reverse the effects of + the most recent operation. + + QUIT Button: Clicking this button will return you to DOS. Any loaded + fonts are not saved, and no confirmation is given. + + + GREEN FONT AREA: This area displays one of the current fonts which + can be edited. The characters are display in order from #0 to #127 + from the upper left, going right, then down. The Font Box is 32 + characters wide and 4 characters Tall. When the editor is in + character mode, just point at and Left Click on the character you + wish to edit and a Cyan box will appear around that character. + + * If you Right Click on a character, the last current character, + which will still appear in the enlarged character grid, will be + copied onto the character you pointed at, replacing it. This is + a shortcut for copying characters: You can hold the right button + down an fill in a large area with a single character pattern. + When the editor is in Block Mode, you select an area by clicking + on any corner of the desired block. Then drag the mouse to the + opposite corner while holding down the left button. A Cyan Box + will stretch to surround the selected block of characters. + + GREEN FONT FILE NAME BOX: This Text Box is used to enter the name + of a font file to load or the name to save the current Green font + as. Just click on the Box, and it will change color and a + flashing cursor will appear. Now you type in a filename or edit + the existing filename. Press or click outside the text + box to end editing. + + GREEN FONT LOAD BUTTON: Clicking this button will load the font file + that is named in the Green File name box. If no name is given or + no such file exists, then nothing will be loaded. + + GREEN FONT SAVE BUTTON: Clicking this button will save the current + font in the Green Font Area under the name given in the File Name + Box. If a Valid name is not provided, nothing will be saved. + + RED FONT AREA: This is just the same as the GREEN FONT AREA; providing + you with the ability to copy and edit between multiple fonts. + + RED FONT FILE NAME BOX: This works just like the GREEN FONT FILE + NAME BOX. + + RED FONT LOAD BUTTON: This works just like the GREEN FONT LOAD BUTTON. + + RED FONT SAVE BUTTON: This works just like the GREEN FONT SAVE BUTTON. + + Message Bar: At the very bottom of the screen, this Bar will display + information and messages for various functions. + + +FONT FILE FORMAT: + + BINARY Image, in order of character. The format is identical to that + used by the VGA ROM. The Files will be exactly 1024 (128 * 8) bytes + long. + + CHARACTER: 8 Bytes + + FONT: Array (0 to 127) of CHARACTER + + +COMMENTS, QUESTIONS, BUG REPORTS, etc: + + Send the to the Author: Matt Pritchard + + Through the 80xxx Fidonet Echo or + + Matt Pritchard + P.O. Box 140264 + Irving, TX 75014 + +CREDITS: + + This Font Editor was written in QuickBASIC 4.5 + diff --git a/src/lib/modex/fontedit/csedit.exe b/src/lib/modex/fontedit/csedit.exe new file mode 100755 index 0000000000000000000000000000000000000000..58b073253ada69b3f089a2f3b359049195178db6 GIT binary patch literal 68368 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 literal 0 HcmV?d00001 diff --git a/src/lib/modex/fontedit/palette.cs b/src/lib/modex/fontedit/palette.cs new file mode 100755 index 0000000000000000000000000000000000000000..09c5549e4967dcb520ae894bd5116c0b530b4304 GIT binary patch literal 768 zcmZva!HUBm5J2Y=2%RO`noI*WHGwcK1qscTHe1-8|NpDio)pxF%6pnq0K&M13AbBZ z!q&xO7l(w|iNxizg=4r~RaITrh}bmEe!p+qw(tAX=`@bxJkQtb)qB6L>$Yv5`=UV{ z$O7SUU=eTvI(#S%i7f}`l?a`0a6UY=gwUL^7s{}g|hJS4Up z0C)#%fCpfX3=D>0$9YI>IT*u7!-L_;Fh?df1Dhk~A+hCPEuSq8G#Fm3nq!k?$b&4p`kvfpll!wHY YgKmDmA2t3h8~nUSZ1J&%-%)-20~L%`_y7O^ literal 0 HcmV?d00001 diff --git a/src/lib/modex/fontedit/rom_8x8.fnt b/src/lib/modex/fontedit/rom_8x8.fnt new file mode 100755 index 0000000000000000000000000000000000000000..708a4f924815cedc3c5e179b42a7cc9d9c492625 GIT binary patch literal 1024 zcmYLIv1%hR5FJwF8j-jZ*rdt_40l(kSRBY_q!RI=OQFJ*5!~J;?(YN6A8>zgZD7H$ zl}MQ;#%yJGAywF7(cT+v;KsRcaNHt(pu$~WyMl)8=J9c}9nL?U|BNw)!Z}yyN?(1sVqU(r_lx_* z;`^cA+!V)SakF`7yVSK0baFON^RpA6R$5nu#x>{2(f!NIkLh$u^M&!=#30pHRh8oq zHspA%Nkd?xER_@#u}zjGx~}U4b?F9o35^S=RtnGI*k$1mn2E`IpKb3GexA6jgX#d( zM9r=tTkt=Yl`K+UPLB$(m&}q! zOTT5a-|y={41hjH>YXc{>oHF7hIw`#bMPId+q-agn?`Nl^7)gS6K0HSk-#1#(1k*o zsOR8(@a`b&LwagnQ+jS1Y7X!FCurlFrtv1{v%o|8xC^sv%e@fWVQK3c#zL2$y)^hxh42f59a)vzx6a@ZkcEDUF0PO NT(pwbM1+VY(Lc=|finOA literal 0 HcmV?d00001 diff --git a/src/lib/modex/fontedit/spaceage.fnt b/src/lib/modex/fontedit/spaceage.fnt new file mode 100755 index 0000000000000000000000000000000000000000..029bae4effb181a29f61b17c588cd848bc04e82a GIT binary patch literal 1024 zcmYLHJ!|7Y5SbOEUxqr5pFqLs>t~iV;RY!1j zs1T!jZ)J0X<+nTE^JYaBxj=YYL5MSiNTH5);!SAhnReQ4LLJYv6KTJliL?`M0<-sY zlBTX3z-|rM$^0|Re0Tq_dU}1IKT>}gC!1%R#!H_*=J(g9)x-T=89OV>Qc7Q0<$+~s zT?B^K+E5~)uWJ_Y^?HqizX~+}2c+5i7$wSfTjM6OHRDgBC36-M>lO%e$Zv$loio%!zj=P}rObnQjD6ug80Nsfe_-MHKA77r{sZ_H5+LHR z+TvT2QYL`;Fy2UiFu>AN=7IUiA5jg2X2e2eWB~Ob0QN8~c`@PQf5`LWp@9I#X99p= h7cUiYAi$&vVG}~bcO~qr4Z(-d%J<)JrH}|U`3JE0#Z>?R literal 0 HcmV?d00001 diff --git a/src/lib/modex/fontedit/system.fnt b/src/lib/modex/fontedit/system.fnt new file mode 100755 index 0000000000000000000000000000000000000000..9a1965ebfe5bd67bea71c313ef7ef2f78aa6fbb7 GIT binary patch literal 1024 zcmYjPv1%JZ5PcEm5aBRag)K}-6L5KuW{X1(ia+GQkTh4gGKX2#%0V3BF6z_-EK>Os z1ct?etqu`V2p7gEjd3Mh1sBIAZ&oH`(CIO|J8x#*46rf1Kc0>EHS~VdG{ji+(@pq+oD&8?kJE-xo@8yMC!0paxQ=Ty*Nj4yoj$J48Ty*GP# ze)zCDIXF2u_;BZn;pBWWEHGL zCiv7oaxvt1|Gte!6`zNyLS}!M7hMM5s=V~4(3L*AX^)VmD!xk<<5UWMJj#Je2VL=s zU8v0yki6tchyn7)OzbN!-3Z3}rS}F(E1IP*7lD}UBs_21Hjo*ebB}3Tqb9b*;1e;4 zm!F_b61GF`|GrY#q`sJ*6^O$l;b#YmxLn@2TH<~19-a5{qwky}FCAKkz`V|Jo)Mkg zFC_0K%!AFw`d_kGsnfUD57(^+S!f;nI4wE_}=<@sf-WqJO)v(U&;#n}qip zUL|>GA!5b3(^-Z!`Fy1-@=~W-CK#fy)UOmXaMEzngOR#Y!+ojzzc~PZIJ_sU8jcVcNPyf^0GVeOHxtq!b&Xha#_W6, ; If DX not setup + MOV DX, Register ; then Select Register + ENDIF + IFDIFI , ; If AX not setup + MOV AX, Value ; then Get Data Value + ENDIF + OUT DX, AX ; Set I/O Register(s) +ENDM + + ; Macro to OUT a 8 bit value to an I/O Port + +OUT_8 MACRO Register, Value + IFDIFI , ; If DX not setup + MOV DX, Register ; then Select Register + ENDIF + IFDIFI , ; If AL not Setup + MOV AL, Value ; then Get Data Value + ENDIF + OUT DX, AL ; Set I/O Register +ENDM + + ; macros to PUSH and POP multiple registers + +; PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8 +; IFNB +; PUSH R1 ; Save R1 +; PUSHx R2, R3, R4, R5, R6, R7, R8 +; ENDIF +; ENDM +; +; POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8 +; IFNB +; POP R1 ; Restore R1 +; POPx R2, R3, R4, R5, R6, R7, R8 +; ENDIF +; ENDM + + ; Macro to Clear Registers to 0 + +; CLR MACRO Register, R2, R3, R4;, R5, R6 +; IFNB +; XOR Register, Register ; Set Register = 0 +; CLR R2, R3, R4;, R5, R6 +; ENDIF +; ENDM + + ; Macros to Decrement Counter & Jump on Condition + +LOOPx MACRO Register, Destination + DEC Register ; Counter-- + JNZ Destination ; Jump if not 0 +ENDM + +LOOPjz MACRO Register, Destination + DEC Register ; Counter-- + JZ Destination ; Jump if 0 +ENDM + + + ; ===== General Constants ===== + + False EQU 0 + True EQU -1 + nil EQU 0 + + b EQU BYTE PTR + w EQU WORD PTR + d EQU DWORD PTR + o EQU OFFSET + f EQU FAR PTR + s EQU SHORT + ?x1 EQU + + ; ===== VGA Register Values ===== + + VGA_Segment EQU 0A000h ; Vga Memory Segment + + ATTRIB_Ctrl EQU 03C0h ; VGA Attribute Controller + GC_Index EQU 03CEh ; VGA Graphics Controller + SC_Index EQU 03C4h ; VGA Sequencer Controller + SC_Data EQU 03C5h ; VGA Sequencer Data Port + CRTC_Index EQU 03D4h ; VGA CRT Controller + CRTC_Data EQU 03D5h ; VGA CRT Controller Data + MISC_OUTPUT EQU 03C2h ; VGA Misc Register + INPUT_1 EQU 03DAh ; Input Status #1 Register + + DAC_WRITE_ADDR EQU 03C8h ; VGA DAC Write Addr Register + DAC_READ_ADDR EQU 03C7h ; VGA DAC Read Addr Register + PEL_DATA_REG EQU 03C9h ; VGA DAC/PEL data Register R/W + + PIXEL_PAN_REG EQU 033h ; Attrib Index: Pixel Pan Reg + MAP_MASK EQU 002h ; Sequ Index: Write Map Mask reg + READ_MAP EQU 004h ; GC Index: Read Map Register + START_DISP_HI EQU 00Ch ; CRTC Index: Display Start Hi + START_DISP_LO EQU 00Dh ; CRTC Index: Display Start Lo + + MAP_MASK_PLANE1 EQU 00102h ; Map Register + Plane 1 + MAP_MASK_PLANE2 EQU 01102h ; Map Register + Plane 1 + ALL_PLANES_ON EQU 00F02h ; Map Register + All Bit Planes + + CHAIN4_OFF EQU 00604h ; Chain 4 mode Off + ASYNC_RESET EQU 00100h ; (A)synchronous Reset + SEQU_RESTART EQU 00300h ; Sequencer Restart + + LATCHES_ON EQU 00008h ; Bit Mask + Data from Latches + LATCHES_OFF EQU 0FF08h ; Bit Mask + Data from CPU + + VERT_RETRACE EQU 08h ; INPUT_1: Vertical Retrace Bit + PLANE_BITS EQU 03h ; Bits 0-1 of Xpos = Plane # + ALL_PLANES EQU 0Fh ; All Bit Planes Selected + CHAR_BITS EQU 0Fh ; Bits 0-3 of Character Data + + GET_CHAR_PTR EQU 01130h ; VGA BIOS Func: Get Char Set + ROM_8x8_Lo EQU 03h ; ROM 8x8 Char Set Lo Pointer + ROM_8x8_Hi EQU 04h ; ROM 8x8 Char Set Hi Pointer + + ; Constants Specific for these routines + + NUM_MODES EQU 8 ; # of Mode X Variations + + ; Specific Mode Data Table format... + +Mode_Data_Table STRUC + M_MiscR DB ? ; Value of MISC_OUTPUT register + M_Pages DB ? ; Maximum Possible # of pages + M_XSize DW ? ; X Size Displayed on screen + M_YSize DW ? ; Y Size Displayed on screen + M_XMax DW ? ; Maximum Possible X Size + M_YMax DW ? ; Maximum Possible Y Size + M_CRTC DW ? ; Table of CRTC register values +Mode_Data_Table ENDS + + ; ===== DGROUP STORAGE NEEDED (42 BYTES) ===== + + .DATA? + +SCREEN_WIDTH DW 0 ; Width of a line in Bytes +SCREEN_HEIGHT DW 0 ; Vertical Height in Pixels + +LAST_PAGE DW 0 ; # of Display Pages +PAGE_ADDR DW 4 DUP (0) ; Offsets to start of each page + +PAGE_SIZE DW 0 ; Size of Page in Addr Bytes + +DISPLAY_PAGE DW 0 ; Page # currently displayed +ACTIVE_PAGE DW 0 ; Page # currently active + +CURRENT_PAGE DW 0 ; Offset of current Page +CURRENT_SEGMENT DW 0 ; Segment of VGA memory + +CURRENT_XOFFSET DW 0 ; Current Display X Offset +CURRENT_YOFFSET DW 0 ; Current Display Y Offset + +CURRENT_MOFFSET DW 0 ; Current Start Offset + +MAX_XOFFSET DW 0 ; Current Display X Offset +MAX_YOFFSET DW 0 ; Current Display Y Offset + +CHARSET_LOW DW 0, 0 ; Far Ptr to Char Set: 0-127 +CHARSET_HI DW 0, 0 ; Far Ptr to Char Set: 128-255 + + .CODE + + ; ===== DATA TABLES ===== + + ; Data Tables, Put in Code Segment for Easy Access + ; (Like when all the other Segment Registers are in + ; use!!) and reduced DGROUP requirements... + + ; Bit Mask Tables for Left/Right/Character Masks + +Left_Clip_Mask DB 0FH, 0EH, 0CH, 08H + +Right_Clip_Mask DB 01H, 03H, 07H, 0FH + + ; Bit Patterns for converting character fonts + +Char_Plane_Data DB 00H,08H,04H,0CH,02H,0AH,06H,0EH + DB 01H,09H,05H,0DH,03H,0BH,07H,0FH + + ; CRTC Register Values for Various Configurations + +MODE_Single_Line: ; CRTC Setup Data for 400/480 Line modes + DW 04009H ; Cell Height (1 Scan Line) + DW 00014H ; Dword Mode off + DW 0E317H ; turn on Byte Mode + DW nil ; End of CRTC Data for 400/480 Line Mode + +MODE_Double_Line: ; CRTC Setup Data for 200/240 Line modes + DW 04109H ; Cell Height (2 Scan Lines) + DW 00014H ; Dword Mode off + DW 0E317H ; turn on Byte Mode + DW nil ; End of CRTC Data for 200/240 Line Mode + +MODE_320_Wide: ; CRTC Setup Data for 320 Horz Pixels + DW 05F00H ; Horz total + DW 04F01H ; Horz Displayed + DW 05002H ; Start Horz Blanking + DW 08203H ; End Horz Blanking + DW 05404H ; Start H Sync + DW 08005H ; End H Sync + DW nil ; End of CRTC Data for 320 Horz pixels + +MODE_360_Wide: ; CRTC Setup Data for 360 Horz Pixels + DW 06B00H ; Horz total + DW 05901H ; Horz Displayed + DW 05A02H ; Start Horz Blanking + DW 08E03H ; End Horz Blanking + DW 05E04H ; Start H Sync + DW 08A05H ; End H Sync + DW nil ; End of CRTC Data for 360 Horz pixels + +MODE_200_Tall: +MODE_400_Tall: ; CRTC Setup Data for 200/400 Line modes + DW 0BF06H ; Vertical Total + DW 01F07H ; Overflow + DW 09C10H ; V Sync Start + DW 08E11H ; V Sync End/Prot Cr0 Cr7 + DW 08F12H ; Vertical Displayed + DW 09615H ; V Blank Start + DW 0B916H ; V Blank End + DW nil ; End of CRTC Data for 200/400 Lines + +MODE_240_Tall: +MODE_480_Tall: ; CRTC Setup Data for 240/480 Line modes + DW 00D06H ; Vertical Total + DW 03E07H ; Overflow + DW 0EA10H ; V Sync Start + DW 08C11H ; V Sync End/Prot Cr0 Cr7 + DW 0DF12H ; Vertical Displayed + DW 0E715H ; V Blank Start + DW 00616H ; V Blank End + DW nil ; End of CRTC Data for 240/480 Lines + + ; Table of Display Mode Tables + +MODE_TABLE: + DW o MODE_320x200, o MODE_320x400 + DW o MODE_360x200, o MODE_360x400 + DW o MODE_320x240, o MODE_320x480 + DW o MODE_360x240, o MODE_360x480 + + ; Table of Display Mode Components + +MODE_320x200: ; Data for 320 by 200 Pixels + + DB 063h ; 400 scan Lines & 25 Mhz Clock + DB 4 ; Maximum of 4 Pages + DW 320, 200 ; Displayed Pixels (X,Y) + DW 1302, 816 ; Max Possible X and Y Sizes + + DW o MODE_320_Wide, o MODE_200_Tall + DW o MODE_Double_Line, nil + +MODE_320x400: ; Data for 320 by 400 Pixels + + DB 063h ; 400 scan Lines & 25 Mhz Clock + DB 2 ; Maximum of 2 Pages + DW 320, 400 ; Displayed Pixels X,Y + DW 648, 816 ; Max Possible X and Y Sizes + + DW o MODE_320_Wide, o MODE_400_Tall + DW o MODE_Single_Line, nil + +MODE_360x240: ; Data for 360 by 240 Pixels + + DB 0E7h ; 480 scan Lines & 28 Mhz Clock + DB 3 ; Maximum of 3 Pages + DW 360, 240 ; Displayed Pixels X,Y + DW 1092, 728 ; Max Possible X and Y Sizes + + DW o MODE_360_Wide, o MODE_240_Tall + DW o MODE_Double_Line , nil + +MODE_360x480: ; Data for 360 by 480 Pixels + + DB 0E7h ; 480 scan Lines & 28 Mhz Clock + DB 1 ; Only 1 Page Possible + DW 360, 480 ; Displayed Pixels X,Y + DW 544, 728 ; Max Possible X and Y Sizes + + DW o MODE_360_Wide, o MODE_480_Tall + DW o MODE_Single_Line , nil + +MODE_320x240: ; Data for 320 by 240 Pixels + + DB 0E3h ; 480 scan Lines & 25 Mhz Clock + DB 3 ; Maximum of 3 Pages + DW 320, 240 ; Displayed Pixels X,Y + DW 1088, 818 ; Max Possible X and Y Sizes + + DW o MODE_320_Wide, o MODE_240_Tall + DW o MODE_Double_Line, nil + +MODE_320x480: ; Data for 320 by 480 Pixels + + DB 0E3h ; 480 scan Lines & 25 Mhz Clock + DB 1 ; Only 1 Page Possible + DW 320, 480 ; Displayed Pixels X,Y + DW 540, 818 ; Max Possible X and Y Sizes + + DW o MODE_320_WIDE, o MODE_480_Tall + DW o MODE_Single_Line, nil + +MODE_360x200: ; Data for 360 by 200 Pixels + + DB 067h ; 400 scan Lines & 28 Mhz Clock + DB 3 ; Maximum of 3 Pages + DW 360, 200 ; Displayed Pixels (X,Y) + DW 1302, 728 ; Max Possible X and Y Sizes + + DW o MODE_360_Wide, MODE_200_Tall + DW o MODE_Double_Line, nil + +MODE_360x400: ; Data for 360 by 400 Pixels + + DB 067h ; 400 scan Lines & 28 Mhz Clock + DB 1 ; Maximum of 1 Pages + DW 360, 400 ; Displayed Pixels X,Y + DW 648, 816 ; Max Possible X and Y Sizes + + DW o MODE_360_Wide, MODE_400_Tall + DW o MODE_Single_Line, nil + + + ; ===== MODE X SETUP ROUTINES ===== + +;====================================================== +;SET_VGA_MODEX% (ModeType%, MaxXPos%, MaxYpos%, Pages%) +;====================================================== +; +; Sets Up the specified version of Mode X. Allows for +; the setup of multiple video pages, and a virtual +; screen which can be larger than the displayed screen +; (which can then be scrolled a pixel at a time) +; +; ENTRY: ModeType = Desired Screen Resolution (0-7) +; +; 0 = 320 x 200, 4 Pages max, 1.2:1 Aspect Ratio +; 1 = 320 x 400, 2 Pages max, 2.4:1 Aspect Ratio +; 2 = 360 x 200, 3 Pages max, 1.35:1 Aspect Ratio +; 3 = 360 x 400, 1 Page max, 2.7:1 Aspect Ratio +; 4 = 320 x 240, 3 Pages max, 1:1 Aspect Ratio +; 5 = 320 x 480, 1 Page max, 2:1 Aspect Ratio +; 6 = 360 x 240, 3 Pages max, 1.125:1 Aspect Ratio +; 7 = 360 x 480, 1 Page max, 2.25:1 Aspect Ratio +; +; MaxXpos = The Desired Virtual Screen Width +; MaxYpos = The Desired Virtual Screen Height +; Pages = The Desired # of Video Pages +; +; EXIT: AX = Success Flag: >0 = Failure / 0 = Success +; + +SVM_STACK STRUC + SVM_Table DW ? ; Offset of Mode Info Table + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DD ? ; Caller + SVM_Pages DW ? ; # of Screen Pages desired + SVM_Ysize DW ? ; Vertical Screen Size Desired + SVM_Xsize DW ? ; Horizontal Screen Size Desired + SVM_Mode DW ? ; Display Resolution Desired +SVM_STACK ENDS + + PUBLIC SET_VGA_MODEX + +SET_VGA_MODEX PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + SUB SP, 2 ; Allocate workspace + MOV BP, SP ; Set up Stack Frame + + ; Check Legality of Mode Request.... + + MOV BX, [BP].SVM_Mode ; Get Requested Mode # + CMP BX, NUM_MODES ; Is it 0..7? + JAE @SVM_BadModeSetup1 ; If Not, Error out + + SHL BX, 1 ; Scale BX + MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info + MOV [BP].SVM_Table, SI ; Save ptr for later use + + ; Check # of Requested Display Pages + + MOV CX, [BP].SVM_Pages ; Get # of Requested Pages + ;CLR CH ; Set Hi Word = 0! + mov ch,0 ; Set Hi Word = 0! + CMP CL, CS:[SI].M_Pages ; Check # Pages for mode + JA @SVM_BadModeSetup2 ; Report Error if too Many Pages + JCXZ @SVM_BadModeSetup3 ; Report Error if 0 Pages + + ; Check Validity of X Size + + AND [BP].SVM_XSize, 0FFF8h ; X size Mod 8 Must = 0 + + MOV AX, [BP].SVM_XSize ; Get Logical Screen Width + CMP AX, CS:[SI].M_XSize ; Check against Displayed X + JB @SVM_BadModeSetup4 ; Report Error if too small + CMP AX, CS:[SI].M_XMax ; Check against Max X + JA @SVM_BadModeSetup5 ; Report Error if too big + + ; Check Validity of Y Size + + MOV BX, [BP].SVM_YSize ; Get Logical Screen Height + CMP BX, CS:[SI].M_YSize ; Check against Displayed Y + JB @SVM_BadModeSetup6 ; Report Error if too small + CMP BX, CS:[SI].M_YMax ; Check against Max Y + JA @SVM_BadModeSetup7 ; Report Error if too big + + ; Enough memory to Fit it all? + + SHR AX, 1 ; # of Bytes:Line = XSize/4 + SHR AX, 1 ; # of Bytes:Line = XSize/4 + MUL CX ; AX = Bytes/Line * Pages + MUL BX ; DX:AX = Total VGA mem needed + JNO @SVM_Continue ; Exit if Total Size > 256K + + DEC DX ; Was it Exactly 256K??? + OR DX, AX ; (DX = 1, AX = 0000) + JZ @SVM_Continue ; if so, it's valid... + + jmp @SVM_Continue;0000 + +@SVM_BadModeSetup: + mov ax,8 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup1: + mov ax,1 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup2: + mov ax,2 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup3: + mov ax,3 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup4: + mov ax,4 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup5: + mov ax,5 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup6: + mov ax,6 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup7: + mov ax,7 ; Return Value = False + JMP @SVM_Exit ; Normal Exit + +@SVM_Continue: + + MOV AX, 13H ; Start with Mode 13H + INT 10H ; Let BIOS Set Mode + + OUT_16 SC_INDEX, CHAIN4_OFF ; Disable Chain 4 Mode + OUT_16 SC_INDEX, ASYNC_RESET ; (A)synchronous Reset + OUT_8 MISC_OUTPUT, CS:[SI].M_MiscR ; Set New Timing/Size + OUT_16 SC_INDEX, SEQU_RESTART ; Restart Sequencer ... + + OUT_8 CRTC_INDEX, 11H ; Select Vert Retrace End Register + INC DX ; Point to Data + IN AL, DX ; Get Value, Bit 7 = Protect + AND AL, 7FH ; Mask out Write Protect + OUT DX, AL ; And send it back + + MOV DX, CRTC_INDEX ; Vga Crtc Registers + ADD SI, M_CRTC ; SI -> CRTC Parameter Data + + ; Load Tables of CRTC Parameters from List of Tables + +@SVM_Setup_Table: + + MOV DI, CS:[SI] ; Get Pointer to CRTC Data Tbl + ADD SI, 2 ; Point to next Ptr Entry + OR DI, DI ; A nil Ptr means that we have + JZ @SVM_Set_Data ; finished CRTC programming + +@SVM_Setup_CRTC: + MOV AX, CS:[DI] ; Get CRTC Data from Table + ADD DI, 2 ; Advance Pointer + OR AX, AX ; At End of Data Table? + JZ @SVM_Setup_Table ; If so, Exit & get next Table + + OUT DX, AX ; Reprogram VGA CRTC reg + JMP s @SVM_Setup_CRTC ; Process Next Table Entry + + ; Initialize Page & Scroll info, DI = 0 + +@SVM_Set_Data: + MOV DISPLAY_PAGE, DI ; Display Page = 0 + MOV ACTIVE_PAGE, DI ; Active Page = 0 + MOV CURRENT_PAGE, DI ; Current Page (Offset) = 0 + MOV CURRENT_XOFFSET, DI ; Horz Scroll Index = 0 + MOV CURRENT_YOFFSET, DI ; Vert Scroll Index = 0 + MOV CURRENT_MOFFSET, DI ; Memory Scroll Index = 0 + + MOV AX, VGA_SEGMENT ; Segment for VGA memory + MOV CURRENT_SEGMENT, AX ; Save for Future LES's + + ; Set Logical Screen Width, X Scroll and Our Data + + MOV SI, [BP].SVM_Table ; Get Saved Ptr to Mode Info + MOV AX, [BP].SVM_Xsize ; Get Display Width + + MOV CX, AX ; CX = Logical Width + SUB CX, CS:[SI].M_XSize ; CX = Max X Scroll Value + MOV MAX_XOFFSET, CX ; Set Maximum X Scroll + + SHR AX, 1 ; Bytes = Pixels / 4 + SHR AX, 1 ; Bytes = Pixels / 4 + MOV SCREEN_WIDTH, AX ; Save Width in Pixels + + SHR AX, 1 ; Offset Value = Bytes / 2 + MOV AH, 13h ; CRTC Offset Register Index + XCHG AL, AH ; Switch format for OUT + OUT DX, AX ; Set VGA CRTC Offset Reg + + ; Setup Data table, Y Scroll, Misc for Other Routines + + MOV AX, [BP].SVM_Ysize ; Get Logical Screen Height + + MOV CX, AX ; CX = Logical Height + SUB BX, CS:[SI].M_YSize ; CX = Max Y Scroll Value + MOV MAX_YOFFSET, CX ; Set Maximum Y Scroll + + MOV SCREEN_HEIGHT, AX ; Save Height in Pixels + MUL SCREEN_WIDTH ; AX = Page Size in Bytes, + MOV PAGE_SIZE, AX ; Save Page Size + + MOV CX, [BP].SVM_Pages ; Get # of Pages + MOV LAST_PAGE, CX ; Save # of Pages + + mov bx,0 ; Page # = 0 + MOV DX, BX ; Page 0 Offset = 0 + +@SVM_Set_Pages: + + MOV PAGE_ADDR[BX], DX ; Set Page #(BX) Offset + ADD BX, 2 ; Page#++ + ADD DX, AX ; Compute Addr of Next Page + LOOPx CX, @SVM_Set_Pages ; Loop until all Pages Set + + ; Clear VGA Memory + + OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes + LES DI, d CURRENT_PAGE ; -> Start of VGA memory + + mov ax,0 ; AX = 0 + CLD ; Block Xfer Forwards + MOV CX, 8000H ; 32K * 4 * 2 = 256K + REP STOSW ; Clear dat memory! + + ; Setup Font Pointers + + MOV BH, ROM_8x8_Lo ; Ask for 8x8 Font, 0-127 + MOV AX, GET_CHAR_PTR ; Service to Get Pointer + INT 10h ; Call VGA BIOS + + MOV CHARSET_LOW, BP ; Save Char Set Offset + MOV CHARSET_LOW+2, ES ; Save Char Set Segment + + MOV BH, ROM_8x8_Hi ; Ask for 8x8 Font, 128-255 + MOV AX, GET_CHAR_PTR ; Service to Get Pointer + INT 10h ; Call VGA BIOS + + MOV CHARSET_HI, BP ; Save Char Set Offset + MOV CHARSET_HI+2, ES ; Save Char Set Segment + + MOV AX, True ; Return Success Code + +@SVM_EXIT: + ADD SP, 2 ; Deallocate workspace + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + RET 8 ; Exit & Clean Up Stack + +SET_VGA_MODEX ENDP + + +;================== +;SET_MODEX% (Mode%) +;================== +; +; Quickie Mode Set - Sets Up Mode X to Default Configuration +; +; ENTRY: ModeType = Desired Screen Resolution (0-7) +; (See SET_VGA_MODEX for list) +; +; EXIT: AX = Success Flag: 0 = Failure / -1= Success +; + +SM_STACK STRUC + DW ?,? ; BP, SI + DD ? ; Caller + SM_Mode DW ? ; Desired Screen Resolution +SM_STACK ENDS + + PUBLIC SET_MODEX + +SET_MODEX PROC FAR + + ;PUSHx BP, SI ; Preserve Important registers + push bp + push si + MOV BP, SP ; Set up Stack Frame + + mov ax,0 ; Assume Failure + MOV BX, [BP].SM_Mode ; Get Desired Mode # + CMP BX, NUM_MODES ; Is it a Valid Mode #? + JAE @SMX_Exit ; If Not, don't Bother + + PUSH BX ; Push Mode Parameter + + SHL BX, 1 ; Scale BX to word Index + MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info + + PUSH CS:[SI].M_XSize ; Push Default X Size + PUSH CS:[SI].M_Ysize ; Push Default Y size + MOV AL, CS:[SI].M_Pages ; Get Default # of Pages + mov ah,0 ; Hi Byte = 0 + PUSH AX ; Push # Pages + + CALL f SET_VGA_MODEX ; Set up Mode X! + +@SMX_Exit: + ;POPx SI, BP ; Restore Registers + pop si + pop bp + RET 2 ; Exit & Clean Up Stack + +SET_MODEX ENDP + + + ; ===== BASIC GRAPHICS PRIMITIVES ===== + +;============================ +;CLEAR_VGA_SCREEN (ColorNum%) +;============================ +; +; Clears the active display page +; +; ENTRY: ColorNum = Color Value to fill the page with +; +; EXIT: No meaningful values returned +; + +CVS_STACK STRUC + DW ?,? ; DI, BP + DD ? ; Caller + CVS_COLOR DB ?,? ; Color to Set Screen to +CVS_STACK ENDS + + PUBLIC CLEAR_VGA_SCREEN + +CLEAR_VGA_SCREEN PROC FAR + + ;PUSHx BP, DI ; Preserve Important Registers + push bp + push di + MOV BP, SP ; Set up Stack Frame + + OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + + MOV AL, [BP].CVS_COLOR ; Get Color + MOV AH, AL ; Copy for Word Write + CLD ; Block fill Forwards + + MOV CX, PAGE_SIZE ; Get Size of Page + SHR CX, 1 ; Divide by 2 for Words + REP STOSW ; Block Fill VGA memory + + ;POPx DI, BP ; Restore Saved Registers + pop di + pop bp + RET 2 ; Exit & Clean Up Stack + +CLEAR_VGA_SCREEN ENDP + + +;=================================== +;SET_POINT (Xpos%, Ypos%, ColorNum%) +;=================================== +; +; Plots a single Pixel on the active display page +; +; ENTRY: Xpos = X position to plot pixel at +; Ypos = Y position to plot pixel at +; ColorNum = Color to plot pixel with +; +; EXIT: No meaningful values returned +; + +SP_STACK STRUC + DW ?,? ; BP, DI + DD ? ; Caller + SETP_Color DB ?,? ; Color of Point to Plot + SETP_Ypos DW ? ; Y pos of Point to Plot + SETP_Xpos DW ? ; X pos of Point to Plot +SP_STACK ENDS + + PUBLIC SET_POINT + +SET_POINT PROC FAR + + ;PUSHx BP, DI ; Preserve Registers + push bp + push di + MOV BP, SP ; Set up Stack Frame + + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + + MOV AX, [BP].SETP_Ypos ; Get Line # of Pixel + MUL SCREEN_WIDTH ; Get Offset to Start of Line + + MOV BX, [BP].SETP_Xpos ; Get Xpos + MOV CX, BX ; Copy to extract Plane # from + SHR BX, 1 ; X offset (Bytes) = Xpos/4 + SHR BX, 1 ; X offset (Bytes) = Xpos/4 + ADD BX, AX ; Offset = Width*Ypos + Xpos/4 + + MOV AX, MAP_MASK_PLANE1 ; Map Mask & Plane Select Register + AND CL, PLANE_BITS ; Get Plane Bits + SHL AH, CL ; Get Plane Select Value + OUT_16 SC_Index, AX ; Select Plane + + MOV AL,[BP].SETP_Color ; Get Pixel Color + MOV ES:[DI+BX], AL ; Draw Pixel + + ;POPx DI, BP ; Restore Saved Registers + pop di + pop bp + RET 6 ; Exit and Clean up Stack + +SET_POINT ENDP + + +;========================== +;READ_POINT% (Xpos%, Ypos%) +;========================== +; +; Read the color of a pixel from the Active Display Page +; +; ENTRY: Xpos = X position of pixel to read +; Ypos = Y position of pixel to read +; +; EXIT: AX = Color of Pixel at (Xpos, Ypos) +; + +RP_STACK STRUC + DW ?,? ; BP, DI + DD ? ; Caller + RP_Ypos DW ? ; Y pos of Point to Read + RP_Xpos DW ? ; X pos of Point to Read +RP_STACK ENDS + + PUBLIC READ_POINT + +READ_POINT PROC FAR + + ;PUSHx BP, DI ; Preserve Registers + push bp + push di + MOV BP, SP ; Set up Stack Frame + + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + + MOV AX, [BP].RP_Ypos ; Get Line # of Pixel + MUL SCREEN_WIDTH ; Get Offset to Start of Line + + MOV BX, [BP].RP_Xpos ; Get Xpos + MOV CX, BX + SHR BX, 1 ; X offset (Bytes) = Xpos/4 + SHR BX, 1 ; X offset (Bytes) = Xpos/4 + ADD BX, AX ; Offset = Width*Ypos + Xpos/4 + + MOV AL, READ_MAP ; GC Read Mask Register + MOV AH, CL ; Get Xpos + AND AH, PLANE_BITS ; & mask out Plane # + OUT_16 GC_INDEX, AX ; Select Plane to read in + + mov ah,0 ; Clear Return Value Hi byte + MOV AL, ES:[DI+BX] ; Get Color of Pixel + + ;POPx DI, BP ; Restore Saved Registers + pop di + pop bp + RET 4 ; Exit and Clean up Stack + +READ_POINT ENDP + + +;====================================================== +;FILL_BLOCK (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%) +;====================================================== +; +; Fills a rectangular block on the active display Page +; +; ENTRY: Xpos1 = Left X position of area to fill +; Ypos1 = Top Y position of area to fill +; Xpos2 = Right X position of area to fill +; Ypos2 = Bottom Y position of area to fill +; ColorNum = Color to fill area with +; +; EXIT: No meaningful values returned +; + +FB_STACK STRUC + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DD ? ; Caller + FB_Color DB ?,? ; Fill Color + FB_Ypos2 DW ? ; Y pos of Lower Right Pixel + FB_Xpos2 DW ? ; X pos of Lower Right Pixel + FB_Ypos1 DW ? ; Y pos of Upper Left Pixel + FB_Xpos1 DW ? ; X pos of Upper Left Pixel +FB_STACK ENDS + + PUBLIC FILL_BLOCK + +FILL_BLOCK PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + MOV BP, SP ; Set up Stack Frame + + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + CLD ; Direction Flag = Forward + + OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select + + ; Validate Pixel Coordinates + ; If necessary, Swap so X1 <= X2, Y1 <= Y2 + + MOV AX, [BP].FB_Ypos1 ; AX = Y1 is Y1< Y2? + MOV BX, [BP].FB_Ypos2 ; BX = Y2 + CMP AX, BX + JLE @FB_NOSWAP1 + + MOV [BP].FB_Ypos1, BX ; Swap Y1 and Y2 and save Y1 + XCHG AX, BX ; on stack for future use + +@FB_NOSWAP1: + SUB BX, AX ; Get Y width + INC BX ; Add 1 to avoid 0 value + MOV [BP].FB_Ypos2, BX ; Save in Ypos2 + + MUL SCREEN_WIDTH ; Mul Y1 by Bytes per Line + ADD DI, AX ; DI = Start of Line Y1 + + MOV AX, [BP].FB_Xpos1 ; Check X1 <= X2 + MOV BX, [BP].FB_Xpos2 ; + CMP AX, BX + JLE @FB_NOSWAP2 ; Skip Ahead if Ok + + MOV [BP].FB_Xpos2, AX ; Swap X1 AND X2 and save X2 + XCHG AX, BX ; on stack for future use + + ; All our Input Values are in order, Now determine + ; How many full "bands" 4 pixels wide (aligned) there + ; are, and if there are partial bands (<4 pixels) on + ; the left and right edges. + +@FB_NOSWAP2: + MOV DX, AX ; DX = X1 (Pixel Position) + SHR DX, 1 ; DX/4 = Bytes into Line + SHR DX, 1 ; DX/4 = Bytes into Line + ADD DI, DX ; DI = Addr of Upper-Left Corner + + MOV CX, BX ; CX = X2 (Pixel Position) + SHR CX, 1 ; CX/4 = Bytes into Line + SHR CX, 1 ; CX/4 = Bytes into Line + + CMP DX, CX ; Start and end in same band? + JNE @FB_NORMAL ; if not, check for l & r edges + JMP @FB_ONE_BAND_ONLY ; if so, then special processing + +@FB_NORMAL: + SUB CX, DX ; CX = # bands -1 + MOV SI, AX ; SI = PLANE#(X1) + AND SI, PLANE_BITS ; if Left edge is aligned then + JZ @FB_L_PLANE_FLUSH ; no special processing.. + + ; Draw "Left Edge" vertical strip of 1-3 pixels... + + OUT_8 SC_Data, Left_Clip_Mask[SI] ; Set Left Edge Plane Mask + + MOV SI, DI ; SI = Copy of Start Addr (UL) + + MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw + MOV AL, [BP].FB_Color ; Get Fill Color + MOV BX, SCREEN_WIDTH ; Get Vertical increment Value + +@FB_LEFT_LOOP: + MOV ES:[SI], AL ; Fill in Left Edge Pixels + ADD SI, BX ; Point to Next Line (Below) + LOOPjz DX, @FB_LEFT_CONT ; Exit loop if all Lines Drawn + + MOV ES:[SI], AL ; Fill in Left Edge Pixels + ADD SI, BX ; Point to Next Line (Below) + LOOPx DX, @FB_LEFT_LOOP ; loop until left strip is drawn + +@FB_LEFT_CONT: + + INC DI ; Point to Middle (or Right) Block + DEC CX ; Reset CX instead of JMP @FB_RIGHT + +@FB_L_PLANE_FLUSH: + INC CX ; Add in Left band to middle block + + ; DI = Addr of 1st middle Pixel (band) to fill + ; CX = # of Bands to fill -1 + +@FB_RIGHT: + MOV SI, [BP].FB_Xpos2 ; Get Xpos2 + AND SI, PLANE_BITS ; Get Plane values + CMP SI, 0003 ; Plane = 3? + JE @FB_R_EDGE_FLUSH ; Hey, add to middle + + ; Draw "Right Edge" vertical strip of 1-3 pixels... + + OUT_8 SC_Data, Right_Clip_Mask[SI] ; Right Edge Plane Mask + + MOV SI, DI ; Get Addr of Left Edge + ADD SI, CX ; Add Width-1 (Bands) + DEC SI ; To point to top of Right Edge + + MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw + MOV AL, [BP].FB_Color ; Get Fill Color + MOV BX, SCREEN_WIDTH ; Get Vertical increment Value + +@FB_RIGHT_LOOP: + MOV ES:[SI], AL ; Fill in Right Edge Pixels + ADD SI, BX ; Point to Next Line (Below) + LOOPjz DX, @FB_RIGHT_CONT ; Exit loop if all Lines Drawn + + MOV ES:[SI], AL ; Fill in Right Edge Pixels + ADD SI, BX ; Point to Next Line (Below) + LOOPx DX, @FB_RIGHT_LOOP ; loop until left strip is drawn + +@FB_RIGHT_CONT: + + DEC CX ; Minus 1 for Middle bands + JZ @FB_EXIT ; Uh.. no Middle bands... + +@FB_R_EDGE_FLUSH: + + ; DI = Addr of Upper Left block to fill + ; CX = # of Bands to fill in (width) + + OUT_8 SC_Data, ALL_PLANES ; Write to All Planes + + MOV DX, SCREEN_WIDTH ; DX = DI Increment + SUB DX, CX ; = Screen_Width-# Planes Filled + + MOV BX, CX ; BX = Quick Refill for CX + MOV SI, [BP].FB_Ypos2 ; SI = # of Line to Fill + MOV AL, [BP].FB_Color ; Get Fill Color + +@FB_MIDDLE_LOOP: + REP STOSB ; Fill in entire line + + MOV CX, BX ; Recharge CX (Line Width) + ADD DI, DX ; Point to start of Next Line + LOOPx SI, @FB_MIDDLE_LOOP ; Loop until all lines drawn + + JMP s @FB_EXIT ; Outa here + +@FB_ONE_BAND_ONLY: + MOV SI, AX ; Get Left Clip Mask, Save X1 + AND SI, PLANE_BITS ; Mask out Row # + MOV AL, Left_Clip_Mask[SI] ; Get Left Edge Mask + MOV SI, BX ; Get Right Clip Mask, Save X2 + AND SI, PLANE_BITS ; Mask out Row # + AND AL, Right_Clip_Mask[SI] ; Get Right Edge Mask byte + + OUT_8 SC_Data, AL ; Clip For Left & Right Masks + + MOV CX, [BP].FB_Ypos2 ; Get # of Lines to draw + MOV AL, [BP].FB_Color ; Get Fill Color + MOV BX, SCREEN_WIDTH ; Get Vertical increment Value + +@FB_ONE_LOOP: + MOV ES:[DI], AL ; Fill in Pixels + ADD DI, BX ; Point to Next Line (Below) + LOOPjz CX, @FB_EXIT ; Exit loop if all Lines Drawn + + MOV ES:[DI], AL ; Fill in Pixels + ADD DI, BX ; Point to Next Line (Below) + LOOPx CX, @FB_ONE_LOOP ; loop until left strip is drawn + +@FB_EXIT: + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + RET 10 ; Exit and Clean up Stack + +FILL_BLOCK ENDP + + +;===================================================== +;DRAW_LINE (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%) +;===================================================== +; +; Draws a Line on the active display page +; +; ENTRY: Xpos1 = X position of first point on line +; Ypos1 = Y position of first point on line +; Xpos2 = X position of last point on line +; Ypos2 = Y position of last point on line +; ColorNum = Color to draw line with +; +; EXIT: No meaningful values returned +; + +DL_STACK STRUC + DW ?x1 ; DI, SI, BP + DW ?x1 ; DI, SI, BP + DW ?x1 ; DI, SI, BP + DD ? ; Caller + DL_ColorF DB ?,? ; Line Draw Color + DL_Ypos2 DW ? ; Y pos of last point + DL_Xpos2 DW ? ; X pos of last point + DL_Ypos1 DW ? ; Y pos of first point + DL_Xpos1 DW ? ; X pos of first point +DL_STACK ENDS + + PUBLIC DRAW_LINE + +DRAW_LINE PROC FAR + + ;PUSHx BP, SI, DI ; Preserve Important Registers + push bp + push si + push di + MOV BP, SP ; Set up Stack Frame + CLD ; Direction Flag = Forward + + OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select + MOV CH, [BP].DL_ColorF ; Save Line Color in CH + + ; Check Line Type + + MOV SI, [BP].DL_Xpos1 ; AX = X1 is X1< X2? + MOV DI, [BP].DL_Xpos2 ; DX = X2 + CMP SI, DI ; Is X1 < X2 + JE @DL_VLINE ; If X1=X2, Draw Vertical Line + JL @DL_NOSWAP1 ; If X1 < X2, don't swap + + XCHG SI, DI ; X2 IS > X1, SO SWAP THEM + +@DL_NOSWAP1: + + ; SI = X1, DI = X2 + + MOV AX, [BP].DL_Ypos1 ; AX = Y1 is Y1 <> Y2? + CMP AX, [BP].DL_Ypos2 ; Y1 = Y2? + JE @DL_HORZ ; If so, Draw a Horizontal Line + + JMP @DL_BREZHAM ; Diagonal line... go do it... + + ; This Code draws a Horizontal Line in Mode X where: + ; SI = X1, DI = X2, and AX = Y1/Y2 + +@DL_HORZ: + + MUL SCREEN_WIDTH ; Offset = Ypos * Screen_Width + MOV DX, AX ; CX = Line offset into Page + + MOV AX, SI ; Get Left edge, Save X1 + AND SI, PLANE_BITS ; Mask out Row # + MOV BL, Left_Clip_Mask[SI] ; Get Left Edge Mask + MOV CX, DI ; Get Right edge, Save X2 + AND DI, PLANE_BITS ; Mask out Row # + MOV BH, Right_Clip_Mask[DI] ; Get Right Edge Mask byte + + SHR AX, 1 ; Get X1 Byte # (=X1/4) + SHR CX, 1 ; Get X2 Byte # (=X2/4) + SHR AX, 1 ; Get X1 Byte # (=X1/4) + SHR CX, 1 ; Get X2 Byte # (=X2/4) + + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + ADD DI, DX ; Point to Start of Line + ADD DI, AX ; Point to Pixel X1 + + SUB CX, AX ; CX = # Of Bands (-1) to set + JNZ @DL_LONGLN ; jump if longer than one segment + + AND BL, BH ; otherwise, merge clip masks + +@DL_LONGLN: + + OUT_8 SC_Data, BL ; Set the Left Clip Mask + + MOV AL, [BP].DL_ColorF ; Get Line Color + MOV BL, AL ; BL = Copy of Line Color + STOSB ; Set Left (1-4) Pixels + + JCXZ @DL_EXIT ; Done if only one Line Segment + + DEC CX ; CX = # of Middle Segments + JZ @DL_XRSEG ; If no middle segments.... + + ; Draw Middle Segments + + OUT_8 DX, ALL_PLANES ; Write to ALL Planes + + MOV AL, BL ; Get Color from BL + REP STOSB ; Draw Middle (4 Pixel) Segments + +@DL_XRSEG: + OUT_8 DX, BH ; Select Planes for Right Clip Mask + MOV AL, BL ; Get Color Value + STOSB ; Draw Right (1-4) Pixels + + JMP s @DL_EXIT ; We Are Done... + + + ; This Code Draws A Vertical Line. On entry: + ; CH = Line Color, SI & DI = X1 + +@DL_VLINE: + + MOV AX, [BP].DL_Ypos1 ; AX = Y1 + MOV SI, [BP].DL_Ypos2 ; SI = Y2 + CMP AX, SI ; Is Y1 < Y2? + JLE @DL_NOSWAP2 ; if so, Don't Swap them + + XCHG AX, SI ; Ok, NOW Y1 < Y2 + +@DL_NOSWAP2: + + SUB SI, AX ; SI = Line Height (Y2-Y1+1) + INC SI + + ; AX = Y1, DI = X1, Get offset into Page into AX + + MUL SCREEN_WIDTH ; Offset = Y1 (AX) * Screen Width + MOV DX, DI ; Copy Xpos into DX + SHR DI, 1 ; DI = Xpos/4 + SHR DI, 1 ; DI = Xpos/4 + ADD AX, DI ; DI = Xpos/4 + ScreenWidth * Y1 + + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + ADD DI, AX ; Point to Pixel X1, Y1 + + ;Select Plane + + MOV CL, DL ; CL = Save X1 + AND CL, PLANE_BITS ; Get X1 MOD 4 (Plane #) + MOV AX, MAP_MASK_PLANE1 ; Code to set Plane #1 + SHL AH, CL ; Change to Correct Plane # + OUT_16 SC_Index, AX ; Select Plane + + MOV AL, CH ; Get Saved Color + MOV BX, SCREEN_WIDTH ; Get Offset to Advance Line By + +@DL_VLoop: + MOV ES:[DI], AL ; Draw Single Pixel + ADD DI, BX ; Point to Next Line + LOOPjz SI, @DL_EXIT ; Lines--, Exit if done + + MOV ES:[DI], AL ; Draw Single Pixel + ADD DI, BX ; Point to Next Line + LOOPx SI, @DL_VLoop ; Lines--, Loop until Done + +@DL_EXIT: + + JMP @DL_EXIT2 ; Done! + + ; This code Draws a diagonal line in Mode X + +@DL_BREZHAM: + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + + MOV AX, [BP].DL_Ypos1 ; get Y1 value + MOV BX, [BP].DL_Ypos2 ; get Y2 value + MOV CX, [BP].DL_Xpos1 ; Get Starting Xpos + + CMP BX, AX ; Y2-Y1 is? + JNC @DL_DeltaYOK ; if Y2>=Y1 then goto... + + XCHG BX, AX ; Swap em... + MOV CX, [BP].DL_Xpos2 ; Get New Starting Xpos + +@DL_DeltaYOK: + MUL SCREEN_WIDTH ; Offset = SCREEN_WIDTH * Y1 + + ADD DI, AX ; DI -> Start of Line Y1 on Page + MOV AX, CX ; AX = Xpos (X1) + SHR AX, 1 ; /4 = Byte Offset into Line + SHR AX, 1 ; /4 = Byte Offset into Line + ADD DI, AX ; DI = Starting pos (X1,Y1) + + MOV AL, 11h ; Staring Mask + AND CL, PLANE_BITS ; Get Plane # + SHL AL, CL ; and shift into place + MOV AH, [BP].DL_ColorF ; Color in Hi Bytes + + PUSH AX ; Save Mask,Color... + + MOV AH, AL ; Plane # in AH + MOV AL, MAP_MASK ; Select Plane Register + OUT_16 SC_Index, AX ; Select initial plane + + MOV AX, [BP].DL_Xpos1 ; get X1 value + MOV BX, [BP].DL_Ypos1 ; get Y1 value + MOV CX, [BP].DL_Xpos2 ; get X2 value + MOV DX, [BP].DL_Ypos2 ; get Y2 value + + MOV BP, SCREEN_WIDTH ; Use BP for Line width to + ; to avoid extra memory access + + SUB DX, BX ; figure Delta_Y + JNC @DL_DeltaYOK2 ; jump if Y2 >= Y1 + + ADD BX, DX ; put Y2 into Y1 + NEG DX ; abs(Delta_Y) + XCHG AX, CX ; and exchange X1 and X2 + +@DL_DeltaYOK2: + MOV BX, 08000H ; seed for fraction accumulator + + SUB CX, AX ; figure Delta_X + JC @DL_DrawLeft ; if negative, go left + + JMP @DL_DrawRight ; Draw Line that slopes right + +@DL_DrawLeft: + + NEG CX ; abs(Delta_X) + + CMP CX, DX ; is Delta_X < Delta_Y? + JB @DL_SteepLeft ; yes, so go do steep line + ; (Delta_Y iterations) + + ; Draw a Shallow line to the left in Mode X + +@DL_ShallowLeft: + mov ax,0 ; zero low word of Delta_Y * 10000h + SUB AX, DX ; DX:AX <- DX * 0FFFFh + SBB DX, 0 ; include carry + DIV CX ; divide by Delta_X + + MOV SI, BX ; SI = Accumulator + MOV BX, AX ; BX = Add fraction + POP AX ; Get Color, Bit mask + MOV DX, SC_Data ; Sequence controller data register + INC CX ; Inc Delta_X so we can unroll loop + + ; Loop (x2) to Draw Pixels, Move Left, and Maybe Down... + +@DL_SLLLoop: + MOV ES:[DI], AH ; set first pixel, plane data set up + LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done + + ADD SI, BX ; add numerator to accumulator + JNC @DL_SLLL2nc ; move down on carry + + ADD DI, BP ; Move Down one line... + +@DL_SLLL2nc: + DEC DI ; Left one addr + ROR AL, 1 ; Move Left one plane, back on 0 1 2 + CMP AL, 87h ; wrap?, if AL <88 then Carry set + ADC DI, 0 ; Adjust Address: DI = DI + Carry + OUT DX, AL ; Set up New Bit Plane mask + + MOV ES:[DI], AH ; set pixel + LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done + + ADD SI, BX ; add numerator to accumulator, + JNC @DL_SLLL3nc ; move down on carry + + ADD DI, BP ; Move Down one line... + +@DL_SLLL3nc: ; Now move left a pixel... + DEC DI ; Left one addr + ROR AL, 1 ; Move Left one plane, back on 0 1 2 + CMP AL, 87h ; Wrap?, if AL <88 then Carry set + ADC DI, 0 ; Adjust Address: DI = DI + Carry + OUT DX, AL ; Set up New Bit Plane mask + JMP s @DL_SLLLoop ; loop until done + +@DL_SLLExit: + JMP @DL_EXIT2 ; and exit + + ; Draw a steep line to the left in Mode X + +@DL_SteepLeft: + mov ax,0 ; zero low word of Delta_Y * 10000h + XCHG DX, CX ; Delta_Y switched with Delta_X + DIV CX ; divide by Delta_Y + + MOV SI, BX ; SI = Accumulator + MOV BX, AX ; BX = Add Fraction + POP AX ; Get Color, Bit mask + MOV DX, SC_Data ; Sequence controller data register + INC CX ; Inc Delta_Y so we can unroll loop + + ; Loop (x2) to Draw Pixels, Move Down, and Maybe left + +@DL_STLLoop: + + MOV ES:[DI], AH ; set first pixel + LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done + + ADD SI, BX ; add numerator to accumulator + JNC @DL_STLnc2 ; No carry, just move down! + + DEC DI ; Move Left one addr + ROR AL, 1 ; Move Left one plane, back on 0 1 2 + CMP AL, 87h ; Wrap?, if AL <88 then Carry set + ADC DI, 0 ; Adjust Address: DI = DI + Carry + OUT DX, AL ; Set up New Bit Plane mask + +@DL_STLnc2: + ADD DI, BP ; advance to next line. + + MOV ES:[DI], AH ; set pixel + LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done + + ADD SI, BX ; add numerator to accumulator + JNC @DL_STLnc3 ; No carry, just move down! + + DEC DI ; Move Left one addr + ROR AL, 1 ; Move Left one plane, back on 0 1 2 + CMP AL, 87h ; Wrap?, if AL <88 then Carry set + ADC DI, 0 ; Adjust Address: DI = DI + Carry + OUT DX, AL ; Set up New Bit Plane mask + +@DL_STLnc3: + ADD DI, BP ; advance to next line. + JMP s @DL_STLLoop ; Loop until done + +@DL_STLExit: + JMP @DL_EXIT2 ; and exit + + ; Draw a line that goes to the Right... + +@DL_DrawRight: + CMP CX, DX ; is Delta_X < Delta_Y? + JB @DL_SteepRight ; yes, so go do steep line + ; (Delta_Y iterations) + + ; Draw a Shallow line to the Right in Mode X + +@DL_ShallowRight: + mov ax,0 ; zero low word of Delta_Y * 10000h + SUB AX, DX ; DX:AX <- DX * 0FFFFh + SBB DX, 0 ; include carry + DIV CX ; divide by Delta_X + + MOV SI, BX ; SI = Accumulator + MOV BX, AX ; BX = Add Fraction + POP AX ; Get Color, Bit mask + MOV DX, SC_Data ; Sequence controller data register + INC CX ; Inc Delta_X so we can unroll loop + + ; Loop (x2) to Draw Pixels, Move Right, and Maybe Down... + +@DL_SLRLoop: + MOV ES:[DI], AH ; set first pixel, mask is set up + LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done.. + + ADD SI, BX ; add numerator to accumulator + JNC @DL_SLR2nc ; don't move down if carry not set + + ADD DI, BP ; Move Down one line... + +@DL_SLR2nc: ; Now move right a pixel... + ROL AL, 1 ; Move Right one addr if Plane = 0 + CMP AL, 12h ; Wrap? if AL >12 then Carry not set + ADC DI, 0 ; Adjust Address: DI = DI + Carry + OUT DX, AL ; Set up New Bit Plane mask + + MOV ES:[DI], AH ; set pixel + LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done.. + + ADD SI, BX ; add numerator to accumulator + JNC @DL_SLR3nc ; don't move down if carry not set + + ADD DI, BP ; Move Down one line... + +@DL_SLR3nc: + ROL AL, 1 ; Move Right one addr if Plane = 0 + CMP AL, 12h ; Wrap? if AL >12 then Carry not set + ADC DI, 0 ; Adjust Address: DI = DI + Carry + OUT DX, AL ; Set up New Bit Plane mask + JMP s @DL_SLRLoop ; loop till done + +@DL_SLRExit: + JMP @DL_EXIT2 ; and exit + + ; Draw a Steep line to the Right in Mode X + +@DL_SteepRight: + mov ax,0 ; zero low word of Delta_Y * 10000h + XCHG DX, CX ; Delta_Y switched with Delta_X + DIV CX ; divide by Delta_Y + + MOV SI, BX ; SI = Accumulator + MOV BX, AX ; BX = Add Fraction + POP AX ; Get Color, Bit mask + MOV DX, SC_Data ; Sequence controller data register + INC CX ; Inc Delta_Y so we can unroll loop + + ; Loop (x2) to Draw Pixels, Move Down, and Maybe Right + +@STRLoop: + MOV ES:[DI], AH ; set first pixel, mask is set up + LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done + + ADD SI, BX ; add numerator to accumulator + JNC @STRnc2 ; if no carry then just go down... + + ROL AL, 1 ; Move Right one addr if Plane = 0 + CMP AL, 12h ; Wrap? if AL >12 then Carry not set + ADC DI, 0 ; Adjust Address: DI = DI + Carry + OUT DX, AL ; Set up New Bit Plane mask + +@STRnc2: + ADD DI, BP ; advance to next line. + + MOV ES:[DI], AH ; set pixel + LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done + + ADD SI, BX ; add numerator to accumulator + JNC @STRnc3 ; if no carry then just go down... + + ROL AL, 1 ; Move Right one addr if Plane = 0 + CMP AL, 12h ; Wrap? if AL >12 then Carry not set + ADC DI, 0 ; Adjust Address: DI = DI + Carry + OUT DX, AL ; Set up New Bit Plane mask + +@STRnc3: + ADD DI, BP ; advance to next line. + JMP s @STRLoop ; loop till done + +@DL_EXIT2: + ;POPx DI, SI, BP ; Restore Saved Registers + pop di + pop si + pop bp + RET 10 ; Exit and Clean up Stack + +DRAW_LINE ENDP + + + ; ===== DAC COLOR REGISTER ROUTINES ===== + +;================================================= +;SET_DAC_REGISTER (Register%, Red%, Green%, Blue%) +;================================================= +; +; Sets a single (RGB) Vga Palette Register +; +; ENTRY: Register = The DAC # to modify (0-255) +; Red = The new Red Intensity (0-63) +; Green = The new Green Intensity (0-63) +; Blue = The new Blue Intensity (0-63) +; +; EXIT: No meaningful values returned +; + +SDR_STACK STRUC + DW ? ; BP + DD ? ; Caller + SDR_Blue DB ?,? ; Blue Data Value + SDR_Green DB ?,? ; Green Data Value + SDR_Red DB ?,? ; Red Data Value + SDR_Register DB ?,? ; Palette Register # +SDR_STACK ENDS + + PUBLIC SET_DAC_REGISTER + +SET_DAC_REGISTER PROC FAR + + PUSH BP ; Save BP + MOV BP, SP ; Set up Stack Frame + + ; Select which DAC Register to modify + + OUT_8 DAC_WRITE_ADDR, [BP].SDR_Register + + MOV DX, PEL_DATA_REG ; Dac Data Register + OUT_8 DX, [BP].SDR_Red ; Set Red Intensity + OUT_8 DX, [BP].SDR_Green ; Set Green Intensity + OUT_8 DX, [BP].SDR_Blue ; Set Blue Intensity + + POP BP ; Restore Registers + RET 8 ; Exit & Clean Up Stack + +SET_DAC_REGISTER ENDP + +;==================================================== +;GET_DAC_REGISTER (Register%, &Red%, &Green%, &Blue%) +;==================================================== +; +; Reads the RGB Values of a single Vga Palette Register +; +; ENTRY: Register = The DAC # to read (0-255) +; Red = Offset to Red Variable in DS +; Green = Offset to Green Variable in DS +; Blue = Offset to Blue Variable in DS +; +; EXIT: The values of the integer variables Red, +; Green, and Blue are set to the values +; taken from the specified DAC register. +; + +GDR_STACK STRUC + DW ? ; BP + DD ? ; Caller + GDR_Blue DW ? ; Addr of Blue Data Value in DS + GDR_Green DW ? ; Addr of Green Data Value in DS + GDR_Red DW ? ; Addr of Red Data Value in DS + GDR_Register DB ?,? ; Palette Register # +GDR_STACK ENDS + + PUBLIC GET_DAC_REGISTER + +GET_DAC_REGISTER PROC FAR + + PUSH BP ; Save BP + MOV BP, SP ; Set up Stack Frame + + ; Select which DAC Register to read in + + OUT_8 DAC_READ_ADDR, [BP].GDR_Register + + MOV DX, PEL_DATA_REG ; Dac Data Register + mov ax,0 ; Clear AX + + IN AL, DX ; Read Red Value + MOV BX, [BP].GDR_Red ; Get Address of Red% + MOV [BX], AX ; *Red% = AX + + IN AL, DX ; Read Green Value + MOV BX, [BP].GDR_Green ; Get Address of Green% + MOV [BX], AX ; *Green% = AX + + IN AL, DX ; Read Blue Value + MOV BX, [BP].GDR_Blue ; Get Address of Blue% + MOV [BX], AX ; *Blue% = AX + + POP BP ; Restore Registers + RET 8 ; Exit & Clean Up Stack + +GET_DAC_REGISTER ENDP + + +;=========================================================== +;LOAD_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%, Sync%) +;=========================================================== +; +; Sets a Block of Vga Palette Registers +; +; ENTRY: PalData = Far Pointer to Block of palette data +; StartReg = First Register # in range to set (0-255) +; EndReg = Last Register # in Range to set (0-255) +; Sync = Wait for Vertical Retrace Flag (Boolean) +; +; EXIT: No meaningful values returned +; +; NOTES: PalData is a linear array of 3 byte Palette values +; in the order: Red (0-63), Green (0-63), Blue (0-63) +; + +LDR_STACK STRUC + DW ?x1 ; BP, DS, SI + DW ?x1 ; BP, DS, SI + DW ?x1 ; BP, DS, SI + DD ? ; Caller + LDR_Sync DW ? ; Vertical Sync Flag + LDR_EndReg DB ?,? ; Last Register # + LDR_StartReg DB ?,? ; First Register # + LDR_PalData DD ? ; Far Ptr to Palette Data +LDR_STACK ENDS + + PUBLIC LOAD_DAC_REGISTERS + +LOAD_DAC_REGISTERS PROC FAR + + ;PUSHx BP, DS, SI ; Save Registers + push bp + push ds + push si + mov BP, SP ; Set up Stack Frame + + mov AX, [BP].LDR_Sync ; Get Vertical Sync Flag + or AX, AX ; is Sync Flag = 0? + jz @LDR_Load ; if so, skip call + + call f SYNC_DISPLAY ; wait for vsync + + ; Determine register #'s, size to copy, etc + +@LDR_Load: + + lds SI, [BP].LDR_PalData ; DS:SI -> Palette Data + mov DX, DAC_WRITE_ADDR ; DAC register # selector + + mov ax,0, BX ; Clear for byte loads + mov AL, [BP].LDR_StartReg ; Get Start Register + mov BL, [BP].LDR_EndReg ; Get End Register + + sub BX, AX ; BX = # of DAC registers -1 + inc BX ; BX = # of DAC registers + mov CX, BX ; CX = # of DAC registers + add CX, BX ; CX = " " * 2 + add CX, BX ; CX = " " * 3 + cld ; Block OUTs forward + out DX, AL ; set up correct register # + + ; Load a block of DAC Registers + + mov DX, PEL_DATA_REG ; Dac Data Register + + ;rep outsb ; block set DAC registers + + ;POPx SI, DS, BP ; Restore Registers + pop si + pop ds + pop bp + ret 10 ; Exit & Clean Up Stack + +LOAD_DAC_REGISTERS ENDP + + +;==================================================== +;READ_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%) +;==================================================== +; +; Reads a Block of Vga Palette Registers +; +; ENTRY: PalData = Far Pointer to block to store palette data +; StartReg = First Register # in range to read (0-255) +; EndReg = Last Register # in Range to read (0-255) +; +; EXIT: No meaningful values returned +; +; NOTES: PalData is a linear array of 3 byte Palette values +; in the order: Red (0-63), Green (0-63), Blue (0-63) +; + +RDR_STACK STRUC + DW ?x1 ; BP, ES, DI + DW ?x1 ; BP, ES, DI + DW ?x1 ; BP, ES, DI + DD ? ; Caller + RDR_EndReg DB ?,? ; Last Register # + RDR_StartReg DB ?,? ; First Register # + RDR_PalData DD ? ; Far Ptr to Palette Data +RDR_STACK ENDS + + PUBLIC READ_DAC_REGISTERS + +READ_DAC_REGISTERS PROC FAR + + ;PUSHx BP, ES, DI ; Save Registers + push bp + push es + push di + mov BP, SP ; Set up Stack Frame + + ; Determine register #'s, size to copy, etc + + les DI, [BP].RDR_PalData ; ES:DI -> Palette Buffer + mov DX, DAC_READ_ADDR ; DAC register # selector + + mov ax,0, BX ; Clear for byte loads + mov AL, [BP].RDR_StartReg ; Get Start Register + mov BL, [BP].RDR_EndReg ; Get End Register + + sub BX, AX ; BX = # of DAC registers -1 + inc BX ; BX = # of DAC registers + mov CX, BX ; CX = # of DAC registers + add CX, BX ; CX = " " * 2 + add CX, BX ; CX = " " * 3 + cld ; Block INs forward + + ; Read a block of DAC Registers + + out DX, AL ; set up correct register # + mov DX, PEL_DATA_REG ; Dac Data Register + + ;rep insb ; block read DAC registers + + ;POPx DI, ES, BP ; Restore Registers + pop di + pop es + pop bp + ret 8 ; Exit & Clean Up Stack + +READ_DAC_REGISTERS ENDP + + + ; ===== PAGE FLIPPING AND SCROLLING ROUTINES ===== + +;========================= +;SET_ACTIVE_PAGE (PageNo%) +;========================= +; +; Sets the active display Page to be used for future drawing +; +; ENTRY: PageNo = Display Page to make active +; (values: 0 to Number of Pages - 1) +; +; EXIT: No meaningful values returned +; + +SAP_STACK STRUC + DW ? ; BP + DD ? ; Caller + SAP_Page DW ? ; Page # for Drawing +SAP_STACK ENDS + + PUBLIC SET_ACTIVE_PAGE + +SET_ACTIVE_PAGE PROC FAR + + PUSH BP ; Preserve Registers + MOV BP, SP ; Set up Stack Frame + + MOV BX, [BP].SAP_Page ; Get Desired Page # + CMP BX, LAST_PAGE ; Is Page # Valid? + JAE @SAP_Exit ; IF Not, Do Nothing + + MOV ACTIVE_PAGE, BX ; Set Active Page # + + SHL BX, 1 ; Scale Page # to Word + MOV AX, PAGE_ADDR[BX] ; Get offset to Page + + MOV CURRENT_PAGE, AX ; And set for future LES's + +@SAP_Exit: + POP BP ; Restore Registers + RET 2 ; Exit and Clean up Stack + +SET_ACTIVE_PAGE ENDP + + +;================ +;GET_ACTIVE_PAGE% +;================ +; +; Returns the Video Page # currently used for Drawing +; +; ENTRY: No Parameters are passed +; +; EXIT: AX = Current Video Page used for Drawing +; + + PUBLIC GET_ACTIVE_PAGE + +GET_ACTIVE_PAGE PROC FAR + + MOV AX, ACTIVE_PAGE ; Get Active Page # + RET ; Exit and Clean up Stack + +GET_ACTIVE_PAGE ENDP + + +;=============================== +;SET_DISPLAY_PAGE (DisplayPage%) +;=============================== +; +; Sets the currently visible display page. +; When called this routine syncronizes the display +; to the vertical blank. +; +; ENTRY: PageNo = Display Page to show on the screen +; (values: 0 to Number of Pages - 1) +; +; EXIT: No meaningful values returned +; + +SDP_STACK STRUC + DW ? ; BP + DD ? ; Caller + SDP_Page DW ? ; Page # to Display... +SDP_STACK ENDS + + PUBLIC SET_DISPLAY_PAGE + +SET_DISPLAY_PAGE PROC FAR + + PUSH BP ; Preserve Registers + MOV BP, SP ; Set up Stack Frame + + MOV BX, [BP].SDP_Page ; Get Desired Page # + CMP BX, LAST_PAGE ; Is Page # Valid? + JAE @SDP_Exit ; IF Not, Do Nothing + + MOV DISPLAY_PAGE, BX ; Set Display Page # + + SHL BX, 1 ; Scale Page # to Word + MOV CX, PAGE_ADDR[BX] ; Get offset in memory to Page + ADD CX, CURRENT_MOFFSET ; Adjust for any scrolling + + ; Wait if we are currently in a Vertical Retrace + + MOV DX, INPUT_1 ; Input Status #1 Register + +@DP_WAIT0: + IN AL, DX ; Get VGA status + AND AL, VERT_RETRACE ; In Display mode yet? + JNZ @DP_WAIT0 ; If Not, wait for it + + ; Set the Start Display Address to the new page + + MOV DX, CRTC_Index ; We Change the VGA Sequencer + + MOV AL, START_DISP_LO ; Display Start Low Register + MOV AH, CL ; Low 8 Bits of Start Addr + OUT DX, AX ; Set Display Addr Low + + MOV AL, START_DISP_HI ; Display Start High Register + MOV AH, CH ; High 8 Bits of Start Addr + OUT DX, AX ; Set Display Addr High + + ; Wait for a Vertical Retrace to smooth out things + + MOV DX, INPUT_1 ; Input Status #1 Register + +@DP_WAIT1: + IN AL, DX ; Get VGA status + AND AL, VERT_RETRACE ; Vertical Retrace Start? + JZ @DP_WAIT1 ; If Not, wait for it + + ; Now Set Display Starting Address + + +@SDP_Exit: + POP BP ; Restore Registers + RET 2 ; Exit and Clean up Stack + +SET_DISPLAY_PAGE ENDP + + +;================= +;GET_DISPLAY_PAGE% +;================= +; +; Returns the Video Page # currently displayed +; +; ENTRY: No Parameters are passed +; +; EXIT: AX = Current Video Page being displayed +; + + PUBLIC GET_DISPLAY_PAGE + +GET_DISPLAY_PAGE PROC FAR + + MOV AX, DISPLAY_PAGE ; Get Display Page # + RET ; Exit & Clean Up Stack + +GET_DISPLAY_PAGE ENDP + + +;======================================= +;SET_WINDOW (DisplayPage%, Xpos%, Ypos%) +;======================================= +; +; Since a Logical Screen can be larger than the Physical +; Screen, Scrolling is possible. This routine sets the +; Upper Left Corner of the Screen to the specified Pixel. +; Also Sets the Display page to simplify combined page +; flipping and scrolling. When called this routine +; syncronizes the display to the vertical blank. +; +; ENTRY: DisplayPage = Display Page to show on the screen +; Xpos = # of pixels to shift screen right +; Ypos = # of lines to shift screen down +; +; EXIT: No meaningful values returned +; + +SW_STACK STRUC + DW ? ; BP + DD ? ; Caller + SW_Ypos DW ? ; Y pos of UL Screen Corner + SW_Xpos DW ? ; X pos of UL Screen Corner + SW_Page DW ? ; (new) Display Page +SW_STACK ENDS + + PUBLIC SET_WINDOW + +SET_WINDOW PROC FAR + + PUSH BP ; Preserve Registers + MOV BP, SP ; Set up Stack Frame + + ; Check if our Scroll Offsets are Valid + + MOV BX, [BP].SW_Page ; Get Desired Page # + CMP BX, LAST_PAGE ; Is Page # Valid? + JAE @SW_Exit ; IF Not, Do Nothing + + MOV AX, [BP].SW_Ypos ; Get Desired Y Offset + CMP AX, MAX_YOFFSET ; Is it Within Limits? + JA @SW_Exit ; if not, exit + + MOV CX, [BP].SW_Xpos ; Get Desired X Offset + CMP CX, MAX_XOFFSET ; Is it Within Limits? + JA @SW_Exit ; if not, exit + + ; Compute proper Display start address to use + + MUL SCREEN_WIDTH ; AX = YOffset * Line Width + SHR CX, 1 ; CX / 4 = Bytes into Line + SHR CX, 1 ; CX / 4 = Bytes into Line + ADD AX, CX ; AX = Offset of Upper Left Pixel + + MOV CURRENT_MOFFSET, AX ; Save Offset Info + + MOV DISPLAY_PAGE, BX ; Set Current Page # + SHL BX, 1 ; Scale Page # to Word + ADD AX, PAGE_ADDR[BX] ; Get offset in VGA to Page + MOV BX, AX ; BX = Desired Display Start + + MOV DX, INPUT_1 ; Input Status #1 Register + + ; Wait if we are currently in a Vertical Retrace + +@SW_WAIT0: + IN AL, DX ; Get VGA status + AND AL, VERT_RETRACE ; In Display mode yet? + JNZ @SW_WAIT0 ; If Not, wait for it + + ; Set the Start Display Address to the new window + + MOV DX, CRTC_Index ; We Change the VGA Sequencer + MOV AL, START_DISP_LO ; Display Start Low Register + MOV AH, BL ; Low 8 Bits of Start Addr + OUT DX, AX ; Set Display Addr Low + + MOV AL, START_DISP_HI ; Display Start High Register + MOV AH, BH ; High 8 Bits of Start Addr + OUT DX, AX ; Set Display Addr High + + ; Wait for a Vertical Retrace to smooth out things + + MOV DX, INPUT_1 ; Input Status #1 Register + +@SW_WAIT1: + IN AL, DX ; Get VGA status + AND AL, VERT_RETRACE ; Vertical Retrace Start? + JZ @SW_WAIT1 ; If Not, wait for it + + ; Now Set the Horizontal Pixel Pan values + + OUT_8 ATTRIB_Ctrl, PIXEL_PAN_REG ; Select Pixel Pan Register + + MOV AX, [BP].SW_Xpos ; Get Desired X Offset + AND AL, 03 ; Get # of Pixels to Pan (0-3) + SHL AL, 1 ; Shift for 256 Color Mode + OUT DX, AL ; Fine tune the display! + +@SW_Exit: + POP BP ; Restore Saved Registers + RET 6 ; Exit and Clean up Stack + +SET_WINDOW ENDP + + +;============= +;GET_X_OFFSET% +;============= +; +; Returns the X coordinate of the Pixel currently display +; in the upper left corner of the display +; +; ENTRY: No Parameters are passed +; +; EXIT: AX = Current Horizontal Scroll Offset +; + + PUBLIC GET_X_OFFSET + +GET_X_OFFSET PROC FAR + + MOV AX, CURRENT_XOFFSET ; Get current horz offset + RET ; Exit & Clean Up Stack + +GET_X_OFFSET ENDP + + +;============= +;GET_Y_OFFSET% +;============= +; +; Returns the Y coordinate of the Pixel currently display +; in the upper left corner of the display +; +; ENTRY: No Parameters are passed +; +; EXIT: AX = Current Vertical Scroll Offset +; + + PUBLIC GET_Y_OFFSET + +GET_Y_OFFSET PROC FAR + + MOV AX, CURRENT_YOFFSET ; Get current vertical offset + RET ; Exit & Clean Up Stack + +GET_Y_OFFSET ENDP + + +;============ +;SYNC_DISPLAY +;============ +; +; Pauses the computer until the next Vertical Retrace starts +; +; ENTRY: No Parameters are passed +; +; EXIT: No meaningful values returned +; + + PUBLIC SYNC_DISPLAY + +SYNC_DISPLAY PROC FAR + + MOV DX, INPUT_1 ; Input Status #1 Register + + ; Wait for any current retrace to end + +@SD_WAIT0: + IN AL, DX ; Get VGA status + AND AL, VERT_RETRACE ; In Display mode yet? + JNZ @SD_WAIT0 ; If Not, wait for it + + ; Wait for the start of the next vertical retrace + +@SD_WAIT1: + IN AL, DX ; Get VGA status + AND AL, VERT_RETRACE ; Vertical Retrace Start? + JZ @SD_WAIT1 ; If Not, wait for it + + RET ; Exit & Clean Up Stack + +SYNC_DISPLAY ENDP + + + ; ===== TEXT DISPLAY ROUTINES ===== + +;================================================== +;GPRINTC (CharNum%, Xpos%, Ypos%, ColorF%, ColorB%) +;================================================== +; +; Draws an ASCII Text Character using the currently selected +; 8x8 font on the active display page. It would be a simple +; exercise to make this routine process variable height fonts. +; +; ENTRY: CharNum = ASCII character # to draw +; Xpos = X position to draw Character at +; Ypos = Y position of to draw Character at +; ColorF = Color to draw text character in +; ColorB = Color to set background to +; +; EXIT: No meaningful values returned +; + +GPC_STACK STRUC + GPC_Width DW ? ; Screen Width-1 + GPC_Lines DB ?,? ; Scan lines to Decode + GPC_T_SETS DW ? ; Saved Charset Segment + GPC_T_SETO DW ? ; Saved Charset Offset + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DD ? ; Caller + GPC_ColorB DB ?,? ; Background Color + GPC_ColorF DB ?,? ; Text Color + GPC_Ypos DW ? ; Y Position to Print at + GPC_Xpos DW ? ; X position to Print at + GPC_Char DB ?,? ; Character to Print +GPC_STACK ENDS + + PUBLIC GPRINTC + +GPRINTC PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + SUB SP, 8 ; Allocate WorkSpace on Stack + MOV BP, SP ; Set up Stack Frame + + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + + MOV AX, SCREEN_WIDTH ; Get Logical Line Width + MOV BX, AX ; BX = Screen Width + DEC BX ; = Screen Width-1 + MOV [BP].GPC_Width, BX ; Save for later use + + MUL [BP].GPC_Ypos ; Start of Line = Ypos * Width + ADD DI, AX ; DI -> Start of Line Ypos + + MOV AX, [BP].GPC_Xpos ; Get Xpos of Character + MOV CX, AX ; Save Copy of Xpos + SHR AX, 1 ; Bytes into Line = Xpos/4 + SHR AX, 1 ; Bytes into Line = Xpos/4 + ADD DI, AX ; DI -> (Xpos, Ypos) + + ;Get Source ADDR of Character Bit Map & Save + + MOV AL, [BP].GPC_Char ; Get Character # + TEST AL, 080h ; Is Hi Bit Set? + JZ @GPC_LowChar ; Nope, use low char set ptr + + AND AL, 07Fh ; Mask Out Hi Bit + MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset + MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment + JMP s @GPC_Set_Char ; Go Setup Character Ptr + +@GPC_LowChar: + + MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset + MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment + +@GPC_Set_Char: + MOV [BP].GPC_T_SETS, DX ; Save Segment on Stack + + MOV AH, 0 ; Valid #'s are 0..127 + SHL AX, 1 ; * 8 Bytes Per Bitmap + SHL AX, 1 ; * 8 Bytes Per Bitmap + SHL AX, 1 ; * 8 Bytes Per Bitmap + ADD BX, AX ; BX = Offset of Selected char + MOV [BP].GPC_T_SETO, BX ; Save Offset on Stack + + AND CX, PLANE_BITS ; Get Plane # + MOV CH, ALL_PLANES ; Get Initial Plane mask + SHL CH, CL ; And shift into position + AND CH, ALL_PLANES ; And mask to lower nibble + + MOV AL, 04 ; 4-Plane # = # of initial + SUB AL, CL ; shifts to align bit mask + MOV CL, AL ; Shift Count for SHL + + ;Get segment of character map + + OUT_8 SC_Index, MAP_MASK ; Setup Plane selections + INC DX ; DX -> SC_Data + + MOV AL, 08 ; 8 Lines to Process + MOV [BP].GPC_Lines, AL ; Save on Stack + + MOV DS, [BP].GPC_T_SETS ; Point to character set + +@GPC_DECODE_CHAR_BYTE: + + MOV SI, [BP].GPC_T_SETO ; Get DS:SI = String + + MOV BH, [SI] ; Get Bit Map + INC SI ; Point to Next Line + MOV [BP].GPC_T_SETO, SI ; And save new Pointer... + + mov ax,0 ; Clear AX + + ;mov bl,0 ; Clear BL + mov bl,0 + ROL BX, CL ; BL holds left edge bits + MOV SI, BX ; Use as Table Index + AND SI, CHAR_BITS ; Get Low Bits + MOV AL, Char_Plane_Data[SI] ; Get Mask in AL + JZ @GPC_NO_LEFT1BITS ; Skip if No Pixels to set + + MOV AH, [BP].GPC_ColorF ; Get Foreground Color + OUT DX, AL ; Set up Screen Mask + MOV ES:[DI], AH ; Write Foreground color + +@GPC_NO_LEFT1BITS: + XOR AL, CH ; Invert mask for Background + JZ @GPC_NO_LEFT0BITS ; Hey, no need for this + + MOV AH, [BP].GPC_ColorB ; Get background Color + OUT DX, AL ; Set up Screen Mask + MOV ES:[DI], AH ; Write Foreground color + + ;Now Do Middle/Last Band + +@GPC_NO_LEFT0BITS: + INC DI ; Point to next Byte + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + + MOV SI, BX ; Make Lookup Pointer + AND SI, CHAR_BITS ; Get Low Bits + MOV AL, Char_Plane_Data[SI] ; Get Mask in AL + JZ @GPC_NO_MIDDLE1BITS ; Skip if no pixels to set + + MOV AH, [BP].GPC_ColorF ; Get Foreground Color + OUT DX, AL ; Set up Screen Mask + MOV ES:[DI], AH ; Write Foreground color + +@GPC_NO_MIDDLE1BITS: + XOR AL, ALL_PLANES ; Invert mask for Background + JZ @GPC_NO_MIDDLE0BITS ; Hey, no need for this + + MOV AH, [BP].GPC_ColorB ; Get background Color + OUT DX, AL ; Set up Screen Mask + MOV ES:[DI], AH ; Write Foreground color + +@GPC_NO_MIDDLE0BITS: + XOR CH, ALL_PLANES ; Invert Clip Mask + CMP CL, 4 ; Aligned by 4? + JZ @GPC_NEXT_LINE ; If so, Exit now.. + + INC DI ; Point to next Byte + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + + MOV SI, BX ; Make Lookup Pointer + AND SI, CHAR_BITS ; Get Low Bits + MOV AL, Char_Plane_Data[SI] ; Get Mask in AL + JZ @GPC_NO_RIGHT1BITS ; Skip if No Pixels to set + + MOV AH, [BP].GPC_ColorF ; Get Foreground Color + OUT DX, AL ; Set up Screen Mask + MOV ES:[DI], AH ; Write Foreground color + +@GPC_NO_RIGHT1BITS: + + XOR AL, CH ; Invert mask for Background + JZ @GPC_NO_RIGHT0BITS ; Hey, no need for this + + MOV AH, [BP].GPC_ColorB ; Get background Color + OUT DX, AL ; Set up Screen Mask + MOV ES:[DI], AH ; Write Foreground color + +@GPC_NO_RIGHT0BITS: + DEC DI ; Adjust for Next Line Advance + +@GPC_NEXT_LINE: + ADD DI, [BP].GPC_Width ; Point to Next Line + XOR CH, CHAR_BITS ; Flip the Clip mask back + + DEC [BP].GPC_Lines ; Count Down Lines + JZ @GPC_EXIT ; Ok... Done! + + JMP @GPC_DECODE_CHAR_BYTE ; Again! Hey! + +@GPC_EXIT: + ADD SP, 08 ; Deallocate stack workspace + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + RET 10 ; Exit and Clean up Stack + +GPRINTC ENDP + + +;========================================== +;TGPRINTC (CharNum%, Xpos%, Ypos%, ColorF%) +;========================================== +; +; Transparently draws an ASCII Text Character using the +; currently selected 8x8 font on the active display page. +; +; ENTRY: CharNum = ASCII character # to draw +; Xpos = X position to draw Character at +; Ypos = Y position of to draw Character at +; ColorF = Color to draw text character in +; +; EXIT: No meaningful values returned +; + +TGP_STACK STRUC + TGP_Width DW ? ; Screen Width-1 + TGP_Lines DB ?,? ; Scan lines to Decode + TGP_T_SETS DW ? ; Saved Charset Segment + TGP_T_SETO DW ? ; Saved Charset Offset + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DD ? ; Caller + TGP_ColorF DB ?,? ; Text Color + TGP_Ypos DW ? ; Y Position to Print at + TGP_Xpos DW ? ; X position to Print at + TGP_Char DB ?,? ; Character to Print +TGP_STACK ENDS + + PUBLIC TGPRINTC + +TGPRINTC PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + SUB SP, 8 ; Allocate WorkSpace on Stack + MOV BP, SP ; Set up Stack Frame + + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + + MOV AX, SCREEN_WIDTH ; Get Logical Line Width + MOV BX, AX ; BX = Screen Width + DEC BX ; = Screen Width-1 + MOV [BP].TGP_Width, BX ; Save for later use + + MUL [BP].TGP_Ypos ; Start of Line = Ypos * Width + ADD DI, AX ; DI -> Start of Line Ypos + + MOV AX, [BP].TGP_Xpos ; Get Xpos of Character + MOV CX, AX ; Save Copy of Xpos + SHR AX, 1 ; Bytes into Line = Xpos/4 + SHR AX, 1 ; Bytes into Line = Xpos/4 + ADD DI, AX ; DI -> (Xpos, Ypos) + + ;Get Source ADDR of Character Bit Map & Save + + MOV AL, [BP].TGP_Char ; Get Character # + TEST AL, 080h ; Is Hi Bit Set? + JZ @TGP_LowChar ; Nope, use low char set ptr + + AND AL, 07Fh ; Mask Out Hi Bit + MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset + MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment + JMP s @TGP_Set_Char ; Go Setup Character Ptr + +@TGP_LowChar: + + MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset + MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment + +@TGP_Set_Char: + MOV [BP].TGP_T_SETS, DX ; Save Segment on Stack + + MOV AH, 0 ; Valid #'s are 0..127 + SHL AX, 1 ; * 8 Bytes Per Bitmap + SHL AX, 1 ; * 8 Bytes Per Bitmap + SHL AX, 1 ; * 8 Bytes Per Bitmap + ADD BX, AX ; BX = Offset of Selected char + MOV [BP].TGP_T_SETO, BX ; Save Offset on Stack + + AND CX, PLANE_BITS ; Get Plane # + MOV CH, ALL_PLANES ; Get Initial Plane mask + SHL CH, CL ; And shift into position + AND CH, ALL_PLANES ; And mask to lower nibble + + MOV AL, 04 ; 4-Plane # = # of initial + SUB AL, CL ; shifts to align bit mask + MOV CL, AL ; Shift Count for SHL + + ;Get segment of character map + + OUT_8 SC_Index, MAP_MASK ; Setup Plane selections + INC DX ; DX -> SC_Data + + MOV AL, 08 ; 8 Lines to Process + MOV [BP].TGP_Lines, AL ; Save on Stack + + MOV DS, [BP].TGP_T_SETS ; Point to character set + +@TGP_DECODE_CHAR_BYTE: + + MOV SI, [BP].TGP_T_SETO ; Get DS:SI = String + + MOV BH, [SI] ; Get Bit Map + INC SI ; Point to Next Line + MOV [BP].TGP_T_SETO, SI ; And save new Pointer... + + MOV AH, [BP].TGP_ColorF ; Get Foreground Color + + mov bl,0 ; Clear BL + ROL BX, CL ; BL holds left edge bits + MOV SI, BX ; Use as Table Index + AND SI, CHAR_BITS ; Get Low Bits + MOV AL, Char_Plane_Data[SI] ; Get Mask in AL + JZ @TGP_NO_LEFT1BITS ; Skip if No Pixels to set + + OUT DX, AL ; Set up Screen Mask + MOV ES:[DI], AH ; Write Foreground color + + ;Now Do Middle/Last Band + +@TGP_NO_LEFT1BITS: + + INC DI ; Point to next Byte + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + + MOV SI, BX ; Make Lookup Pointer + AND SI, CHAR_BITS ; Get Low Bits + MOV AL, Char_Plane_Data[SI] ; Get Mask in AL + JZ @TGP_NO_MIDDLE1BITS ; Skip if no pixels to set + + OUT DX, AL ; Set up Screen Mask + MOV ES:[DI], AH ; Write Foreground color + +@TGP_NO_MIDDLE1BITS: + XOR CH, ALL_PLANES ; Invert Clip Mask + CMP CL, 4 ; Aligned by 4? + JZ @TGP_NEXT_LINE ; If so, Exit now.. + + INC DI ; Point to next Byte + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + + MOV SI, BX ; Make Lookup Pointer + AND SI, CHAR_BITS ; Get Low Bits + MOV AL, Char_Plane_Data[SI] ; Get Mask in AL + JZ @TGP_NO_RIGHT1BITS ; Skip if No Pixels to set + + OUT DX, AL ; Set up Screen Mask + MOV ES:[DI], AH ; Write Foreground color + +@TGP_NO_RIGHT1BITS: + + DEC DI ; Adjust for Next Line Advance + +@TGP_NEXT_LINE: + ADD DI, [BP].TGP_Width ; Point to Next Line + XOR CH, CHAR_BITS ; Flip the Clip mask back + + DEC [BP].TGP_Lines ; Count Down Lines + JZ @TGP_EXIT ; Ok... Done! + + JMP @TGP_DECODE_CHAR_BYTE ; Again! Hey! + +@TGP_EXIT: + ADD SP, 08 ; Deallocate stack workspace + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + RET 8 ; Exit and Clean up Stack + +TGPRINTC ENDP + + +;=============================================================== +;PRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%) +;=============================================================== +; +; Routine to quickly Print a null terminated ASCII string on the +; active display page up to a maximum length. +; +; ENTRY: String = Far Pointer to ASCII string to print +; MaxLen = # of characters to print if no null found +; Xpos = X position to draw Text at +; Ypos = Y position of to draw Text at +; ColorF = Color to draw text in +; ColorB = Color to set background to +; +; EXIT: No meaningful values returned +; + +PS_STACK STRUC + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DD ? ; Caller + PS_ColorB DW ? ; Background Color + PS_ColorF DW ? ; Text Color + PS_Ypos DW ? ; Y Position to Print at + PS_Xpos DW ? ; X position to Print at + PS_Len DW ? ; Maximum Length of string to print + PS_Text DW ?,? ; Far Ptr to Text String +PS_STACK ENDS + + PUBLIC PRINT_STR + +PRINT_STR PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + MOV BP, SP ; Set up Stack Frame + +@PS_Print_It: + + MOV CX, [BP].PS_Len ; Get Remaining text Length + JCXZ @PS_Exit ; Exit when out of text + + LES DI, d [BP].PS_Text ; ES:DI -> Current Char in Text + MOV AL, ES:[DI] ; AL = Text Character + AND AX, 00FFh ; Clear High Word + JZ @PS_Exit ; Exit if null character + + DEC [BP].PS_Len ; Remaining Text length-- + INC [BP].PS_Text ; Point to Next text char + + ; Set up Call to GPRINTC + + PUSH AX ; Set Character Parameter + MOV BX, [BP].PS_Xpos ; Get Xpos + PUSH BX ; Set Xpos Parameter + ADD BX, 8 ; Advance 1 Char to Right + MOV [BP].PS_Xpos, BX ; Save for next time through + + MOV BX, [BP].PS_Ypos ; Get Ypos + PUSH BX ; Set Ypos Parameter + + MOV BX, [BP].PS_ColorF ; Get Text Color + PUSH BX ; Set ColorF Parameter + + MOV BX, [BP].PS_ColorB ; Get Background Color + PUSH BX ; Set ColorB Parameter + + CALL f GPRINTC ; Print Character! + JMP s @PS_Print_It ; Process next character + +@PS_Exit: + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + RET 14 ; Exit and Clean up Stack + +PRINT_STR ENDP + + +;================================================================ +;TPRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%) +;================================================================ +; +; Routine to quickly transparently Print a null terminated ASCII +; string on the active display page up to a maximum length. +; +; ENTRY: String = Far Pointer to ASCII string to print +; MaxLen = # of characters to print if no null found +; Xpos = X position to draw Text at +; Ypos = Y position of to draw Text at +; ColorF = Color to draw text in +; +; EXIT: No meaningful values returned +; + +TPS_STACK STRUC + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DD ? ; Caller + TPS_ColorF DW ? ; Text Color + TPS_Ypos DW ? ; Y Position to Print at + TPS_Xpos DW ? ; X position to Print at + TPS_Len DW ? ; Maximum Length of string to print + TPS_Text DW ?,? ; Far Ptr to Text String +TPS_STACK ENDS + + PUBLIC TPRINT_STR + +TPRINT_STR PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + MOV BP, SP ; Set up Stack Frame + +@TPS_Print_It: + + MOV CX, [BP].TPS_Len ; Get Remaining text Length + JCXZ @TPS_Exit ; Exit when out of text + + LES DI, d [BP].TPS_Text ; ES:DI -> Current Char in Text + MOV AL, ES:[DI] ; AL = Text Character + AND AX, 00FFh ; Clear High Word + JZ @TPS_Exit ; Exit if null character + + DEC [BP].TPS_Len ; Remaining Text length-- + INC [BP].TPS_Text ; Point to Next text char + + ; Set up Call to TGPRINTC + + PUSH AX ; Set Character Parameter + MOV BX, [BP].TPS_Xpos ; Get Xpos + PUSH BX ; Set Xpos Parameter + ADD BX, 8 ; Advance 1 Char to Right + MOV [BP].TPS_Xpos, BX ; Save for next time through + + MOV BX, [BP].TPS_Ypos ; Get Ypos + PUSH BX ; Set Ypos Parameter + + MOV BX, [BP].TPS_ColorF ; Get Text Color + PUSH BX ; Set ColorF Parameter + + CALL f TGPRINTC ; Print Character! + JMP s @TPS_Print_It ; Process next character + +@TPS_Exit: + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + RET 12 ; Exit and Clean up Stack + +TPRINT_STR ENDP + + +;=========================================== +;SET_DISPLAY_FONT(SEG FontData, FontNumber%) +;=========================================== +; +; Allows the user to specify their own font data for +; wither the lower or upper 128 characters. +; +; ENTRY: FontData = Far Pointer to Font Bitmaps +; FontNumber = Which half of set this is +; = 0, Lower 128 characters +; = 1, Upper 128 characters +; +; EXIT: No meaningful values returned +; + +SDF_STACK STRUC + DW ? ; BP + DD ? ; Caller + SDF_Which DW ? ; Hi Table/Low Table Flag + SDF_Font DD ? ; Far Ptr to Font Table +SDF_STACK ENDS + + PUBLIC SET_DISPLAY_FONT + +SET_DISPLAY_FONT PROC FAR + + PUSH BP ; Preserve Registers + MOV BP, SP ; Set up Stack Frame + + LES DI, [BP].SDF_Font ; Get Far Ptr to Font + + MOV SI, o CHARSET_LOW ; Assume Lower 128 chars + TEST [BP].SDF_Which, 1 ; Font #1 selected? + JZ @SDF_Set_Font ; If not, skip ahead + + MOV SI, o CHARSET_HI ; Ah, really it's 128-255 + +@SDF_Set_Font: + MOV [SI], DI ; Set Font Pointer Offset + MOV [SI+2], ES ; Set Font Pointer Segment + + POP BP ; Restore Registers + RET 6 ; We are Done.. Outa here + +SET_DISPLAY_FONT ENDP + + + ; ===== BITMAP (SPRITE) DISPLAY ROUTINES ===== + +;====================================================== +;DRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%) +;====================================================== +; +; Draws a variable sized Graphics Bitmap such as a +; picture or an Icon on the current Display Page in +; Mode X. The Bitmap is stored in a linear byte array +; corresponding to (0,0) (1,0), (2,0) .. (Width, Height) +; This is the same linear manner as mode 13h graphics. +; +; ENTRY: Image = Far Pointer to Bitmap Data +; Xpos = X position to Place Upper Left pixel at +; Ypos = Y position to Place Upper Left pixel at +; Width = Width of the Bitmap in Pixels +; Height = Height of the Bitmap in Pixels +; +; EXIT: No meaningful values returned +; + +DB_STACK STRUC + DB_LineO DW ? ; Offset to Next Line + DB_PixCount DW ? ; (Minimum) # of Pixels/Line + DB_Start DW ? ; Addr of Upper Left Pixel + DB_PixSkew DW ? ; # of bytes to Adjust EOL + DB_SkewFlag DW ? ; Extra Pix on Plane Flag + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DD ? ; Caller + DB_Height DW ? ; Height of Bitmap in Pixels + DB_Width DW ? ; Width of Bitmap in Pixels + DB_Ypos DW ? ; Y position to Draw Bitmap at + DB_Xpos DW ? ; X position to Draw Bitmap at + DB_Image DD ? ; Far Pointer to Graphics Bitmap +DB_STACK ENDS + + PUBLIC DRAW_BITMAP + +DRAW_BITMAP PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + SUB SP, 10 ; Allocate workspace + MOV BP, SP ; Set up Stack Frame + + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + CLD ; Direction Flag = Forward + + MOV AX, [BP].DB_Ypos ; Get UL Corner Ypos + MUL SCREEN_WIDTH ; AX = Offset to Line Ypos + + MOV BX, [BP].DB_Xpos ; Get UL Corner Xpos + MOV CL, BL ; Save Plane # in CL + SHR BX, 1 ; Xpos/4 = Offset Into Line + SHR BX, 1 ; Xpos/4 = Offset Into Line + + ADD DI, AX ; ES:DI -> Start of Line + ADD DI, BX ; ES:DI -> Upper Left Pixel + MOV [BP].DB_Start, DI ; Save Starting Addr + + ; Compute line to line offset + + MOV BX, [BP].DB_Width ; Get Width of Image + MOV DX, BX ; Save Copy in DX + SHR BX, 1 ; /4 = width in bands + SHR BX, 1 ; /4 = width in bands + MOV AX, SCREEN_WIDTH ; Get Screen Width + SUB AX, BX ; - (Bitmap Width/4) + + MOV [BP].DB_LineO, AX ; Save Line Width offset + MOV [BP].DB_PixCount, BX ; Minimum # pix to copy + + AND DX, PLANE_BITS ; Get "partial band" size (0-3) + MOV [BP].DB_PixSkew, DX ; Also End of Line Skew + MOV [BP].DB_SkewFlag, DX ; Save as Flag/Count + + AND CX, PLANE_BITS ; CL = Starting Plane # + MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select + SHL AH, CL ; Select correct Plane + OUT_16 SC_Index, AX ; Select Plane... + MOV BH, AH ; BH = Saved Plane Mask + MOV BL, 4 ; BL = Planes to Copy + +@DB_COPY_PLANE: + + LDS SI, [BP].DB_Image ; DS:SI-> Source Image + MOV DX, [BP].DB_Height ; # of Lines to Copy + MOV DI, [BP].DB_Start ; ES:DI-> Dest pos + +@DB_COPY_LINE: + MOV CX, [BP].DB_PixCount ; Min # to copy + + TEST CL, 0FCh ; 16+PixWide? + JZ @DB_COPY_REMAINDER ; Nope... + + ; Pixel Copy loop has been unrolled to x4 + +@DB_COPY_LOOP: + MOVSB ; Copy Bitmap Pixel + ADD SI, 3 ; Skip to Next Byte in same plane + MOVSB ; Copy Bitmap Pixel + ADD SI, 3 ; Skip to Next Byte in same plane + MOVSB ; Copy Bitmap Pixel + ADD SI, 3 ; Skip to Next Byte in same plane + MOVSB ; Copy Bitmap Pixel + ADD SI, 3 ; Skip to Next Byte in same plane + + SUB CL, 4 ; Pixels to Copy=-4 + TEST CL, 0FCh ; 4+ Pixels Left? + JNZ @DB_COPY_LOOP ; if so, do another block + +@DB_COPY_REMAINDER: + JCXZ @DB_NEXT_LINE ; Any Pixels left on line + +@DB_COPY2: + MOVSB ; Copy Bitmap Pixel + ADD SI,3 ; Skip to Next Byte in same plane + LOOPx CX, @DB_COPY2 ; Pixels to Copy--, Loop until done + +@DB_NEXT_LINE: + + ; any Partial Pixels? (some planes only) + + OR CX, [BP].DB_SkewFlag ; Get Skew Count + JZ @DB_NEXT2 ; if no partial pixels + + MOVSB ; Copy Bitmap Pixel + DEC DI ; Back up to align + DEC SI ; Back up to align + +@DB_NEXT2: + ADD SI, [BP].DB_PixSkew ; Adjust Skew + ADD DI, [BP].DB_LineO ; Set to Next Display Line + LOOPx DX, @DB_COPY_LINE ; Lines to Copy--, Loop if more + + ; Copy Next Plane.... + + DEC BL ; Planes to Go-- + JZ @DB_Exit ; Hey! We are done + + ROL BH, 1 ; Next Plane in line... + OUT_8 SC_Data, BH ; Select Plane + + CMP AL, 12h ; Carry Set if AL=11h + ADC [BP].DB_Start, 0 ; Screen Addr =+Carry + INC w [BP].DB_Image ; Start @ Next Byte + + SUB [BP].DB_SkewFlag, 1 ; Reduce Planes to Skew + ADC [BP].DB_SkewFlag, 0 ; Back to 0 if it was -1 + + JMP s @DB_COPY_PLANE ; Go Copy the Next Plane + +@DB_Exit: + ADD SP, 10 ; Deallocate workspace + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + RET 12 ; Exit and Clean up Stack + +DRAW_BITMAP ENDP + + +;======================================================= +;TDRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%) +;======================================================= +; +; Transparently Draws a variable sized Graphics Bitmap +; such as a picture or an Icon on the current Display Page +; in Mode X. Pixels with a value of 0 are not drawn, +; leaving the previous "background" contents intact. +; +; The Bitmap format is the same as for the DRAW_BITMAP function. +; +; ENTRY: Image = Far Pointer to Bitmap Data +; Xpos = X position to Place Upper Left pixel at +; Ypos = Y position to Place Upper Left pixel at +; Width = Width of the Bitmap in Pixels +; Height = Height of the Bitmap in Pixels +; +; EXIT: No meaningful values returned +; + +TB_STACK STRUC + TB_LineO DW ? ; Offset to Next Line + TB_PixCount DW ? ; (Minimum) # of Pixels/Line + TB_Start DW ? ; Addr of Upper Left Pixel + TB_PixSkew DW ? ; # of bytes to Adjust EOL + TB_SkewFlag DW ? ; Extra Pix on Plane Flag + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DD ? ; Caller + TB_Height DW ? ; Height of Bitmap in Pixels + TB_Width DW ? ; Width of Bitmap in Pixels + TB_Ypos DW ? ; Y position to Draw Bitmap at + TB_Xpos DW ? ; X position to Draw Bitmap at + TB_Image DD ? ; Far Pointer to Graphics Bitmap +TB_STACK ENDS + + PUBLIC TDRAW_BITMAP + +TDRAW_BITMAP PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + SUB SP, 10 ; Allocate workspace + MOV BP, SP ; Set up Stack Frame + + LES DI, d CURRENT_PAGE ; Point to Active VGA Page + CLD ; Direction Flag = Forward + + MOV AX, [BP].TB_Ypos ; Get UL Corner Ypos + MUL SCREEN_WIDTH ; AX = Offset to Line Ypos + + MOV BX, [BP].TB_Xpos ; Get UL Corner Xpos + MOV CL, BL ; Save Plane # in CL + SHR BX, 1 ; Xpos/4 = Offset Into Line + SHR BX, 1 ; Xpos/4 = Offset Into Line + + ADD DI, AX ; ES:DI -> Start of Line + ADD DI, BX ; ES:DI -> Upper Left Pixel + MOV [BP].TB_Start, DI ; Save Starting Addr + + ; Compute line to line offset + + MOV BX, [BP].TB_Width ; Get Width of Image + MOV DX, BX ; Save Copy in DX + SHR BX, 1 ; /4 = width in bands + SHR BX, 1 ; /4 = width in bands + MOV AX, SCREEN_WIDTH ; Get Screen Width + SUB AX, BX ; - (Bitmap Width/4) + + MOV [BP].TB_LineO, AX ; Save Line Width offset + MOV [BP].TB_PixCount, BX ; Minimum # pix to copy + + AND DX, PLANE_BITS ; Get "partial band" size (0-3) + MOV [BP].TB_PixSkew, DX ; Also End of Line Skew + MOV [BP].TB_SkewFlag, DX ; Save as Flag/Count + + AND CX, PLANE_BITS ; CL = Starting Plane # + MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select + SHL AH, CL ; Select correct Plane + OUT_16 SC_Index, AX ; Select Plane... + MOV BH, AH ; BH = Saved Plane Mask + MOV BL, 4 ; BL = Planes to Copy + +@TB_COPY_PLANE: + + LDS SI, [BP].TB_Image ; DS:SI-> Source Image + MOV DX, [BP].TB_Height ; # of Lines to Copy + MOV DI, [BP].TB_Start ; ES:DI-> Dest pos + + ; Here AH is set with the value to be considered + ; "Transparent". It can be changed! + + MOV AH, 0 ; Value to Detect 0 + +@TB_COPY_LINE: + MOV CX, [BP].TB_PixCount ; Min # to copy + + TEST CL, 0FCh ; 16+PixWide? + JZ @TB_COPY_REMAINDER ; Nope... + + ; Pixel Copy loop has been unrolled to x4 + +@TB_COPY_LOOP: + LODSB ; Get Pixel Value in AL + ADD SI, 3 ; Skip to Next Byte in same plane + CMP AL, AH ; It is "Transparent"? + JE @TB_SKIP_01 ; Skip ahead if so + MOV ES:[DI], AL ; Copy Pixel to VGA screen + +@TB_SKIP_01: + LODSB ; Get Pixel Value in AL + ADD SI, 3 ; Skip to Next Byte in same plane + CMP AL, AH ; It is "Transparent"? + JE @TB_SKIP_02 ; Skip ahead if so + MOV ES:[DI+1], AL ; Copy Pixel to VGA screen + +@TB_SKIP_02: + LODSB ; Get Pixel Value in AL + ADD SI, 3 ; Skip to Next Byte in same plane + CMP AL, AH ; It is "Transparent"? + JE @TB_SKIP_03 ; Skip ahead if so + MOV ES:[DI+2], AL ; Copy Pixel to VGA screen + +@TB_SKIP_03: + LODSB ; Get Pixel Value in AL + ADD SI, 3 ; Skip to Next Byte in same plane + CMP AL, AH ; It is "Transparent"? + JE @TB_SKIP_04 ; Skip ahead if so + MOV ES:[DI+3], AL ; Copy Pixel to VGA screen + +@TB_SKIP_04: + ADD DI, 4 ; Adjust Pixel Write Location + SUB CL, 4 ; Pixels to Copy=-4 + TEST CL, 0FCh ; 4+ Pixels Left? + JNZ @TB_COPY_LOOP ; if so, do another block + +@TB_COPY_REMAINDER: + JCXZ @TB_NEXT_LINE ; Any Pixels left on line + +@TB_COPY2: + LODSB ; Get Pixel Value in AL + ADD SI, 3 ; Skip to Next Byte in same plane + CMP AL, AH ; It is "Transparent"? + JE @TB_SKIP_05 ; Skip ahead if so + MOV ES:[DI], AL ; Copy Pixel to VGA screen + +@TB_SKIP_05: + INC DI ; Advance Dest Addr + LOOPx CX, @TB_COPY2 ; Pixels to Copy--, Loop until done + +@TB_NEXT_LINE: + + ; any Partial Pixels? (some planes only) + + OR CX, [BP].TB_SkewFlag ; Get Skew Count + JZ @TB_NEXT2 ; if no partial pixels + + LODSB ; Get Pixel Value in AL + DEC SI ; Backup to Align + CMP AL, AH ; It is "Transparent"? + JE @TB_NEXT2 ; Skip ahead if so + MOV ES:[DI], AL ; Copy Pixel to VGA screen + +@TB_NEXT2: + ADD SI, [BP].TB_PixSkew ; Adjust Skew + ADD DI, [BP].TB_LineO ; Set to Next Display Line + LOOPx DX, @TB_COPY_LINE ; Lines to Copy--, Loop if More + + ;Copy Next Plane.... + + DEC BL ; Planes to Go-- + JZ @TB_Exit ; Hey! We are done + + ROL BH, 1 ; Next Plane in line... + OUT_8 SC_Data, BH ; Select Plane + + CMP AL, 12h ; Carry Set if AL=11h + ADC [BP].TB_Start, 0 ; Screen Addr =+Carry + INC w [BP].TB_Image ; Start @ Next Byte + + SUB [BP].TB_SkewFlag, 1 ; Reduce Planes to Skew + ADC [BP].TB_SkewFlag, 0 ; Back to 0 if it was -1 + + JMP @TB_COPY_PLANE ; Go Copy the next Plane + +@TB_Exit: + ADD SP, 10 ; Deallocate workspace + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + RET 12 ; Exit and Clean up Stack + +TDRAW_BITMAP ENDP + + + ; ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES ===== + +;================================== +;COPY_PAGE (SourcePage%, DestPage%) +;================================== +; +; Duplicate on display page onto another +; +; ENTRY: SourcePage = Display Page # to Duplicate +; DestPage = Display Page # to hold copy +; +; EXIT: No meaningful values returned +; + +CP_STACK STRUC + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DD ? ; Caller + CP_DestP DW ? ; Page to hold copied image + CP_SourceP DW ? ; Page to Make copy from +CP_STACK ENDS + + PUBLIC COPY_PAGE + +COPY_PAGE PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + MOV BP, SP ; Set up Stack Frame + CLD ; Block Xfer Forwards + + ; Make sure Page #'s are valid + + MOV AX, [BP].CP_SourceP ; Get Source Page # + CMP AX, LAST_PAGE ; is it > Max Page #? + JAE @CP_Exit ; if so, abort + + MOV BX, [BP].CP_DestP ; Get Destination Page # + CMP BX, LAST_PAGE ; is it > Max Page #? + JAE @CP_Exit ; if so, abort + + CMP AX, BX ; Pages #'s the same? + JE @CP_Exit ; if so, abort + + ; Setup DS:SI and ES:DI to Video Pages + + SHL BX, 1 ; Scale index to Word + MOV DI, PAGE_ADDR[BX] ; Offset to Dest Page + + MOV BX, AX ; Index to Source page + SHL BX, 1 ; Scale index to Word + MOV SI, PAGE_ADDR[BX] ; Offset to Source Page + + MOV CX, PAGE_SIZE ; Get size of Page + MOV AX, CURRENT_SEGMENT ; Get Video Mem Segment + MOV ES, AX ; ES:DI -> Dest Page + MOV DS, AX ; DS:SI -> Source Page + + ; Setup VGA registers for Mem to Mem copy + + OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on + OUT_16 SC_Index, ALL_PLANES_ON ; Copy all Planes + + ; Note.. Do *NOT* use MOVSW or MOVSD - they will + ; Screw with the latches which are 8 bits x 4 + + REP MOVSB ; Copy entire Page! + + ; Reset VGA for normal memory access + + OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = off + +@CP_Exit: + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + RET 4 ; Exit and Clean up Stack + +COPY_PAGE ENDP + + +;========================================================================== +;COPY_BITMAP (SourcePage%, X1%, Y1%, X2%, Y2%, DestPage%, DestX1%, DestY1%) +;========================================================================== +; +; Copies a Bitmap Image from one Display Page to Another +; This Routine is Limited to copying Images with the same +; Plane Alignment. To Work: (X1 MOD 4) must = (DestX1 MOD 4) +; Copying an Image to the Same Page is supported, but results +; may be defined when the when the rectangular areas +; (X1, Y1) - (X2, Y2) and (DestX1, DestY1) - +; (DestX1+(X2-X1), DestY1+(Y2-Y1)) overlap... +; No Paramter checking to done to insure that +; X2 >= X1 and Y2 >= Y1. Be Careful... +; +; ENTRY: SourcePage = Display Page # with Source Image +; X1 = Upper Left Xpos of Source Image +; Y1 = Upper Left Ypos of Source Image +; X2 = Lower Right Xpos of Source Image +; Y2 = Lower Right Ypos of Source Image +; DestPage = Display Page # to copy Image to +; DestX1 = Xpos to Copy UL Corner of Image to +; DestY1 = Ypos to Copy UL Corner of Image to +; +; EXIT: AX = Success Flag: 0 = Failure / -1= Success +; + +CB_STACK STRUC + CB_Height DW ? ; Height of Image in Lines + CB_Width DW ? ; Width of Image in "bands" + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DD ? ; Caller + CB_DestY1 DW ? ; Destination Ypos + CB_DestX1 DW ? ; Destination Xpos + CB_DestP DW ? ; Page to Copy Bitmap To + CB_Y2 DW ? ; LR Ypos of Image + CB_X2 DW ? ; LR Xpos of Image + CB_Y1 DW ? ; UL Ypos of Image + CB_X1 DW ? ; UL Xpos of Image + CB_SourceP DW ? ; Page containing Source Bitmap +CB_STACK ENDS + + PUBLIC COPY_BITMAP + +COPY_BITMAP PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + SUB SP, 4 ; Allocate WorkSpace on Stack + MOV BP, SP ; Set up Stack Frame + + ; Prep Registers (and keep jumps short!) + + MOV ES, CURRENT_SEGMENT ; ES -> VGA Ram + CLD ; Block Xfer Forwards + + ; Make sure Parameters are valid + + MOV BX, [BP].CB_SourceP ; Get Source Page # + CMP BX, LAST_PAGE ; is it > Max Page #? + JAE @CB_Abort ; if so, abort + + MOV CX, [BP].CB_DestP ; Get Destination Page # + CMP CX, LAST_PAGE ; is it > Max Page #? + JAE @CB_Abort ; if so, abort + + MOV AX, [BP].CB_X1 ; Get Source X1 + XOR AX, [BP].CB_DestX1 ; Compare Bits 0-1 + AND AX, PLANE_BITS ; Check Plane Bits + JNZ @CB_Abort ; They should cancel out + + ; Setup for Copy processing + + OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select + OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on + + ; Compute Info About Images, Setup ES:SI & ES:DI + + MOV AX, [BP].CB_Y2 ; Height of Bitmap in lines + SUB AX, [BP].CB_Y1 ; is Y2 - Y1 + 1 + INC AX ; (add 1 since were not 0 based) + MOV [BP].CB_Height, AX ; Save on Stack for later use + + MOV AX, [BP].CB_X2 ; Get # of "Bands" of 4 Pixels + MOV DX, [BP].CB_X1 ; the Bitmap Occupies as X2-X1 + SHR AX, 1 ; Get X2 Band (X2 / 4) + SHR DX, 1 ; Get X1 Band (X1 / 4) + SHR AX, 1 ; Get X2 Band (X2 / 4) + SHR DX, 1 ; Get X1 Band (X1 / 4) + SUB AX, DX ; AX = # of Bands - 1 + INC AX ; AX = # of Bands + MOV [BP].CB_Width, AX ; Save on Stack for later use + + SHL BX, 1 ; Scale Source Page to Word + MOV SI, PAGE_ADDR[BX] ; SI = Offset of Source Page + MOV AX, [BP].CB_Y1 ; Get Source Y1 Line + MUL SCREEN_WIDTH ; AX = Offset to Line Y1 + ADD SI, AX ; SI = Offset to Line Y1 + MOV AX, [BP].CB_X1 ; Get Source X1 + SHR AX, 1 ; X1 / 4 = Byte offset + SHR AX, 1 ; X1 / 4 = Byte offset + ADD SI, AX ; SI = Byte Offset to (X1,Y1) + + MOV BX, CX ; Dest Page Index to BX + SHL BX, 1 ; Scale Source Page to Word + MOV DI, PAGE_ADDR[BX] ; DI = Offset of Dest Page + MOV AX, [BP].CB_DestY1 ; Get Dest Y1 Line + MUL SCREEN_WIDTH ; AX = Offset to Line Y1 + ADD DI, AX ; DI = Offset to Line Y1 + MOV AX, [BP].CB_DestX1 ; Get Dest X1 + SHR AX, 1 ; X1 / 4 = Byte offset + SHR AX, 1 ; X1 / 4 = Byte offset + ADD DI, AX ; DI = Byte Offset to (D-X1,D-Y1) + + MOV CX, [BP].CB_Width ; CX = Width of Image (Bands) + DEC CX ; CX = 1? + JE @CB_Only_One_Band ; 0 Means Image Width of 1 Band + + MOV BX, [BP].CB_X1 ; Get Source X1 + AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 00?) + JZ @CB_Check_Right ; if so, check right alignment + JNZ @CB_Left_Band ; not aligned? well.. + +@CB_Abort: + mov ax,0 ; Return False (Failure) + JMP @CB_Exit ; and Finish Up + + ; Copy when Left & Right Clip Masks overlap... + +@CB_Only_One_Band: + MOV BX, [BP].CB_X1 ; Get Left Clip Mask + AND BX, PLANE_BITS ; Mask out Row # + MOV AL, Left_Clip_Mask[BX] ; Get Left Edge Mask + MOV BX, [BP].CB_X2 ; Get Right Clip Mask + AND BX, PLANE_BITS ; Mask out Row # + AND AL, Right_Clip_Mask[BX] ; Get Right Edge Mask byte + + OUT_8 SC_Data, AL ; Clip For Left & Right Masks + + MOV CX, [BP].CB_Height ; CX = # of Lines to Copy + MOV DX, SCREEN_WIDTH ; DX = Width of Screen + mov bx,0 ; BX = Offset into Image + +@CB_One_Loop: + MOV AL, ES:[SI+BX] ; Load Latches + MOV ES:[DI+BX], AL ; Unload Latches + ADD BX, DX ; Advance Offset to Next Line + LOOPjz CX, @CB_One_Done ; Exit Loop if Finished + + MOV AL, ES:[SI+BX] ; Load Latches + MOV ES:[DI+BX], AL ; Unload Latches + ADD BX, DX ; Advance Offset to Next Line + LOOPx CX, @CB_One_Loop ; Loop until Finished + +@CB_One_Done: + JMP @CB_Finish ; Outa Here! + + ; Copy Left Edge of Bitmap + +@CB_Left_Band: + + OUT_8 SC_Data, Left_Clip_Mask[BX] ; Set Left Edge Plane Mask + + MOV CX, [BP].CB_Height ; CX = # of Lines to Copy + MOV DX, SCREEN_WIDTH ; DX = Width of Screen + mov bx,0 ; BX = Offset into Image + +@CB_Left_Loop: + MOV AL, ES:[SI+BX] ; Load Latches + MOV ES:[DI+BX], AL ; Unload Latches + ADD BX, DX ; Advance Offset to Next Line + LOOPjz CX, @CB_Left_Done ; Exit Loop if Finished + + MOV AL, ES:[SI+BX] ; Load Latches + MOV ES:[DI+BX], AL ; Unload Latches + ADD BX, DX ; Advance Offset to Next Line + LOOPx CX, @CB_Left_Loop ; Loop until Finished + +@CB_Left_Done: + INC DI ; Move Dest Over 1 band + INC SI ; Move Source Over 1 band + DEC [BP].CB_Width ; Band Width-- + + ; Determine if Right Edge of Bitmap needs special copy + +@CB_Check_Right: + MOV BX, [BP].CB_X2 ; Get Source X2 + AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 11?) + CMP BL, 03h ; Plane = 3? + JE @CB_Copy_Middle ; Copy the Middle then! + + ; Copy Right Edge of Bitmap + +@CB_Right_Band: + + OUT_8 SC_Data, Right_Clip_Mask[BX] ; Set Right Edge Plane Mask + + DEC [BP].CB_Width ; Band Width-- + MOV CX, [BP].CB_Height ; CX = # of Lines to Copy + MOV DX, SCREEN_WIDTH ; DX = Width of Screen + MOV BX, [BP].CB_Width ; BX = Offset to Right Edge + +@CB_Right_Loop: + MOV AL, ES:[SI+BX] ; Load Latches + MOV ES:[DI+BX], AL ; Unload Latches + ADD BX, DX ; Advance Offset to Next Line + LOOPjz CX, @CB_Right_Done ; Exit Loop if Finished + + MOV AL, ES:[SI+BX] ; Load Latches + MOV ES:[DI+BX], AL ; Unload Latches + ADD BX, DX ; Advance Offset to Next Line + LOOPx CX, @CB_Right_Loop ; Loop until Finished + +@CB_Right_Done: + + ; Copy the Main Block of the Bitmap + +@CB_Copy_Middle: + + MOV CX, [BP].CB_Width ; Get Width Remaining + JCXZ @CB_Finish ; Exit if Done + + OUT_8 SC_Data, ALL_PLANES ; Copy all Planes + + MOV DX, SCREEN_WIDTH ; Get Width of Screen minus + SUB DX, CX ; Image width (for Adjustment) + MOV AX, [BP].CB_Height ; AX = # of Lines to Copy + MOV BX, CX ; BX = Quick REP reload count + MOV CX, ES ; Move VGA Segment + MOV DS, CX ; Into DS + + ; Actual Copy Loop. REP MOVSB does the work + +@CB_Middle_Copy: + MOV CX, BX ; Recharge Rep Count + REP MOVSB ; Move Bands + LOOPjz AX, @CB_Finish ; Exit Loop if Finished + + ADD SI, DX ; Adjust DS:SI to Next Line + ADD DI, DX ; Adjust ES:DI to Next Line + + MOV CX, BX ; Recharge Rep Count + REP MOVSB ; Move Bands + + ADD SI, DX ; Adjust DS:SI to Next Line + ADD DI, DX ; Adjust ES:DI to Next Line + LOOPx AX, @CB_Middle_Copy ; Copy Lines until Done + +@CB_Finish: + OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = on + +@CB_Exit: + ADD SP, 04 ; Deallocate stack workspace + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + RET 16 ; Exit and Clean up Stack + +COPY_BITMAP ENDP + + END ; End of Code Segment diff --git a/src/lib/modex/modex.bi b/src/lib/modex/modex.bi new file mode 100755 index 00000000..6b1d7afe --- /dev/null +++ b/src/lib/modex/modex.bi @@ -0,0 +1,63 @@ + + ' ===== SCREEN RESOLUTIONS ===== + +CONST Mode320x200 = 0, Mode320x400 = 1 +CONST Mode360x200 = 2, Mode360x400 = 3 +CONST Mode320x240 = 4, Mode320x480 = 5 +CONST Mode360x240 = 6, Mode360x480 = 7 + + ' ===== MODE X SETUP ROUTINES ===== + +DECLARE FUNCTION SET.VGA.MODEX% ALIAS "SET_VGA_MODEX" (BYVAL ModeType%, BYVAL MaxXpos%, BYVAL MaxYpos%, BYVAL Pages%) +DECLARE FUNCTION SET.MODEX% ALIAS "SET_MODEX" (BYVAL Mode%) + + ' ===== BASIC GRAPHICS PRIMITIVES ===== + +DECLARE SUB CLEAR.VGA.SCREEN ALIAS "CLEAR_VGA_SCREEN" (BYVAL ColorNum%) +DECLARE SUB SET.POINT ALIAS "SET_POINT" (BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorNum%) +DECLARE FUNCTION READ.POINT% ALIAS "READ_POINT" (BYVAL Xpos%, BYVAL Ypos%) +DECLARE SUB FILL.BLOCK ALIAS "FILL_BLOCK" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%) +DECLARE SUB DRAW.LINE ALIAS "DRAW_LINE" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%) + + ' ===== DAC COLOR REGISTER ROUTINES ===== + +DECLARE SUB SET.DAC.REGISTER ALIAS "SET_DAC_REGISTER" (BYVAL RegNo%, BYVAL Red%, BYVAL Green%, BYVAL Blue%) +DECLARE SUB GET.DAC.REGISTER ALIAS "GET_DAC_REGISTER" (BYVAL RegNo%, Red%, Green%, Blue%) +DECLARE SUB LOAD.DAC.REGISTERS ALIAS "LOAD_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%, BYVAL VSync%) +DECLARE SUB READ.DAC.REGISTERS ALIAS "READ_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%) + + + ' ===== PAGE FLIPPING AND SCROLLING ROUTINES ===== + +DECLARE SUB SET.ACTIVE.PAGE ALIAS "SET_ACTIVE_PAGE" (BYVAL PageNo%) +DECLARE FUNCTION GET.ACTIVE.PAGE% ALIAS "GET_ACTIVE_PAGE" +DECLARE SUB SET.DISPLAY.PAGE ALIAS "SET_DISPLAY_PAGE" (BYVAL PageNo%) +DECLARE FUNCTION GET.DISPLAY.PAGE% ALIAS "GET_DISPLAY_PAGE" +DECLARE SUB SET.WINDOW ALIAS "SET_WINDOW" (BYVAL DisplayPage%, BYVAL XOffset%, BYVAL YOffset%) +DECLARE FUNCTION GET.X.OFFSET% ALIAS "GET_X_OFFSET" () +DECLARE FUNCTION GET.Y.OFFSET% ALIAS "GET_Y_OFFSET" () +DECLARE SUB SYNC.DISPLAY ALIAS "SYNC_DISPLAY" + + ' ===== TEXT DISPLAY ROUTINES ===== + +DECLARE SUB GPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%) +DECLARE SUB TGPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%) +DECLARE SUB PRINT.STR ALIAS "PRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%) +DECLARE SUB TPRINT.STR ALIAS "TPRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%) +DECLARE SUB SET.DISPLAY.FONT ALIAS "SET_DISPLAY_FONT" (SEG FontData AS ANY, BYVAL FontNumber%) + + ' ===== BITMAP (SPRITE) DISPLAY ROUTINES ===== + +DECLARE SUB DRAW.BITMAP ALIAS "DRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%) +DECLARE SUB TDRAW.BITMAP ALIAS "TDRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%) + + ' ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES ===== + +DECLARE SUB COPY.PAGE ALIAS "COPY_PAGE" (BYVAL SourcePage%, BYVAL DestPage%) +DECLARE SUB COPY.BITMAP ALIAS "COPY_BITMAP" (BYVAL SourcePage%, BYVAL X1%, BYVAL Y1%, BYVAL X2%, BYVAL Y2%, BYVAL DestPage%, BYVAL DestX1%, BYVAL DestY1%) + + + + + + diff --git a/src/lib/modex/modex.h b/src/lib/modex/modex.h new file mode 100755 index 00000000..1381abb6 --- /dev/null +++ b/src/lib/modex/modex.h @@ -0,0 +1,76 @@ + +#ifndef __MODEX_H +#define __MODEX_H + + /* ===== SCREEN RESOLUTIONS ===== */ + +#define Mode_320x200 0 +#define Mode_320x400 1 +#define Mode_360x200 2 +#define Mode_360x400 3 +#define Mode_320x240 4 +#define Mode_320x480 5 +#define Mode_360x240 6 +#define Mode_360x480 7 + + /* ===== MODE X SETUP ROUTINES ===== */ + +int far pascal set_vga_modex (int Mode, int MaxXpos, int MaxYpos, int Pages); +int far pascal set_modex (int Mode); + + /* ===== BASIC GRAPHICS PRIMITIVES ===== */ + +void far pascal clear_vga_screen (int Color); +void far pascal set_point (int Xpos, int Ypos, int Color); +int far pascal read_point (int Xpos, int Ypos); +void far pascal fill_block (int Xpos1, int Ypos1, int Xpos2, int Ypos2, + int Color); +void far pascal draw_line (int Xpos1, int Ypos1, int Xpos2, int Ypos2, + int Color); + + /* ===== DAC COLOR REGISTER ROUTINES ===== */ + +void far pascal set_dac_register (int RegNo, int Red, int Green, int Blue); +void far pascal get_dac_register (int RegNo, int* Red, int* Green, int* Blue); +void far pascal load_dac_registers (char far *PalData, int StartReg, + int EndReg, int VSync); +void far pascal readd_dac_registers (char far *PalData, int StartReg, + int EndReg); + + /* ===== PAGE FLIPPING AND SCROLLING ROUTINES ===== */ + +void far pascal set_active_page (int PageNo); +int far pascal get_active_page (void); +void far pascal set_display_page (int PageNo); +int far pascal get_display_page (void); +void far pascal set_window (int DisplayPage, int XOffset, int YOffset); +int far pascal get_x_offset (void); +int far pascal get_y_offset (void); +void far pascal sync_display (void); + + /* ===== TEXT DISPLAY ROUTINES ===== */ + +void far pascal gprintc (int CharNum, int Xpos, int Ypos, int ColorF, + int ColorB); +void far pascal tgprintc (int CharNum, int Xpos, int Ypos, int ColorF); +void far pascal print_str (char far *Text, int MaxLen, int Xpos, int Ypos, + int ColorF, int ColorB); +void far pascal tprint_str (char far *Text, int MaxLen, int Xpos, int Ypos, + int ColorF); +void far pascal set_display_font (char far *FontData, int FontNumber); + + /* ===== BITMAP (SPRITE) DISPLAY ROUTINES ===== */ + +void far pascal draw_bitmap (char far *Image, int Xpos, int Ypos, + int Width, int Height); +void far pascal tdraw_bitmap (char far *Image, int Xpos, int Ypos, + int Width, int Height); + + /* ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES ===== */ + +void far pascal copy_page (int SourcePage, int DestPage); +void far pascal copy_bitmap (int SourcePage, int X1, int Y1, int X2, int Y2, + int DestPage, int DestX1, int DestY1); + + +#endif diff --git a/src/lib/modex/modex.lst b/src/lib/modex/modex.lst new file mode 100755 index 00000000..ce6d955c --- /dev/null +++ b/src/lib/modex/modex.lst @@ -0,0 +1,4122 @@ +Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 +modex.asm Page 1 - 1 + + + ;======================================================== + ; MODEX.ASM - A Complete Mode X Library + ; + ; Version 1.04 Release, 3 May 1993, By Matt Pritchard + ; With considerable input from Michael Abrash + ; + ; The following information is donated to the public domain in + ; the hopes that save other programmers much frustration. + ; + ; If you do use this code in a product, it would be nice if + ; you include a line like "Mode X routines by Matt Pritchard" + ; in the credits. + ; + ; ========================================================= + ; + ; All of this code is designed to be assembled with MASM 5.10a + ; but TASM 3.0 could be used as well. + ; + ; The routines contained are designed for use in a MEDIUM model + ; program. All Routines are FAR, and is assumed that a DGROUP + ; data segment exists and that DS will point to it on entry. + ; + ; For all routines, the AX, BX, CX, DX, ES and FLAGS registers + ; will not be preserved, while the DS, BP, SI and DI registers + ; will be preserved. + ; + ; Unless specifically noted, All Parameters are assumed to be + ; "PASSED BY VALUE". That is, the actual value is placed on + ; the stack. When a reference is passed it is assumed to be + ; a near pointer to a variable in the DGROUP segment. + ; + ; Routines that return a single 16-Bit integer value will + ; return that value in the AX register. + ; + ; This code will *NOT* run on an 8086/8088 because 80286+ + ; specific instructions are used. If you have an 8088/86 + ; and VGA, you can buy an 80386-40 motherboard for about + ; $160 and move into the 90's. + ; + ; This code is reasonably optimized: Most drawing loops have + ; been unrolled once and memory references are minimized by + ; keeping stuff in registers when possible. + ; + ; Error Trapping varies by Routine. No Clipping is performed + ; so the caller should verify that all coordinates are valid. + ; + ; Several Macros are used to simplify common 2 or 3 instruction + ; sequences. Several Single letter Text Constants also + ; simplify common assembler expressions like "WORD PTR". + ; + ; ------------------ Mode X Variations ------------------ + ; + ; Mode # Screen Size Max Pages Aspect Ratio (X:Y) + ; + ; 0 320 x 200 4 Pages 1.2:1 + ; 1 320 x 400 2 Pages 2.4:1 + ; 2 360 x 200 3 Pages 1.35:1 + ; 3 360 x 400 1 Page 2.7:1 + ; 4 320 x 240 3 Pages 1:1 + ; 5 320 x 480 1 Page 2:1 + ; 6 360 x 240 3 Pages 1.125:1 + ; 7 360 x 480 1 Page 2.25:1 + ; + ; -------------------- The Legal Stuff ------------------ + ; + ; No warranty, either written or implied, is made as to + ; the accuracy and usability of this code product. Use + ; at your own risk. Batteries not included. Pepperoni + ; and extra cheese available for an additional charge. + ; + ; ----------------------- The Author -------------------- + ; + ; Matt Pritchard is a paid programmer who'd rather be + ; writing games. He can be reached at: P.O. Box 140264, + ; Irving, TX 75014 USA. Michael Abrash is a living + ; god, who now works for Bill Gates (Microsoft). + ; + ; -------------------- Revision History ----------------- + ; 4-12-93: v1.02 - SET_POINT & READ_POINT now saves DI + ; SET_MODEX now saves SI + ; 5-3-93: v1.04 - added LOAD_DAC_REGISTERS and + ; READ_DAC_REGISTERS. Expanded CLR Macro + ; to handle multiple registers + ; + + PAGE 255, 132 + + .MODEL Medium + .286 + + ; ===== MACROS ===== + + ; Macro to OUT a 16 bit value to an I/O port + + OUT_16 MACRO Register, Value + IFDIFI , ; If DX not setup + MOV DX, Register ; then Select Register + ENDIF + IFDIFI , ; If AX not setup + MOV AX, Value ; then Get Data Value + ENDIF + OUT DX, AX ; Set I/O Register(s) + ENDM + + ; Macro to OUT a 8 bit value to an I/O Port + + OUT_8 MACRO Register, Value + IFDIFI , ; If DX not setup + MOV DX, Register ; then Select Register + ENDIF + IFDIFI , ; If AL not Setup + MOV AL, Value ; then Get Data Value + ENDIF + OUT DX, AL ; Set I/O Register + ENDM + + ; macros to PUSH and POP multiple registers + + PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8 + IFNB + PUSH R1 ; Save R1 + PUSHx R2, R3, R4, R5, R6, R7, R8 + ENDIF + ENDM + + POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8 + IFNB + POP R1 ; Restore R1 + POPx R2, R3, R4, R5, R6, R7, R8 + ENDIF + ENDM + + ; Macro to Clear Registers to 0 + + CLR MACRO Register, R2, R3, R4, R5, R6 + IFNB + XOR Register, Register ; Set Register = 0 + CLR R2, R3, R4, R5, R6 + ENDIF + ENDM + + ; Macros to Decrement Counter & Jump on Condition + + LOOPx MACRO Register, Destination + DEC Register ; Counter-- + JNZ Destination ; Jump if not 0 + ENDM + + LOOPjz MACRO Register, Destination + DEC Register ; Counter-- + JZ Destination ; Jump if 0 + ENDM + + + ; ===== General Constants ===== + + = 0000 False EQU 0 + =-0001 True EQU -1 + = 0000 nil EQU 0 + + = BYTE PTR b EQU BYTE PTR + = WORD PTR w EQU WORD PTR + = DWORD PTR d EQU DWORD PTR + = OFFSET o EQU OFFSET + = FAR PTR f EQU FAR PTR + = SHORT s EQU SHORT + = ?,?,?,? ?x4 EQU + = ?,?,? ?x3 EQU + + ; ===== VGA Register Values ===== + + = A000 VGA_Segment EQU 0A000h ; Vga Memory Segment + + = 03C0 ATTRIB_Ctrl EQU 03C0h ; VGA Attribute Controller + = 03CE GC_Index EQU 03CEh ; VGA Graphics Controller + = 03C4 SC_Index EQU 03C4h ; VGA Sequencer Controller + = 03C5 SC_Data EQU 03C5h ; VGA Sequencer Data Port + = 03D4 CRTC_Index EQU 03D4h ; VGA CRT Controller + = 03D5 CRTC_Data EQU 03D5h ; VGA CRT Controller Data + = 03C2 MISC_OUTPUT EQU 03C2h ; VGA Misc Register + = 03DA INPUT_1 EQU 03DAh ; Input Status #1 Register + + = 03C8 DAC_WRITE_ADDR EQU 03C8h ; VGA DAC Write Addr Register + = 03C7 DAC_READ_ADDR EQU 03C7h ; VGA DAC Read Addr Register + = 03C9 PEL_DATA_REG EQU 03C9h ; VGA DAC/PEL data Register R/W + + = 0033 PIXEL_PAN_REG EQU 033h ; Attrib Index: Pixel Pan Reg + = 0002 MAP_MASK EQU 002h ; Sequ Index: Write Map Mask reg + = 0004 READ_MAP EQU 004h ; GC Index: Read Map Register + = 000C START_DISP_HI EQU 00Ch ; CRTC Index: Display Start Hi + = 000D START_DISP_LO EQU 00Dh ; CRTC Index: Display Start Lo + + = 0102 MAP_MASK_PLANE1 EQU 00102h ; Map Register + Plane 1 + = 1102 MAP_MASK_PLANE2 EQU 01102h ; Map Register + Plane 1 + = 0F02 ALL_PLANES_ON EQU 00F02h ; Map Register + All Bit Planes + + = 0604 CHAIN4_OFF EQU 00604h ; Chain 4 mode Off + = 0100 ASYNC_RESET EQU 00100h ; (A)synchronous Reset + = 0300 SEQU_RESTART EQU 00300h ; Sequencer Restart + + = 0008 LATCHES_ON EQU 00008h ; Bit Mask + Data from Latches + = FF08 LATCHES_OFF EQU 0FF08h ; Bit Mask + Data from CPU + + = 0008 VERT_RETRACE EQU 08h ; INPUT_1: Vertical Retrace Bit + = 0003 PLANE_BITS EQU 03h ; Bits 0-1 of Xpos = Plane # + = 000F ALL_PLANES EQU 0Fh ; All Bit Planes Selected + = 000F CHAR_BITS EQU 0Fh ; Bits 0-3 of Character Data + + = 1130 GET_CHAR_PTR EQU 01130h ; VGA BIOS Func: Get Char Set + = 0003 ROM_8x8_Lo EQU 03h ; ROM 8x8 Char Set Lo Pointer + = 0004 ROM_8x8_Hi EQU 04h ; ROM 8x8 Char Set Hi Pointer + + ; Constants Specific for these routines + + = 0008 NUM_MODES EQU 8 ; # of Mode X Variations + + ; Specific Mode Data Table format... + + 000C Mode_Data_Table STRUC + 0000 00 M_MiscR DB ? ; Value of MISC_OUTPUT register + 0001 00 M_Pages DB ? ; Maximum Possible # of pages + 0002 0000 M_XSize DW ? ; X Size Displayed on screen + 0004 0000 M_YSize DW ? ; Y Size Displayed on screen + 0006 0000 M_XMax DW ? ; Maximum Possible X Size + 0008 0000 M_YMax DW ? ; Maximum Possible Y Size + 000A 0000 M_CRTC DW ? ; Table of CRTC register values + Mode_Data_Table ENDS + + ; ===== DGROUP STORAGE NEEDED (42 BYTES) ===== + + 0000 .DATA? + + 0000 0000 SCREEN_WIDTH DW 0 ; Width of a line in Bytes + 0002 0000 SCREEN_HEIGHT DW 0 ; Vertical Height in Pixels + + 0004 0000 LAST_PAGE DW 0 ; # of Display Pages + 0006 0004 [ PAGE_ADDR DW 4 DUP (0) ; Offsets to start of each page + 0000 + ] + + 000E 0000 PAGE_SIZE DW 0 ; Size of Page in Addr Bytes + + 0010 0000 DISPLAY_PAGE DW 0 ; Page # currently displayed + 0012 0000 ACTIVE_PAGE DW 0 ; Page # currently active + + 0014 0000 CURRENT_PAGE DW 0 ; Offset of current Page + 0016 0000 CURRENT_SEGMENT DW 0 ; Segment of VGA memory + + 0018 0000 CURRENT_XOFFSET DW 0 ; Current Display X Offset + 001A 0000 CURRENT_YOFFSET DW 0 ; Current Display Y Offset + + 001C 0000 CURRENT_MOFFSET DW 0 ; Current Start Offset + + 001E 0000 MAX_XOFFSET DW 0 ; Current Display X Offset + 0020 0000 MAX_YOFFSET DW 0 ; Current Display Y Offset + + 0022 0000 0000 CHARSET_LOW DW 0, 0 ; Far Ptr to Char Set: 0-127 + 0026 0000 0000 CHARSET_HI DW 0, 0 ; Far Ptr to Char Set: 128-255 + + 0000 .CODE + + ; ===== DATA TABLES ===== + + ; Data Tables, Put in Code Segment for Easy Access + ; (Like when all the other Segment Registers are in + ; use!!) and reduced DGROUP requirements... + + ; Bit Mask Tables for Left/Right/Character Masks + + 0000 0F 0E 0C 08 Left_Clip_Mask DB 0FH, 0EH, 0CH, 08H + + 0004 01 03 07 0F Right_Clip_Mask DB 01H, 03H, 07H, 0FH + + ; Bit Patterns for converting character fonts + + 0008 00 08 04 0C 02 0A Char_Plane_Data DB 00H,08H,04H,0CH,02H,0AH,06H,0EH + 06 0E + 0010 01 09 05 0D 03 0B DB 01H,09H,05H,0DH,03H,0BH,07H,0FH + 07 0F + + ; CRTC Register Values for Various Configurations + + 0018 MODE_Single_Line: ; CRTC Setup Data for 400/480 Line modes + 0018 4009 DW 04009H ; Cell Height (1 Scan Line) + 001A 0014 DW 00014H ; Dword Mode off + 001C E317 DW 0E317H ; turn on Byte Mode + 001E 0000 DW nil ; End of CRTC Data for 400/480 Line Mode + + 0020 MODE_Double_Line: ; CRTC Setup Data for 200/240 Line modes + 0020 4109 DW 04109H ; Cell Height (2 Scan Lines) + 0022 0014 DW 00014H ; Dword Mode off + 0024 E317 DW 0E317H ; turn on Byte Mode + 0026 0000 DW nil ; End of CRTC Data for 200/240 Line Mode + + 0028 MODE_320_Wide: ; CRTC Setup Data for 320 Horz Pixels + 0028 5F00 DW 05F00H ; Horz total + 002A 4F01 DW 04F01H ; Horz Displayed + 002C 5002 DW 05002H ; Start Horz Blanking + 002E 8203 DW 08203H ; End Horz Blanking + 0030 5404 DW 05404H ; Start H Sync + 0032 8005 DW 08005H ; End H Sync + 0034 0000 DW nil ; End of CRTC Data for 320 Horz pixels + + 0036 MODE_360_Wide: ; CRTC Setup Data for 360 Horz Pixels + 0036 6B00 DW 06B00H ; Horz total + 0038 5901 DW 05901H ; Horz Displayed + 003A 5A02 DW 05A02H ; Start Horz Blanking + 003C 8E03 DW 08E03H ; End Horz Blanking + 003E 5E04 DW 05E04H ; Start H Sync + 0040 8A05 DW 08A05H ; End H Sync + 0042 0000 DW nil ; End of CRTC Data for 360 Horz pixels + + 0044 MODE_200_Tall: + 0044 MODE_400_Tall: ; CRTC Setup Data for 200/400 Line modes + 0044 BF06 DW 0BF06H ; Vertical Total + 0046 1F07 DW 01F07H ; Overflow + 0048 9C10 DW 09C10H ; V Sync Start + 004A 8E11 DW 08E11H ; V Sync End/Prot Cr0 Cr7 + 004C 8F12 DW 08F12H ; Vertical Displayed + 004E 9615 DW 09615H ; V Blank Start + 0050 B916 DW 0B916H ; V Blank End + 0052 0000 DW nil ; End of CRTC Data for 200/400 Lines + + 0054 MODE_240_Tall: + 0054 MODE_480_Tall: ; CRTC Setup Data for 240/480 Line modes + 0054 0D06 DW 00D06H ; Vertical Total + 0056 3E07 DW 03E07H ; Overflow + 0058 EA10 DW 0EA10H ; V Sync Start + 005A 8C11 DW 08C11H ; V Sync End/Prot Cr0 Cr7 + 005C DF12 DW 0DF12H ; Vertical Displayed + 005E E715 DW 0E715H ; V Blank Start + 0060 0616 DW 00616H ; V Blank End + 0062 0000 DW nil ; End of CRTC Data for 240/480 Lines + + ; Table of Display Mode Tables + + 0064 MODE_TABLE: + 0064 0074 R 0086 R DW o MODE_320x200, o MODE_320x400 + 0068 00E0 R 00F2 R DW o MODE_360x200, o MODE_360x400 + 006C 00BC R 00CE R DW o MODE_320x240, o MODE_320x480 + Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 +modex.asm Page 2 - 1 + + + 0070 0098 R 00AA R DW o MODE_360x240, o MODE_360x480 + + ; Table of Display Mode Components + + 0074 MODE_320x200: ; Data for 320 by 200 Pixels + + 0074 63 DB 063h ; 400 scan Lines & 25 Mhz Clock + 0075 04 DB 4 ; Maximum of 4 Pages + 0076 0140 00C8 DW 320, 200 ; Displayed Pixels (X,Y) + 007A 0516 0330 DW 1302, 816 ; Max Possible X and Y Sizes + + 007E 0028 R 0044 R DW o MODE_320_Wide, o MODE_200_Tall + 0082 0020 R 0000 DW o MODE_Double_Line, nil + + 0086 MODE_320x400: ; Data for 320 by 400 Pixels + + 0086 63 DB 063h ; 400 scan Lines & 25 Mhz Clock + 0087 02 DB 2 ; Maximum of 2 Pages + 0088 0140 0190 DW 320, 400 ; Displayed Pixels X,Y + 008C 0288 0330 DW 648, 816 ; Max Possible X and Y Sizes + + 0090 0028 R 0044 R DW o MODE_320_Wide, o MODE_400_Tall + 0094 0018 R 0000 DW o MODE_Single_Line, nil + + 0098 MODE_360x240: ; Data for 360 by 240 Pixels + + 0098 E7 DB 0E7h ; 480 scan Lines & 28 Mhz Clock + 0099 03 DB 3 ; Maximum of 3 Pages + 009A 0168 00F0 DW 360, 240 ; Displayed Pixels X,Y + 009E 0444 02D8 DW 1092, 728 ; Max Possible X and Y Sizes + + 00A2 0036 R 0054 R DW o MODE_360_Wide, o MODE_240_Tall + 00A6 0020 R 0000 DW o MODE_Double_Line , nil + + 00AA MODE_360x480: ; Data for 360 by 480 Pixels + + 00AA E7 DB 0E7h ; 480 scan Lines & 28 Mhz Clock + 00AB 01 DB 1 ; Only 1 Page Possible + 00AC 0168 01E0 DW 360, 480 ; Displayed Pixels X,Y + 00B0 0220 02D8 DW 544, 728 ; Max Possible X and Y Sizes + + 00B4 0036 R 0054 R DW o MODE_360_Wide, o MODE_480_Tall + 00B8 0018 R 0000 DW o MODE_Single_Line , nil + + 00BC MODE_320x240: ; Data for 320 by 240 Pixels + + 00BC E3 DB 0E3h ; 480 scan Lines & 25 Mhz Clock + 00BD 03 DB 3 ; Maximum of 3 Pages + 00BE 0140 00F0 DW 320, 240 ; Displayed Pixels X,Y + 00C2 0440 0332 DW 1088, 818 ; Max Possible X and Y Sizes + + 00C6 0028 R 0054 R DW o MODE_320_Wide, o MODE_240_Tall + 00CA 0020 R 0000 DW o MODE_Double_Line, nil + + 00CE MODE_320x480: ; Data for 320 by 480 Pixels + + 00CE E3 DB 0E3h ; 480 scan Lines & 25 Mhz Clock + 00CF 01 DB 1 ; Only 1 Page Possible + 00D0 0140 01E0 DW 320, 480 ; Displayed Pixels X,Y + 00D4 021C 0332 DW 540, 818 ; Max Possible X and Y Sizes + + 00D8 0028 R 0054 R DW o MODE_320_WIDE, o MODE_480_Tall + 00DC 0018 R 0000 DW o MODE_Single_Line, nil + + 00E0 MODE_360x200: ; Data for 360 by 200 Pixels + + 00E0 67 DB 067h ; 400 scan Lines & 28 Mhz Clock + 00E1 03 DB 3 ; Maximum of 3 Pages + 00E2 0168 00C8 DW 360, 200 ; Displayed Pixels (X,Y) + 00E6 0516 02D8 DW 1302, 728 ; Max Possible X and Y Sizes + + 00EA 0036 R 0044 R DW o MODE_360_Wide, MODE_200_Tall + 00EE 0020 R 0000 DW o MODE_Double_Line, nil + + 00F2 MODE_360x400: ; Data for 360 by 400 Pixels + + 00F2 67 DB 067h ; 400 scan Lines & 28 Mhz Clock + 00F3 01 DB 1 ; Maximum of 1 Pages + 00F4 0168 0190 DW 360, 400 ; Displayed Pixels X,Y + 00F8 0288 0330 DW 648, 816 ; Max Possible X and Y Sizes + + 00FC 0036 R 0044 R DW o MODE_360_Wide, MODE_400_Tall + 0100 0018 R 0000 DW o MODE_Single_Line, nil + + + ; ===== MODE X SETUP ROUTINES ===== + + ;====================================================== + ;SET_VGA_MODEX% (ModeType%, MaxXPos%, MaxYpos%, Pages%) + ;====================================================== + ; + ; Sets Up the specified version of Mode X. Allows for + ; the setup of multiple video pages, and a virtual + ; screen which can be larger than the displayed screen + ; (which can then be scrolled a pixel at a time) + ; + ; ENTRY: ModeType = Desired Screen Resolution (0-7) + ; + ; 0 = 320 x 200, 4 Pages max, 1.2:1 Aspect Ratio + ; 1 = 320 x 400, 2 Pages max, 2.4:1 Aspect Ratio + ; 2 = 360 x 200, 3 Pages max, 1.35:1 Aspect Ratio + ; 3 = 360 x 400, 1 Page max, 2.7:1 Aspect Ratio + ; 4 = 320 x 240, 3 Pages max, 1:1 Aspect Ratio + ; 5 = 320 x 480, 1 Page max, 2:1 Aspect Ratio + ; 6 = 360 x 240, 3 Pages max, 1.125:1 Aspect Ratio + ; 7 = 360 x 480, 1 Page max, 2.25:1 Aspect Ratio + ; + ; MaxXpos = The Desired Virtual Screen Width + ; MaxYpos = The Desired Virtual Screen Height + ; Pages = The Desired # of Video Pages + ; + ; EXIT: AX = Success Flag: 0 = Failure / -1= Success + ; + + 0016 SVM_STACK STRUC + 0000 0000 SVM_Table DW ? ; Offset of Mode Info Table + 0002 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP + 0000 + 000A 00000000 DD ? ; Caller + 000E 0000 SVM_Pages DW ? ; # of Screen Pages desired + 0010 0000 SVM_Ysize DW ? ; Vertical Screen Size Desired + 0012 0000 SVM_Xsize DW ? ; Horizontal Screen Size Desired + 0014 0000 SVM_Mode DW ? ; Display Resolution Desired + SVM_STACK ENDS + + PUBLIC SET_VGA_MODEX + + 0104 SET_VGA_MODEX PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 0104 55 1 PUSH BP ; Save R1 + 0105 1E 2 PUSH DS ; Save R1 + 0106 56 3 PUSH SI ; Save R1 + 0107 57 4 PUSH DI ; Save R1 + 0108 83 EC 02 SUB SP, 2 ; Allocate workspace + 010B 8B EC MOV BP, SP ; Set up Stack Frame + + ; Check Legality of Mode Request.... + + 010D 8B 5E 14 MOV BX, [BP].SVM_Mode ; Get Requested Mode # + 0110 83 FB 08 CMP BX, NUM_MODES ; Is it 0..7? + 0113 73 47 JAE @SVM_BadModeSetup ; If Not, Error out + + 0115 D1 E3 SHL BX, 1 ; Scale BX + 0117 2E: 8B B7 0064 R MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info + 011C 89 76 00 MOV [BP].SVM_Table, SI ; Save ptr for later use + + ; Check # of Requested Display Pages + + 011F 8B 4E 0E MOV CX, [BP].SVM_Pages ; Get # of Requested Pages + CLR CH ; Set Hi Word = 0! + 0122 32 ED 1 XOR CH, CH ; Set Register = 0 + 0124 2E: 3A 4C 01 CMP CL, CS:[SI].M_Pages ; Check # Pages for mode + 0128 77 32 JA @SVM_BadModeSetup ; Report Error if too Many Pages + 012A E3 30 JCXZ @SVM_BadModeSetup ; Report Error if 0 Pages + + ; Check Validity of X Size + + 012C 83 66 12 F8 AND [BP].SVM_XSize, 0FFF8h ; X size Mod 8 Must = 0 + + 0130 8B 46 12 MOV AX, [BP].SVM_XSize ; Get Logical Screen Width + 0133 2E: 3B 44 02 CMP AX, CS:[SI].M_XSize ; Check against Displayed X + 0137 72 23 JB @SVM_BadModeSetup ; Report Error if too small + 0139 2E: 3B 44 06 CMP AX, CS:[SI].M_XMax ; Check against Max X + 013D 77 1D JA @SVM_BadModeSetup ; Report Error if too big + + ; Check Validity of Y Size + + 013F 8B 5E 10 MOV BX, [BP].SVM_YSize ; Get Logical Screen Height + 0142 2E: 3B 5C 04 CMP BX, CS:[SI].M_YSize ; Check against Displayed Y + 0146 72 14 JB @SVM_BadModeSetup ; Report Error if too small + 0148 2E: 3B 5C 08 CMP BX, CS:[SI].M_YMax ; Check against Max Y + 014C 77 0E JA @SVM_BadModeSetup ; Report Error if too big + + ; Enough memory to Fit it all? + + 014E C1 E8 02 SHR AX, 2 ; # of Bytes:Line = XSize/4 + 0151 F7 E1 MUL CX ; AX = Bytes/Line * Pages + 0153 F7 E3 MUL BX ; DX:AX = Total VGA mem needed + 0155 71 0A JNO @SVM_Continue ; Exit if Total Size > 256K + + 0157 4A DEC DX ; Was it Exactly 256K??? + 0158 0B D0 OR DX, AX ; (DX = 1, AX = 0000) + 015A 74 05 JZ @SVM_Continue ; if so, it's valid... + + 015C @SVM_BadModeSetup: + + CLR AX ; Return Value = False + 015C 33 C0 1 XOR AX, AX ; Set Register = 0 + 015E E9 00E6 JMP @SVM_Exit ; Normal Exit + + 0161 @SVM_Continue: + + 0161 B8 0013 MOV AX, 13H ; Start with Mode 13H + 0164 CD 10 INT 10H ; Let BIOS Set Mode + + OUT_16 SC_INDEX, CHAIN4_OFF ; Disable Chain 4 Mode + 0166 BA 03C4 1 MOV DX, SC_INDEX ; then Select Register + 0169 B8 0604 1 MOV AX, CHAIN4_OFF ; then Get Data Value + 016C EF 1 OUT DX, AX ; Set I/O Register(s) + OUT_16 SC_INDEX, ASYNC_RESET ; (A)synchronous Reset + 016D BA 03C4 1 MOV DX, SC_INDEX ; then Select Register + 0170 B8 0100 1 MOV AX, ASYNC_RESET ; then Get Data Value + 0173 EF 1 OUT DX, AX ; Set I/O Register(s) + OUT_8 MISC_OUTPUT, CS:[SI].M_MiscR ; Set New Timing/Size + 0174 BA 03C2 1 MOV DX, MISC_OUTPUT ; then Select Register + 0177 2E: 8A 04 1 MOV AL, CS:[SI].M_MiscR ; then Get Data Value + 017A EE 1 OUT DX, AL ; Set I/O Register + OUT_16 SC_INDEX, SEQU_RESTART ; Restart Sequencer ... + 017B BA 03C4 1 MOV DX, SC_INDEX ; then Select Register + 017E B8 0300 1 MOV AX, SEQU_RESTART ; then Get Data Value + 0181 EF 1 OUT DX, AX ; Set I/O Register(s) + + OUT_8 CRTC_INDEX, 11H ; Select Vert Retrace End Register + 0182 BA 03D4 1 MOV DX, CRTC_INDEX ; then Select Register + 0185 B0 11 1 MOV AL, 11H ; then Get Data Value + 0187 EE 1 OUT DX, AL ; Set I/O Register + 0188 42 INC DX ; Point to Data + 0189 EC IN AL, DX ; Get Value, Bit 7 = Protect + 018A 24 7F AND AL, 7FH ; Mask out Write Protect + 018C EE OUT DX, AL ; And send it back + + 018D BA 03D4 MOV DX, CRTC_INDEX ; Vga Crtc Registers + 0190 83 C6 0A ADD SI, M_CRTC ; SI -> CRTC Parameter Data + + ; Load Tables of CRTC Parameters from List of Tables + + 0193 @SVM_Setup_Table: + + 0193 2E: 8B 3C MOV DI, CS:[SI] ; Get Pointer to CRTC Data Tbl + 0196 83 C6 02 ADD SI, 2 ; Point to next Ptr Entry + 0199 0B FF OR DI, DI ; A nil Ptr means that we have + 019B 74 0D JZ @SVM_Set_Data ; finished CRTC programming + + 019D @SVM_Setup_CRTC: + 019D 2E: 8B 05 MOV AX, CS:[DI] ; Get CRTC Data from Table + 01A0 83 C7 02 ADD DI, 2 ; Advance Pointer + 01A3 0B C0 OR AX, AX ; At End of Data Table? + 01A5 74 EC JZ @SVM_Setup_Table ; If so, Exit & get next Table + + 01A7 EF OUT DX, AX ; Reprogram VGA CRTC reg + 01A8 EB F3 JMP s @SVM_Setup_CRTC ; Process Next Table Entry + + ; Initialize Page & Scroll info, DI = 0 + + 01AA @SVM_Set_Data: + 01AA 89 3E 0010 R MOV DISPLAY_PAGE, DI ; Display Page = 0 + 01AE 89 3E 0012 R MOV ACTIVE_PAGE, DI ; Active Page = 0 + 01B2 89 3E 0014 R MOV CURRENT_PAGE, DI ; Current Page (Offset) = 0 + 01B6 89 3E 0018 R MOV CURRENT_XOFFSET, DI ; Horz Scroll Index = 0 + 01BA 89 3E 001A R MOV CURRENT_YOFFSET, DI ; Vert Scroll Index = 0 + Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 +modex.asm Page 3 - 1 + + + 01BE 89 3E 001C R MOV CURRENT_MOFFSET, DI ; Memory Scroll Index = 0 + + 01C2 B8 A000 MOV AX, VGA_SEGMENT ; Segment for VGA memory + 01C5 A3 0016 R MOV CURRENT_SEGMENT, AX ; Save for Future LES's + + ; Set Logical Screen Width, X Scroll and Our Data + + 01C8 8B 76 00 MOV SI, [BP].SVM_Table ; Get Saved Ptr to Mode Info + 01CB 8B 46 12 MOV AX, [BP].SVM_Xsize ; Get Display Width + + 01CE 8B C8 MOV CX, AX ; CX = Logical Width + 01D0 2E: 2B 4C 02 SUB CX, CS:[SI].M_XSize ; CX = Max X Scroll Value + 01D4 89 0E 001E R MOV MAX_XOFFSET, CX ; Set Maximum X Scroll + + 01D8 C1 E8 02 SHR AX, 2 ; Bytes = Pixels / 4 + 01DB A3 0000 R MOV SCREEN_WIDTH, AX ; Save Width in Pixels + + 01DE D1 E8 SHR AX, 1 ; Offset Value = Bytes / 2 + 01E0 B4 13 MOV AH, 13h ; CRTC Offset Register Index + 01E2 86 C4 XCHG AL, AH ; Switch format for OUT + 01E4 EF OUT DX, AX ; Set VGA CRTC Offset Reg + + ; Setup Data table, Y Scroll, Misc for Other Routines + + 01E5 8B 46 10 MOV AX, [BP].SVM_Ysize ; Get Logical Screen Height + + 01E8 8B C8 MOV CX, AX ; CX = Logical Height + 01EA 2E: 2B 5C 04 SUB BX, CS:[SI].M_YSize ; CX = Max Y Scroll Value + 01EE 89 0E 0020 R MOV MAX_YOFFSET, CX ; Set Maximum Y Scroll + + 01F2 A3 0002 R MOV SCREEN_HEIGHT, AX ; Save Height in Pixels + 01F5 F7 26 0000 R MUL SCREEN_WIDTH ; AX = Page Size in Bytes, + 01F9 A3 000E R MOV PAGE_SIZE, AX ; Save Page Size + + 01FC 8B 4E 0E MOV CX, [BP].SVM_Pages ; Get # of Pages + 01FF 89 0E 0004 R MOV LAST_PAGE, CX ; Save # of Pages + + CLR BX ; Page # = 0 + 0203 33 DB 1 XOR BX, BX ; Set Register = 0 + 0205 8B D3 MOV DX, BX ; Page 0 Offset = 0 + + 0207 @SVM_Set_Pages: + + 0207 89 97 0006 R MOV PAGE_ADDR[BX], DX ; Set Page #(BX) Offset + 020B 83 C3 02 ADD BX, 2 ; Page#++ + 020E 03 D0 ADD DX, AX ; Compute Addr of Next Page + LOOPx CX, @SVM_Set_Pages ; Loop until all Pages Set + 0210 49 1 DEC CX ; Counter-- + 0211 75 F4 1 JNZ @SVM_Set_Pages ; Jump if not 0 + + ; Clear VGA Memory + + OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes + 0213 BA 03C4 1 MOV DX, SC_INDEX ; then Select Register + 0216 B8 0F02 1 MOV AX, ALL_PLANES_ON ; then Get Data Value + 0219 EF 1 OUT DX, AX ; Set I/O Register(s) + 021A C4 3E 0014 R LES DI, d CURRENT_PAGE ; -> Start of VGA memory + + CLR AX ; AX = 0 + 021E 33 C0 1 XOR AX, AX ; Set Register = 0 + 0220 FC CLD ; Block Xfer Forwards + 0221 B9 8000 MOV CX, 8000H ; 32K * 4 * 2 = 256K + 0224 F3/ AB REP STOSW ; Clear dat memory! + + ; Setup Font Pointers + + 0226 B7 03 MOV BH, ROM_8x8_Lo ; Ask for 8x8 Font, 0-127 + 0228 B8 1130 MOV AX, GET_CHAR_PTR ; Service to Get Pointer + 022B CD 10 INT 10h ; Call VGA BIOS + + 022D 89 2E 0022 R MOV CHARSET_LOW, BP ; Save Char Set Offset + 0231 8C 06 0024 R MOV CHARSET_LOW+2, ES ; Save Char Set Segment + + 0235 B7 04 MOV BH, ROM_8x8_Hi ; Ask for 8x8 Font, 128-255 + 0237 B8 1130 MOV AX, GET_CHAR_PTR ; Service to Get Pointer + 023A CD 10 INT 10h ; Call VGA BIOS + + 023C 89 2E 0026 R MOV CHARSET_HI, BP ; Save Char Set Offset + 0240 8C 06 0028 R MOV CHARSET_HI+2, ES ; Save Char Set Segment + + 0244 B8 FFFF MOV AX, True ; Return Success Code + + 0247 @SVM_EXIT: + 0247 83 C4 02 ADD SP, 2 ; Deallocate workspace + POPx DI, SI, DS, BP ; Restore Saved Registers + 024A 5F 1 POP DI ; Restore R1 + 024B 5E 2 POP SI ; Restore R1 + 024C 1F 3 POP DS ; Restore R1 + 024D 5D 4 POP BP ; Restore R1 + 024E CA 0008 RET 8 ; Exit & Clean Up Stack + + 0251 SET_VGA_MODEX ENDP + + + ;================== + ;SET_MODEX% (Mode%) + ;================== + ; + ; Quickie Mode Set - Sets Up Mode X to Default Configuration + ; + ; ENTRY: ModeType = Desired Screen Resolution (0-7) + ; (See SET_VGA_MODEX for list) + ; + ; EXIT: AX = Success Flag: 0 = Failure / -1= Success + ; + + 000A SM_STACK STRUC + 0000 0000 0000 DW ?,? ; BP, SI + 0004 00000000 DD ? ; Caller + 0008 0000 SM_Mode DW ? ; Desired Screen Resolution + SM_STACK ENDS + + PUBLIC SET_MODEX + + 0251 SET_MODEX PROC FAR + + PUSHx BP, SI ; Preserve Important registers + 0251 55 1 PUSH BP ; Save R1 + 0252 56 2 PUSH SI ; Save R1 + 0253 8B EC MOV BP, SP ; Set up Stack Frame + + CLR AX ; Assume Failure + 0255 33 C0 1 XOR AX, AX ; Set Register = 0 + 0257 8B 5E 08 MOV BX, [BP].SM_Mode ; Get Desired Mode # + 025A 83 FB 08 CMP BX, NUM_MODES ; Is it a Valid Mode #? + 025D 73 1C JAE @SMX_Exit ; If Not, don't Bother + + 025F 53 PUSH BX ; Push Mode Parameter + + 0260 D1 E3 SHL BX, 1 ; Scale BX to word Index + 0262 2E: 8B B7 0064 R MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info + + 0267 2E: FF 74 02 PUSH CS:[SI].M_XSize ; Push Default X Size + 026B 2E: FF 74 04 PUSH CS:[SI].M_Ysize ; Push Default Y size + 026F 2E: 8A 44 01 MOV AL, CS:[SI].M_Pages ; Get Default # of Pages + CLR AH ; Hi Byte = 0 + 0273 32 E4 1 XOR AH, AH ; Set Register = 0 + 0275 50 PUSH AX ; Push # Pages + + 0276 9A ---- 0104 R CALL f SET_VGA_MODEX ; Set up Mode X! + + 027B @SMX_Exit: + POPx SI, BP ; Restore Registers + 027B 5E 1 POP SI ; Restore R1 + 027C 5D 2 POP BP ; Restore R1 + 027D CA 0002 RET 2 ; Exit & Clean Up Stack + + 0280 SET_MODEX ENDP + + + ; ===== BASIC GRAPHICS PRIMITIVES ===== + + ;============================ + ;CLEAR_VGA_SCREEN (ColorNum%) + ;============================ + ; + ; Clears the active display page + ; + ; ENTRY: ColorNum = Color Value to fill the page with + ; + ; EXIT: No meaningful values returned + ; + + 000A CVS_STACK STRUC + 0000 0000 0000 DW ?,? ; DI, BP + 0004 00000000 DD ? ; Caller + 0008 00 00 CVS_COLOR DB ?,? ; Color to Set Screen to + CVS_STACK ENDS + + PUBLIC CLEAR_VGA_SCREEN + + 0280 CLEAR_VGA_SCREEN PROC FAR + + PUSHx BP, DI ; Preserve Important Registers + 0280 55 1 PUSH BP ; Save R1 + 0281 57 2 PUSH DI ; Save R1 + 0282 8B EC MOV BP, SP ; Set up Stack Frame + + OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes + 0284 BA 03C4 1 MOV DX, SC_INDEX ; then Select Register + 0287 B8 0F02 1 MOV AX, ALL_PLANES_ON ; then Get Data Value + 028A EF 1 OUT DX, AX ; Set I/O Register(s) + 028B C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page + + 028F 8A 46 08 MOV AL, [BP].CVS_COLOR ; Get Color + 0292 8A E0 MOV AH, AL ; Copy for Word Write + 0294 FC CLD ; Block fill Forwards + + 0295 8B 0E 000E R MOV CX, PAGE_SIZE ; Get Size of Page + 0299 D1 E9 SHR CX, 1 ; Divide by 2 for Words + 029B F3/ AB REP STOSW ; Block Fill VGA memory + + POPx DI, BP ; Restore Saved Registers + 029D 5F 1 POP DI ; Restore R1 + 029E 5D 2 POP BP ; Restore R1 + 029F CA 0002 RET 2 ; Exit & Clean Up Stack + + 02A2 CLEAR_VGA_SCREEN ENDP + + + ;=================================== + ;SET_POINT (Xpos%, Ypos%, ColorNum%) + ;=================================== + ; + ; Plots a single Pixel on the active display page + ; + ; ENTRY: Xpos = X position to plot pixel at + ; Ypos = Y position to plot pixel at + ; ColorNum = Color to plot pixel with + ; + ; EXIT: No meaningful values returned + ; + + 000E SP_STACK STRUC + 0000 0000 0000 DW ?,? ; BP, DI + 0004 00000000 DD ? ; Caller + 0008 00 00 SETP_Color DB ?,? ; Color of Point to Plot + 000A 0000 SETP_Ypos DW ? ; Y pos of Point to Plot + 000C 0000 SETP_Xpos DW ? ; X pos of Point to Plot + SP_STACK ENDS + + PUBLIC SET_POINT + + 02A2 SET_POINT PROC FAR + + PUSHx BP, DI ; Preserve Registers + 02A2 55 1 PUSH BP ; Save R1 + 02A3 57 2 PUSH DI ; Save R1 + 02A4 8B EC MOV BP, SP ; Set up Stack Frame + + 02A6 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page + + 02AA 8B 46 0A MOV AX, [BP].SETP_Ypos ; Get Line # of Pixel + 02AD F7 26 0000 R MUL SCREEN_WIDTH ; Get Offset to Start of Line + + 02B1 8B 5E 0C MOV BX, [BP].SETP_Xpos ; Get Xpos + 02B4 8B CB MOV CX, BX ; Copy to extract Plane # from + 02B6 C1 EB 02 SHR BX, 2 ; X offset (Bytes) = Xpos/4 + 02B9 03 D8 ADD BX, AX ; Offset = Width*Ypos + Xpos/4 + + 02BB B8 0102 MOV AX, MAP_MASK_PLANE1 ; Map Mask & Plane Select Register + 02BE 80 E1 03 AND CL, PLANE_BITS ; Get Plane Bits + 02C1 D2 E4 SHL AH, CL ; Get Plane Select Value + OUT_16 SC_Index, AX ; Select Plane + 02C3 BA 03C4 1 MOV DX, SC_Index ; then Select Register + 02C6 EF 1 OUT DX, AX ; Set I/O Register(s) + + 02C7 8A 46 08 MOV AL,[BP].SETP_Color ; Get Pixel Color + 02CA 26: 88 01 MOV ES:[DI+BX], AL ; Draw Pixel + + POPx DI, BP ; Restore Saved Registers + Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 +modex.asm Page 4 - 1 + + + 02CD 5F 1 POP DI ; Restore R1 + 02CE 5D 2 POP BP ; Restore R1 + 02CF CA 0006 RET 6 ; Exit and Clean up Stack + + 02D2 SET_POINT ENDP + + + ;========================== + ;READ_POINT% (Xpos%, Ypos%) + ;========================== + ; + ; Read the color of a pixel from the Active Display Page + ; + ; ENTRY: Xpos = X position of pixel to read + ; Ypos = Y position of pixel to read + ; + ; EXIT: AX = Color of Pixel at (Xpos, Ypos) + ; + + 000C RP_STACK STRUC + 0000 0000 0000 DW ?,? ; BP, DI + 0004 00000000 DD ? ; Caller + 0008 0000 RP_Ypos DW ? ; Y pos of Point to Read + 000A 0000 RP_Xpos DW ? ; X pos of Point to Read + RP_STACK ENDS + + PUBLIC READ_POINT + + 02D2 READ_POINT PROC FAR + + PUSHx BP, DI ; Preserve Registers + 02D2 55 1 PUSH BP ; Save R1 + 02D3 57 2 PUSH DI ; Save R1 + 02D4 8B EC MOV BP, SP ; Set up Stack Frame + + 02D6 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page + + 02DA 8B 46 08 MOV AX, [BP].RP_Ypos ; Get Line # of Pixel + 02DD F7 26 0000 R MUL SCREEN_WIDTH ; Get Offset to Start of Line + + 02E1 8B 5E 0A MOV BX, [BP].RP_Xpos ; Get Xpos + 02E4 8B CB MOV CX, BX + 02E6 C1 EB 02 SHR BX, 2 ; X offset (Bytes) = Xpos/4 + 02E9 03 D8 ADD BX, AX ; Offset = Width*Ypos + Xpos/4 + + 02EB B0 04 MOV AL, READ_MAP ; GC Read Mask Register + 02ED 8A E1 MOV AH, CL ; Get Xpos + 02EF 80 E4 03 AND AH, PLANE_BITS ; & mask out Plane # + OUT_16 GC_INDEX, AX ; Select Plane to read in + 02F2 BA 03CE 1 MOV DX, GC_INDEX ; then Select Register + 02F5 EF 1 OUT DX, AX ; Set I/O Register(s) + + CLR AH ; Clear Return Value Hi byte + 02F6 32 E4 1 XOR AH, AH ; Set Register = 0 + 02F8 26: 8A 01 MOV AL, ES:[DI+BX] ; Get Color of Pixel + + POPx DI, BP ; Restore Saved Registers + 02FB 5F 1 POP DI ; Restore R1 + 02FC 5D 2 POP BP ; Restore R1 + 02FD CA 0004 RET 4 ; Exit and Clean up Stack + + 0300 READ_POINT ENDP + + + ;====================================================== + ;FILL_BLOCK (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%) + ;====================================================== + ; + ; Fills a rectangular block on the active display Page + ; + ; ENTRY: Xpos1 = Left X position of area to fill + ; Ypos1 = Top Y position of area to fill + ; Xpos2 = Right X position of area to fill + ; Ypos2 = Bottom Y position of area to fill + ; ColorNum = Color to fill area with + ; + ; EXIT: No meaningful values returned + ; + + 0016 FB_STACK STRUC + 0000 0000 0000 0000 DW ?x4 ; DS, DI, SI, BP + 0000 + 0008 00000000 DD ? ; Caller + 000C 00 00 FB_Color DB ?,? ; Fill Color + 000E 0000 FB_Ypos2 DW ? ; Y pos of Lower Right Pixel + 0010 0000 FB_Xpos2 DW ? ; X pos of Lower Right Pixel + 0012 0000 FB_Ypos1 DW ? ; Y pos of Upper Left Pixel + 0014 0000 FB_Xpos1 DW ? ; X pos of Upper Left Pixel + FB_STACK ENDS + + PUBLIC FILL_BLOCK + + 0300 FILL_BLOCK PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 0300 55 1 PUSH BP ; Save R1 + 0301 1E 2 PUSH DS ; Save R1 + 0302 56 3 PUSH SI ; Save R1 + 0303 57 4 PUSH DI ; Save R1 + 0304 8B EC MOV BP, SP ; Set up Stack Frame + + 0306 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page + 030A FC CLD ; Direction Flag = Forward + + OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select + 030B BA 03C4 1 MOV DX, SC_INDEX ; then Select Register + 030E B0 02 1 MOV AL, MAP_MASK ; then Get Data Value + 0310 EE 1 OUT DX, AL ; Set I/O Register + + ; Validate Pixel Coordinates + ; If necessary, Swap so X1 <= X2, Y1 <= Y2 + + 0311 8B 46 12 MOV AX, [BP].FB_Ypos1 ; AX = Y1 is Y1< Y2? + 0314 8B 5E 0E MOV BX, [BP].FB_Ypos2 ; BX = Y2 + 0317 3B C3 CMP AX, BX + 0319 7E 04 JLE @FB_NOSWAP1 + + 031B 89 5E 12 MOV [BP].FB_Ypos1, BX ; Swap Y1 and Y2 and save Y1 + 031E 93 XCHG AX, BX ; on stack for future use + + 031F @FB_NOSWAP1: + 031F 2B D8 SUB BX, AX ; Get Y width + 0321 43 INC BX ; Add 1 to avoid 0 value + 0322 89 5E 0E MOV [BP].FB_Ypos2, BX ; Save in Ypos2 + + 0325 F7 26 0000 R MUL SCREEN_WIDTH ; Mul Y1 by Bytes per Line + 0329 03 F8 ADD DI, AX ; DI = Start of Line Y1 + + 032B 8B 46 14 MOV AX, [BP].FB_Xpos1 ; Check X1 <= X2 + 032E 8B 5E 10 MOV BX, [BP].FB_Xpos2 ; + 0331 3B C3 CMP AX, BX + 0333 7E 04 JLE @FB_NOSWAP2 ; Skip Ahead if Ok + + 0335 89 46 10 MOV [BP].FB_Xpos2, AX ; Swap X1 AND X2 and save X2 + 0338 93 XCHG AX, BX ; on stack for future use + + ; All our Input Values are in order, Now determine + ; How many full "bands" 4 pixels wide (aligned) there + ; are, and if there are partial bands (<4 pixels) on + ; the left and right edges. + + 0339 @FB_NOSWAP2: + 0339 8B D0 MOV DX, AX ; DX = X1 (Pixel Position) + 033B C1 EA 02 SHR DX, 2 ; DX/4 = Bytes into Line + 033E 03 FA ADD DI, DX ; DI = Addr of Upper-Left Corner + + 0340 8B CB MOV CX, BX ; CX = X2 (Pixel Position) + 0342 C1 E9 02 SHR CX, 2 ; CX/4 = Bytes into Line + + 0345 3B D1 CMP DX, CX ; Start and end in same band? + 0347 75 03 JNE @FB_NORMAL ; if not, check for l & r edges + 0349 E9 0086 JMP @FB_ONE_BAND_ONLY ; if so, then special processing + + 034C @FB_NORMAL: + 034C 2B CA SUB CX, DX ; CX = # bands -1 + 034E 8B F0 MOV SI, AX ; SI = PLANE#(X1) + 0350 83 E6 03 AND SI, PLANE_BITS ; if Left edge is aligned then + 0353 74 27 JZ @FB_L_PLANE_FLUSH ; no special processing.. + + ; Draw "Left Edge" vertical strip of 1-3 pixels... + + OUT_8 SC_Data, Left_Clip_Mask[SI] ; Set Left Edge Plane Mask + 0355 BA 03C5 1 MOV DX, SC_Data ; then Select Register + 0358 2E: 8A 84 0000 R 1 MOV AL, Left_Clip_Mask[SI] ; then Get Data Value + 035D EE 1 OUT DX, AL ; Set I/O Register + + 035E 8B F7 MOV SI, DI ; SI = Copy of Start Addr (UL) + + 0360 8B 56 0E MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw + 0363 8A 46 0C MOV AL, [BP].FB_Color ; Get Fill Color + 0366 8B 1E 0000 R MOV BX, SCREEN_WIDTH ; Get Vertical increment Value + + 036A @FB_LEFT_LOOP: + 036A 26: 88 04 MOV ES:[SI], AL ; Fill in Left Edge Pixels + 036D 03 F3 ADD SI, BX ; Point to Next Line (Below) + LOOPjz DX, @FB_LEFT_CONT ; Exit loop if all Lines Drawn + 036F 4A 1 DEC DX ; Counter-- + 0370 74 08 1 JZ @FB_LEFT_CONT ; Jump if 0 + + 0372 26: 88 04 MOV ES:[SI], AL ; Fill in Left Edge Pixels + 0375 03 F3 ADD SI, BX ; Point to Next Line (Below) + LOOPx DX, @FB_LEFT_LOOP ; loop until left strip is drawn + 0377 4A 1 DEC DX ; Counter-- + 0378 75 F0 1 JNZ @FB_LEFT_LOOP ; Jump if not 0 + + 037A @FB_LEFT_CONT: + + 037A 47 INC DI ; Point to Middle (or Right) Block + 037B 49 DEC CX ; Reset CX instead of JMP @FB_RIGHT + + 037C @FB_L_PLANE_FLUSH: + 037C 41 INC CX ; Add in Left band to middle block + + ; DI = Addr of 1st middle Pixel (band) to fill + ; CX = # of Bands to fill -1 + + 037D @FB_RIGHT: + 037D 8B 76 10 MOV SI, [BP].FB_Xpos2 ; Get Xpos2 + 0380 83 E6 03 AND SI, PLANE_BITS ; Get Plane values + 0383 83 FE 03 CMP SI, 0003 ; Plane = 3? + 0386 74 2B JE @FB_R_EDGE_FLUSH ; Hey, add to middle + + ; Draw "Right Edge" vertical strip of 1-3 pixels... + + OUT_8 SC_Data, Right_Clip_Mask[SI] ; Right Edge Plane Mask + 0388 BA 03C5 1 MOV DX, SC_Data ; then Select Register + 038B 2E: 8A 84 0004 R 1 MOV AL, Right_Clip_Mask[SI] ; then Get Data Value + 0390 EE 1 OUT DX, AL ; Set I/O Register + + 0391 8B F7 MOV SI, DI ; Get Addr of Left Edge + 0393 03 F1 ADD SI, CX ; Add Width-1 (Bands) + 0395 4E DEC SI ; To point to top of Right Edge + + 0396 8B 56 0E MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw + 0399 8A 46 0C MOV AL, [BP].FB_Color ; Get Fill Color + 039C 8B 1E 0000 R MOV BX, SCREEN_WIDTH ; Get Vertical increment Value + + 03A0 @FB_RIGHT_LOOP: + 03A0 26: 88 04 MOV ES:[SI], AL ; Fill in Right Edge Pixels + 03A3 03 F3 ADD SI, BX ; Point to Next Line (Below) + LOOPjz DX, @FB_RIGHT_CONT ; Exit loop if all Lines Drawn + 03A5 4A 1 DEC DX ; Counter-- + 03A6 74 08 1 JZ @FB_RIGHT_CONT ; Jump if 0 + + 03A8 26: 88 04 MOV ES:[SI], AL ; Fill in Right Edge Pixels + 03AB 03 F3 ADD SI, BX ; Point to Next Line (Below) + LOOPx DX, @FB_RIGHT_LOOP ; loop until left strip is drawn + 03AD 4A 1 DEC DX ; Counter-- + 03AE 75 F0 1 JNZ @FB_RIGHT_LOOP ; Jump if not 0 + + 03B0 @FB_RIGHT_CONT: + + 03B0 49 DEC CX ; Minus 1 for Middle bands + 03B1 74 51 JZ @FB_EXIT ; Uh.. no Middle bands... + + 03B3 @FB_R_EDGE_FLUSH: + + ; DI = Addr of Upper Left block to fill + ; CX = # of Bands to fill in (width) + + OUT_8 SC_Data, ALL_PLANES ; Write to All Planes + 03B3 BA 03C5 1 MOV DX, SC_Data ; then Select Register + 03B6 B0 0F 1 MOV AL, ALL_PLANES ; then Get Data Value + 03B8 EE 1 OUT DX, AL ; Set I/O Register + + 03B9 8B 16 0000 R MOV DX, SCREEN_WIDTH ; DX = DI Increment + 03BD 2B D1 SUB DX, CX ; = Screen_Width-# Planes Filled + + 03BF 8B D9 MOV BX, CX ; BX = Quick Refill for CX + 03C1 8B 76 0E MOV SI, [BP].FB_Ypos2 ; SI = # of Line to Fill + 03C4 8A 46 0C MOV AL, [BP].FB_Color ; Get Fill Color + Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 +modex.asm Page 5 - 1 + + + + 03C7 @FB_MIDDLE_LOOP: + 03C7 F3/ AA REP STOSB ; Fill in entire line + + 03C9 8B CB MOV CX, BX ; Recharge CX (Line Width) + 03CB 03 FA ADD DI, DX ; Point to start of Next Line + LOOPx SI, @FB_MIDDLE_LOOP ; Loop until all lines drawn + 03CD 4E 1 DEC SI ; Counter-- + 03CE 75 F7 1 JNZ @FB_MIDDLE_LOOP ; Jump if not 0 + + 03D0 EB 32 JMP s @FB_EXIT ; Outa here + + 03D2 @FB_ONE_BAND_ONLY: + 03D2 8B F0 MOV SI, AX ; Get Left Clip Mask, Save X1 + 03D4 83 E6 03 AND SI, PLANE_BITS ; Mask out Row # + 03D7 2E: 8A 84 0000 R MOV AL, Left_Clip_Mask[SI] ; Get Left Edge Mask + 03DC 8B F3 MOV SI, BX ; Get Right Clip Mask, Save X2 + 03DE 83 E6 03 AND SI, PLANE_BITS ; Mask out Row # + 03E1 2E: 22 84 0004 R AND AL, Right_Clip_Mask[SI] ; Get Right Edge Mask byte + + OUT_8 SC_Data, AL ; Clip For Left & Right Masks + 03E6 BA 03C5 1 MOV DX, SC_Data ; then Select Register + 03E9 EE 1 OUT DX, AL ; Set I/O Register + + 03EA 8B 4E 0E MOV CX, [BP].FB_Ypos2 ; Get # of Lines to draw + 03ED 8A 46 0C MOV AL, [BP].FB_Color ; Get Fill Color + 03F0 8B 1E 0000 R MOV BX, SCREEN_WIDTH ; Get Vertical increment Value + + 03F4 @FB_ONE_LOOP: + 03F4 26: 88 05 MOV ES:[DI], AL ; Fill in Pixels + 03F7 03 FB ADD DI, BX ; Point to Next Line (Below) + LOOPjz CX, @FB_EXIT ; Exit loop if all Lines Drawn + 03F9 49 1 DEC CX ; Counter-- + 03FA 74 08 1 JZ @FB_EXIT ; Jump if 0 + + 03FC 26: 88 05 MOV ES:[DI], AL ; Fill in Pixels + 03FF 03 FB ADD DI, BX ; Point to Next Line (Below) + LOOPx CX, @FB_ONE_LOOP ; loop until left strip is drawn + 0401 49 1 DEC CX ; Counter-- + 0402 75 F0 1 JNZ @FB_ONE_LOOP ; Jump if not 0 + + 0404 @FB_EXIT: + POPx DI, SI, DS, BP ; Restore Saved Registers + 0404 5F 1 POP DI ; Restore R1 + 0405 5E 2 POP SI ; Restore R1 + 0406 1F 3 POP DS ; Restore R1 + 0407 5D 4 POP BP ; Restore R1 + 0408 CA 000A RET 10 ; Exit and Clean up Stack + + 040B FILL_BLOCK ENDP + + + ;===================================================== + ;DRAW_LINE (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%) + ;===================================================== + ; + ; Draws a Line on the active display page + ; + ; ENTRY: Xpos1 = X position of first point on line + ; Ypos1 = Y position of first point on line + ; Xpos2 = X position of last point on line + ; Ypos2 = Y position of last point on line + ; ColorNum = Color to draw line with + ; + ; EXIT: No meaningful values returned + ; + + 0014 DL_STACK STRUC + 0000 0000 0000 0000 DW ?x3 ; DI, SI, BP + 0006 00000000 DD ? ; Caller + 000A 00 00 DL_ColorF DB ?,? ; Line Draw Color + 000C 0000 DL_Ypos2 DW ? ; Y pos of last point + 000E 0000 DL_Xpos2 DW ? ; X pos of last point + 0010 0000 DL_Ypos1 DW ? ; Y pos of first point + 0012 0000 DL_Xpos1 DW ? ; X pos of first point + DL_STACK ENDS + + PUBLIC DRAW_LINE + + 040B DRAW_LINE PROC FAR + + PUSHx BP, SI, DI ; Preserve Important Registers + 040B 55 1 PUSH BP ; Save R1 + 040C 56 2 PUSH SI ; Save R1 + 040D 57 3 PUSH DI ; Save R1 + 040E 8B EC MOV BP, SP ; Set up Stack Frame + 0410 FC CLD ; Direction Flag = Forward + + OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select + 0411 BA 03C4 1 MOV DX, SC_INDEX ; then Select Register + 0414 B0 02 1 MOV AL, MAP_MASK ; then Get Data Value + 0416 EE 1 OUT DX, AL ; Set I/O Register + 0417 8A 6E 0A MOV CH, [BP].DL_ColorF ; Save Line Color in CH + + ; Check Line Type + + 041A 8B 76 12 MOV SI, [BP].DL_Xpos1 ; AX = X1 is X1< X2? + 041D 8B 7E 0E MOV DI, [BP].DL_Xpos2 ; DX = X2 + 0420 3B F7 CMP SI, DI ; Is X1 < X2 + 0422 74 5D JE @DL_VLINE ; If X1=X2, Draw Vertical Line + 0424 7C 02 JL @DL_NOSWAP1 ; If X1 < X2, don't swap + + 0426 87 F7 XCHG SI, DI ; X2 IS > X1, SO SWAP THEM + + 0428 @DL_NOSWAP1: + + ; SI = X1, DI = X2 + + 0428 8B 46 10 MOV AX, [BP].DL_Ypos1 ; AX = Y1 is Y1 <> Y2? + 042B 3B 46 0C CMP AX, [BP].DL_Ypos2 ; Y1 = Y2? + 042E 74 03 JE @DL_HORZ ; If so, Draw a Horizontal Line + + 0430 E9 0094 JMP @DL_BREZHAM ; Diagonal line... go do it... + + ; This Code draws a Horizontal Line in Mode X where: + ; SI = X1, DI = X2, and AX = Y1/Y2 + + 0433 @DL_HORZ: + + 0433 F7 26 0000 R MUL SCREEN_WIDTH ; Offset = Ypos * Screen_Width + 0437 8B D0 MOV DX, AX ; CX = Line offset into Page + + 0439 8B C6 MOV AX, SI ; Get Left edge, Save X1 + 043B 83 E6 03 AND SI, PLANE_BITS ; Mask out Row # + 043E 2E: 8A 9C 0000 R MOV BL, Left_Clip_Mask[SI] ; Get Left Edge Mask + 0443 8B CF MOV CX, DI ; Get Right edge, Save X2 + 0445 83 E7 03 AND DI, PLANE_BITS ; Mask out Row # + 0448 2E: 8A BD 0004 R MOV BH, Right_Clip_Mask[DI] ; Get Right Edge Mask byte + + 044D C1 E8 02 SHR AX, 2 ; Get X1 Byte # (=X1/4) + 0450 C1 E9 02 SHR CX, 2 ; Get X2 Byte # (=X2/4) + + 0453 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page + 0457 03 FA ADD DI, DX ; Point to Start of Line + 0459 03 F8 ADD DI, AX ; Point to Pixel X1 + + 045B 2B C8 SUB CX, AX ; CX = # Of Bands (-1) to set + 045D 75 02 JNZ @DL_LONGLN ; jump if longer than one segment + + 045F 22 DF AND BL, BH ; otherwise, merge clip masks + + 0461 @DL_LONGLN: + + OUT_8 SC_Data, BL ; Set the Left Clip Mask + 0461 BA 03C5 1 MOV DX, SC_Data ; then Select Register + 0464 8A C3 1 MOV AL, BL ; then Get Data Value + 0466 EE 1 OUT DX, AL ; Set I/O Register + + 0467 8A 46 0A MOV AL, [BP].DL_ColorF ; Get Line Color + 046A 8A D8 MOV BL, AL ; BL = Copy of Line Color + 046C AA STOSB ; Set Left (1-4) Pixels + + 046D E3 55 JCXZ @DL_EXIT ; Done if only one Line Segment + + 046F 49 DEC CX ; CX = # of Middle Segments + 0470 74 07 JZ @DL_XRSEG ; If no middle segments.... + + ; Draw Middle Segments + + OUT_8 DX, ALL_PLANES ; Write to ALL Planes + 0472 B0 0F 1 MOV AL, ALL_PLANES ; then Get Data Value + 0474 EE 1 OUT DX, AL ; Set I/O Register + + 0475 8A C3 MOV AL, BL ; Get Color from BL + 0477 F3/ AA REP STOSB ; Draw Middle (4 Pixel) Segments + + 0479 @DL_XRSEG: + OUT_8 DX, BH ; Select Planes for Right Clip Mask + 0479 8A C7 1 MOV AL, BH ; then Get Data Value + 047B EE 1 OUT DX, AL ; Set I/O Register + 047C 8A C3 MOV AL, BL ; Get Color Value + 047E AA STOSB ; Draw Right (1-4) Pixels + + 047F EB 43 JMP s @DL_EXIT ; We Are Done... + + + ; This Code Draws A Vertical Line. On entry: + ; CH = Line Color, SI & DI = X1 + + 0481 @DL_VLINE: + + 0481 8B 46 10 MOV AX, [BP].DL_Ypos1 ; AX = Y1 + 0484 8B 76 0C MOV SI, [BP].DL_Ypos2 ; SI = Y2 + 0487 3B C6 CMP AX, SI ; Is Y1 < Y2? + 0489 7E 01 JLE @DL_NOSWAP2 ; if so, Don't Swap them + + 048B 96 XCHG AX, SI ; Ok, NOW Y1 < Y2 + + 048C @DL_NOSWAP2: + + 048C 2B F0 SUB SI, AX ; SI = Line Height (Y2-Y1+1) + 048E 46 INC SI + + ; AX = Y1, DI = X1, Get offset into Page into AX + + 048F F7 26 0000 R MUL SCREEN_WIDTH ; Offset = Y1 (AX) * Screen Width + 0493 8B D7 MOV DX, DI ; Copy Xpos into DX + 0495 C1 EF 02 SHR DI, 2 ; DI = Xpos/4 + 0498 03 C7 ADD AX, DI ; DI = Xpos/4 + ScreenWidth * Y1 + + 049A C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page + 049E 03 F8 ADD DI, AX ; Point to Pixel X1, Y1 + + ;Select Plane + + 04A0 8A CA MOV CL, DL ; CL = Save X1 + 04A2 80 E1 03 AND CL, PLANE_BITS ; Get X1 MOD 4 (Plane #) + 04A5 B8 0102 MOV AX, MAP_MASK_PLANE1 ; Code to set Plane #1 + 04A8 D2 E4 SHL AH, CL ; Change to Correct Plane # + OUT_16 SC_Index, AX ; Select Plane + 04AA BA 03C4 1 MOV DX, SC_Index ; then Select Register + 04AD EF 1 OUT DX, AX ; Set I/O Register(s) + + 04AE 8A C5 MOV AL, CH ; Get Saved Color + 04B0 8B 1E 0000 R MOV BX, SCREEN_WIDTH ; Get Offset to Advance Line By + + 04B4 @DL_VLoop: + 04B4 26: 88 05 MOV ES:[DI], AL ; Draw Single Pixel + 04B7 03 FB ADD DI, BX ; Point to Next Line + LOOPjz SI, @DL_EXIT ; Lines--, Exit if done + 04B9 4E 1 DEC SI ; Counter-- + 04BA 74 08 1 JZ @DL_EXIT ; Jump if 0 + + 04BC 26: 88 05 MOV ES:[DI], AL ; Draw Single Pixel + 04BF 03 FB ADD DI, BX ; Point to Next Line + LOOPx SI, @DL_VLoop ; Lines--, Loop until Done + 04C1 4E 1 DEC SI ; Counter-- + 04C2 75 F0 1 JNZ @DL_VLoop ; Jump if not 0 + + 04C4 @DL_EXIT: + + 04C4 E9 0157 JMP @DL_EXIT2 ; Done! + + ; This code Draws a diagonal line in Mode X + + 04C7 @DL_BREZHAM: + 04C7 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page + + 04CB 8B 46 10 MOV AX, [BP].DL_Ypos1 ; get Y1 value + 04CE 8B 5E 0C MOV BX, [BP].DL_Ypos2 ; get Y2 value + 04D1 8B 4E 12 MOV CX, [BP].DL_Xpos1 ; Get Starting Xpos + + 04D4 3B D8 CMP BX, AX ; Y2-Y1 is? + 04D6 73 04 JNC @DL_DeltaYOK ; if Y2>=Y1 then goto... + + 04D8 93 XCHG BX, AX ; Swap em... + 04D9 8B 4E 0E MOV CX, [BP].DL_Xpos2 ; Get New Starting Xpos + + 04DC @DL_DeltaYOK: + 04DC F7 26 0000 R MUL SCREEN_WIDTH ; Offset = SCREEN_WIDTH * Y1 + + Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 +modex.asm Page 6 - 1 + + + 04E0 03 F8 ADD DI, AX ; DI -> Start of Line Y1 on Page + 04E2 8B C1 MOV AX, CX ; AX = Xpos (X1) + 04E4 C1 E8 02 SHR AX, 2 ; /4 = Byte Offset into Line + 04E7 03 F8 ADD DI, AX ; DI = Starting pos (X1,Y1) + + 04E9 B0 11 MOV AL, 11h ; Staring Mask + 04EB 80 E1 03 AND CL, PLANE_BITS ; Get Plane # + 04EE D2 E0 SHL AL, CL ; and shift into place + 04F0 8A 66 0A MOV AH, [BP].DL_ColorF ; Color in Hi Bytes + + 04F3 50 PUSH AX ; Save Mask,Color... + + 04F4 8A E0 MOV AH, AL ; Plane # in AH + 04F6 B0 02 MOV AL, MAP_MASK ; Select Plane Register + OUT_16 SC_Index, AX ; Select initial plane + 04F8 BA 03C4 1 MOV DX, SC_Index ; then Select Register + 04FB EF 1 OUT DX, AX ; Set I/O Register(s) + + 04FC 8B 46 12 MOV AX, [BP].DL_Xpos1 ; get X1 value + 04FF 8B 5E 10 MOV BX, [BP].DL_Ypos1 ; get Y1 value + 0502 8B 4E 0E MOV CX, [BP].DL_Xpos2 ; get X2 value + 0505 8B 56 0C MOV DX, [BP].DL_Ypos2 ; get Y2 value + + 0508 8B 2E 0000 R MOV BP, SCREEN_WIDTH ; Use BP for Line width to + ; to avoid extra memory access + + 050C 2B D3 SUB DX, BX ; figure Delta_Y + 050E 73 05 JNC @DL_DeltaYOK2 ; jump if Y2 >= Y1 + + 0510 03 DA ADD BX, DX ; put Y2 into Y1 + 0512 F7 DA NEG DX ; abs(Delta_Y) + 0514 91 XCHG AX, CX ; and exchange X1 and X2 + + 0515 @DL_DeltaYOK2: + 0515 BB 8000 MOV BX, 08000H ; seed for fraction accumulator + + 0518 2B C8 SUB CX, AX ; figure Delta_X + 051A 72 03 JC @DL_DrawLeft ; if negative, go left + + 051C E9 0084 JMP @DL_DrawRight ; Draw Line that slopes right + + 051F @DL_DrawLeft: + + 051F F7 D9 NEG CX ; abs(Delta_X) + + 0521 3B CA CMP CX, DX ; is Delta_X < Delta_Y? + 0523 72 41 JB @DL_SteepLeft ; yes, so go do steep line + ; (Delta_Y iterations) + + ; Draw a Shallow line to the left in Mode X + + 0525 @DL_ShallowLeft: + CLR AX ; zero low word of Delta_Y * 10000h + 0525 33 C0 1 XOR AX, AX ; Set Register = 0 + 0527 2B C2 SUB AX, DX ; DX:AX <- DX * 0FFFFh + 0529 83 DA 00 SBB DX, 0 ; include carry + 052C F7 F1 DIV CX ; divide by Delta_X + + 052E 8B F3 MOV SI, BX ; SI = Accumulator + 0530 8B D8 MOV BX, AX ; BX = Add fraction + 0532 58 POP AX ; Get Color, Bit mask + 0533 BA 03C5 MOV DX, SC_Data ; Sequence controller data register + 0536 41 INC CX ; Inc Delta_X so we can unroll loop + + ; Loop (x2) to Draw Pixels, Move Left, and Maybe Down... + + 0537 @DL_SLLLoop: + 0537 26: 88 25 MOV ES:[DI], AH ; set first pixel, plane data set up + LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done + 053A 49 1 DEC CX ; Counter-- + 053B 74 26 1 JZ @DL_SLLExit ; Jump if 0 + + 053D 03 F3 ADD SI, BX ; add numerator to accumulator + 053F 73 02 JNC @DL_SLLL2nc ; move down on carry + + 0541 03 FD ADD DI, BP ; Move Down one line... + + 0543 @DL_SLLL2nc: + 0543 4F DEC DI ; Left one addr + 0544 D0 C8 ROR AL, 1 ; Move Left one plane, back on 0 1 2 + 0546 3C 87 CMP AL, 87h ; wrap?, if AL <88 then Carry set + 0548 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry + 054B EE OUT DX, AL ; Set up New Bit Plane mask + + 054C 26: 88 25 MOV ES:[DI], AH ; set pixel + LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done + 054F 49 1 DEC CX ; Counter-- + 0550 74 11 1 JZ @DL_SLLExit ; Jump if 0 + + 0552 03 F3 ADD SI, BX ; add numerator to accumulator, + 0554 73 02 JNC @DL_SLLL3nc ; move down on carry + + 0556 03 FD ADD DI, BP ; Move Down one line... + + 0558 @DL_SLLL3nc: ; Now move left a pixel... + 0558 4F DEC DI ; Left one addr + 0559 D0 C8 ROR AL, 1 ; Move Left one plane, back on 0 1 2 + 055B 3C 87 CMP AL, 87h ; Wrap?, if AL <88 then Carry set + 055D 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry + 0560 EE OUT DX, AL ; Set up New Bit Plane mask + 0561 EB D4 JMP s @DL_SLLLoop ; loop until done + + 0563 @DL_SLLExit: + 0563 E9 00B8 JMP @DL_EXIT2 ; and exit + + ; Draw a steep line to the left in Mode X + + 0566 @DL_SteepLeft: + CLR AX ; zero low word of Delta_Y * 10000h + 0566 33 C0 1 XOR AX, AX ; Set Register = 0 + 0568 87 D1 XCHG DX, CX ; Delta_Y switched with Delta_X + 056A F7 F1 DIV CX ; divide by Delta_Y + + 056C 8B F3 MOV SI, BX ; SI = Accumulator + 056E 8B D8 MOV BX, AX ; BX = Add Fraction + 0570 58 POP AX ; Get Color, Bit mask + 0571 BA 03C5 MOV DX, SC_Data ; Sequence controller data register + 0574 41 INC CX ; Inc Delta_Y so we can unroll loop + + ; Loop (x2) to Draw Pixels, Move Down, and Maybe left + + 0575 @DL_STLLoop: + + 0575 26: 88 25 MOV ES:[DI], AH ; set first pixel + LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done + 0578 49 1 DEC CX ; Counter-- + 0579 74 26 1 JZ @DL_STLExit ; Jump if 0 + + 057B 03 F3 ADD SI, BX ; add numerator to accumulator + 057D 73 09 JNC @DL_STLnc2 ; No carry, just move down! + + 057F 4F DEC DI ; Move Left one addr + 0580 D0 C8 ROR AL, 1 ; Move Left one plane, back on 0 1 2 + 0582 3C 87 CMP AL, 87h ; Wrap?, if AL <88 then Carry set + 0584 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry + 0587 EE OUT DX, AL ; Set up New Bit Plane mask + + 0588 @DL_STLnc2: + 0588 03 FD ADD DI, BP ; advance to next line. + + 058A 26: 88 25 MOV ES:[DI], AH ; set pixel + LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done + 058D 49 1 DEC CX ; Counter-- + 058E 74 11 1 JZ @DL_STLExit ; Jump if 0 + + 0590 03 F3 ADD SI, BX ; add numerator to accumulator + 0592 73 09 JNC @DL_STLnc3 ; No carry, just move down! + + 0594 4F DEC DI ; Move Left one addr + 0595 D0 C8 ROR AL, 1 ; Move Left one plane, back on 0 1 2 + 0597 3C 87 CMP AL, 87h ; Wrap?, if AL <88 then Carry set + 0599 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry + 059C EE OUT DX, AL ; Set up New Bit Plane mask + + 059D @DL_STLnc3: + 059D 03 FD ADD DI, BP ; advance to next line. + 059F EB D4 JMP s @DL_STLLoop ; Loop until done + + 05A1 @DL_STLExit: + 05A1 EB 7B JMP @DL_EXIT2 ; and exit + + ; Draw a line that goes to the Right... + + 05A3 @DL_DrawRight: + 05A3 3B CA CMP CX, DX ; is Delta_X < Delta_Y? + 05A5 72 3E JB @DL_SteepRight ; yes, so go do steep line + ; (Delta_Y iterations) + + ; Draw a Shallow line to the Right in Mode X + + 05A7 @DL_ShallowRight: + CLR AX ; zero low word of Delta_Y * 10000h + 05A7 33 C0 1 XOR AX, AX ; Set Register = 0 + 05A9 2B C2 SUB AX, DX ; DX:AX <- DX * 0FFFFh + 05AB 83 DA 00 SBB DX, 0 ; include carry + 05AE F7 F1 DIV CX ; divide by Delta_X + + 05B0 8B F3 MOV SI, BX ; SI = Accumulator + 05B2 8B D8 MOV BX, AX ; BX = Add Fraction + 05B4 58 POP AX ; Get Color, Bit mask + 05B5 BA 03C5 MOV DX, SC_Data ; Sequence controller data register + 05B8 41 INC CX ; Inc Delta_X so we can unroll loop + + ; Loop (x2) to Draw Pixels, Move Right, and Maybe Down... + + 05B9 @DL_SLRLoop: + 05B9 26: 88 25 MOV ES:[DI], AH ; set first pixel, mask is set up + LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done.. + 05BC 49 1 DEC CX ; Counter-- + 05BD 74 24 1 JZ @DL_SLRExit ; Jump if 0 + + 05BF 03 F3 ADD SI, BX ; add numerator to accumulator + 05C1 73 02 JNC @DL_SLR2nc ; don't move down if carry not set + + 05C3 03 FD ADD DI, BP ; Move Down one line... + + 05C5 @DL_SLR2nc: ; Now move right a pixel... + 05C5 D0 C0 ROL AL, 1 ; Move Right one addr if Plane = 0 + 05C7 3C 12 CMP AL, 12h ; Wrap? if AL >12 then Carry not set + 05C9 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry + 05CC EE OUT DX, AL ; Set up New Bit Plane mask + + 05CD 26: 88 25 MOV ES:[DI], AH ; set pixel + LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done.. + 05D0 49 1 DEC CX ; Counter-- + 05D1 74 10 1 JZ @DL_SLRExit ; Jump if 0 + + 05D3 03 F3 ADD SI, BX ; add numerator to accumulator + 05D5 73 02 JNC @DL_SLR3nc ; don't move down if carry not set + + 05D7 03 FD ADD DI, BP ; Move Down one line... + + 05D9 @DL_SLR3nc: + 05D9 D0 C0 ROL AL, 1 ; Move Right one addr if Plane = 0 + 05DB 3C 12 CMP AL, 12h ; Wrap? if AL >12 then Carry not set + 05DD 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry + 05E0 EE OUT DX, AL ; Set up New Bit Plane mask + 05E1 EB D6 JMP s @DL_SLRLoop ; loop till done + + 05E3 @DL_SLRExit: + 05E3 EB 39 JMP @DL_EXIT2 ; and exit + + ; Draw a Steep line to the Right in Mode X + + 05E5 @DL_SteepRight: + CLR AX ; zero low word of Delta_Y * 10000h + 05E5 33 C0 1 XOR AX, AX ; Set Register = 0 + 05E7 87 D1 XCHG DX, CX ; Delta_Y switched with Delta_X + 05E9 F7 F1 DIV CX ; divide by Delta_Y + + 05EB 8B F3 MOV SI, BX ; SI = Accumulator + 05ED 8B D8 MOV BX, AX ; BX = Add Fraction + 05EF 58 POP AX ; Get Color, Bit mask + 05F0 BA 03C5 MOV DX, SC_Data ; Sequence controller data register + 05F3 41 INC CX ; Inc Delta_Y so we can unroll loop + + ; Loop (x2) to Draw Pixels, Move Down, and Maybe Right + + 05F4 @STRLoop: + 05F4 26: 88 25 MOV ES:[DI], AH ; set first pixel, mask is set up + LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done + 05F7 49 1 DEC CX ; Counter-- + 05F8 74 24 1 JZ @DL_EXIT2 ; Jump if 0 + + 05FA 03 F3 ADD SI, BX ; add numerator to accumulator + 05FC 73 08 JNC @STRnc2 ; if no carry then just go down... + + 05FE D0 C0 ROL AL, 1 ; Move Right one addr if Plane = 0 + 0600 3C 12 CMP AL, 12h ; Wrap? if AL >12 then Carry not set + 0602 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry + 0605 EE OUT DX, AL ; Set up New Bit Plane mask + Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 +modex.asm Page 7 - 1 + + + + 0606 @STRnc2: + 0606 03 FD ADD DI, BP ; advance to next line. + + 0608 26: 88 25 MOV ES:[DI], AH ; set pixel + LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done + 060B 49 1 DEC CX ; Counter-- + 060C 74 10 1 JZ @DL_EXIT2 ; Jump if 0 + + 060E 03 F3 ADD SI, BX ; add numerator to accumulator + 0610 73 08 JNC @STRnc3 ; if no carry then just go down... + + 0612 D0 C0 ROL AL, 1 ; Move Right one addr if Plane = 0 + 0614 3C 12 CMP AL, 12h ; Wrap? if AL >12 then Carry not set + 0616 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry + 0619 EE OUT DX, AL ; Set up New Bit Plane mask + + 061A @STRnc3: + 061A 03 FD ADD DI, BP ; advance to next line. + 061C EB D6 JMP s @STRLoop ; loop till done + + 061E @DL_EXIT2: + POPx DI, SI, BP ; Restore Saved Registers + 061E 5F 1 POP DI ; Restore R1 + 061F 5E 2 POP SI ; Restore R1 + 0620 5D 3 POP BP ; Restore R1 + 0621 CA 000A RET 10 ; Exit and Clean up Stack + + 0624 DRAW_LINE ENDP + + + ; ===== DAC COLOR REGISTER ROUTINES ===== + + ;================================================= + ;SET_DAC_REGISTER (Register%, Red%, Green%, Blue%) + ;================================================= + ; + ; Sets a single (RGB) Vga Palette Register + ; + ; ENTRY: Register = The DAC # to modify (0-255) + ; Red = The new Red Intensity (0-63) + ; Green = The new Green Intensity (0-63) + ; Blue = The new Blue Intensity (0-63) + ; + ; EXIT: No meaningful values returned + ; + + 000E SDR_STACK STRUC + 0000 0000 DW ? ; BP + 0002 00000000 DD ? ; Caller + 0006 00 00 SDR_Blue DB ?,? ; Blue Data Value + 0008 00 00 SDR_Green DB ?,? ; Green Data Value + 000A 00 00 SDR_Red DB ?,? ; Red Data Value + 000C 00 00 SDR_Register DB ?,? ; Palette Register # + SDR_STACK ENDS + + PUBLIC SET_DAC_REGISTER + + 0624 SET_DAC_REGISTER PROC FAR + + 0624 55 PUSH BP ; Save BP + 0625 8B EC MOV BP, SP ; Set up Stack Frame + + ; Select which DAC Register to modify + + OUT_8 DAC_WRITE_ADDR, [BP].SDR_Register + 0627 BA 03C8 1 MOV DX, DAC_WRITE_ADDR ; then Select Register + 062A 8A 46 0C 1 MOV AL, [BP].SDR_Register ; then Get Data Value + 062D EE 1 OUT DX, AL ; Set I/O Register + + 062E BA 03C9 MOV DX, PEL_DATA_REG ; Dac Data Register + OUT_8 DX, [BP].SDR_Red ; Set Red Intensity + 0631 8A 46 0A 1 MOV AL, [BP].SDR_Red ; then Get Data Value + 0634 EE 1 OUT DX, AL ; Set I/O Register + OUT_8 DX, [BP].SDR_Green ; Set Green Intensity + 0635 8A 46 08 1 MOV AL, [BP].SDR_Green ; then Get Data Value + 0638 EE 1 OUT DX, AL ; Set I/O Register + OUT_8 DX, [BP].SDR_Blue ; Set Blue Intensity + 0639 8A 46 06 1 MOV AL, [BP].SDR_Blue ; then Get Data Value + 063C EE 1 OUT DX, AL ; Set I/O Register + + 063D 5D POP BP ; Restore Registers + 063E CA 0008 RET 8 ; Exit & Clean Up Stack + + 0641 SET_DAC_REGISTER ENDP + + ;==================================================== + ;GET_DAC_REGISTER (Register%, &Red%, &Green%, &Blue%) + ;==================================================== + ; + ; Reads the RGB Values of a single Vga Palette Register + ; + ; ENTRY: Register = The DAC # to read (0-255) + ; Red = Offset to Red Variable in DS + ; Green = Offset to Green Variable in DS + ; Blue = Offset to Blue Variable in DS + ; + ; EXIT: The values of the integer variables Red, + ; Green, and Blue are set to the values + ; taken from the specified DAC register. + ; + + 000E GDR_STACK STRUC + 0000 0000 DW ? ; BP + 0002 00000000 DD ? ; Caller + 0006 0000 GDR_Blue DW ? ; Addr of Blue Data Value in DS + 0008 0000 GDR_Green DW ? ; Addr of Green Data Value in DS + 000A 0000 GDR_Red DW ? ; Addr of Red Data Value in DS + 000C 00 00 GDR_Register DB ?,? ; Palette Register # + GDR_STACK ENDS + + PUBLIC GET_DAC_REGISTER + + 0641 GET_DAC_REGISTER PROC FAR + + 0641 55 PUSH BP ; Save BP + 0642 8B EC MOV BP, SP ; Set up Stack Frame + + ; Select which DAC Register to read in + + OUT_8 DAC_READ_ADDR, [BP].GDR_Register + 0644 BA 03C7 1 MOV DX, DAC_READ_ADDR ; then Select Register + 0647 8A 46 0C 1 MOV AL, [BP].GDR_Register ; then Get Data Value + 064A EE 1 OUT DX, AL ; Set I/O Register + + 064B BA 03C9 MOV DX, PEL_DATA_REG ; Dac Data Register + CLR AX ; Clear AX + 064E 33 C0 1 XOR AX, AX ; Set Register = 0 + + 0650 EC IN AL, DX ; Read Red Value + 0651 8B 5E 0A MOV BX, [BP].GDR_Red ; Get Address of Red% + 0654 89 07 MOV [BX], AX ; *Red% = AX + + 0656 EC IN AL, DX ; Read Green Value + 0657 8B 5E 08 MOV BX, [BP].GDR_Green ; Get Address of Green% + 065A 89 07 MOV [BX], AX ; *Green% = AX + + 065C EC IN AL, DX ; Read Blue Value + 065D 8B 5E 06 MOV BX, [BP].GDR_Blue ; Get Address of Blue% + 0660 89 07 MOV [BX], AX ; *Blue% = AX + + 0662 5D POP BP ; Restore Registers + 0663 CA 0008 RET 8 ; Exit & Clean Up Stack + + 0666 GET_DAC_REGISTER ENDP + + + ;=========================================================== + ;LOAD_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%, Sync%) + ;=========================================================== + ; + ; Sets a Block of Vga Palette Registers + ; + ; ENTRY: PalData = Far Pointer to Block of palette data + ; StartReg = First Register # in range to set (0-255) + ; EndReg = Last Register # in Range to set (0-255) + ; Sync = Wait for Vertical Retrace Flag (Boolean) + ; + ; EXIT: No meaningful values returned + ; + ; NOTES: PalData is a linear array of 3 byte Palette values + ; in the order: Red (0-63), Green (0-63), Blue (0-63) + ; + + 0014 LDR_STACK STRUC + 0000 0000 0000 0000 DW ?x3 ; BP, DS, SI + 0006 00000000 DD ? ; Caller + 000A 0000 LDR_Sync DW ? ; Vertical Sync Flag + 000C 00 00 LDR_EndReg DB ?,? ; Last Register # + 000E 00 00 LDR_StartReg DB ?,? ; First Register # + 0010 00000000 LDR_PalData DD ? ; Far Ptr to Palette Data + LDR_STACK ENDS + + PUBLIC LOAD_DAC_REGISTERS + + 0666 LOAD_DAC_REGISTERS PROC FAR + + PUSHx BP, DS, SI ; Save Registers + 0666 55 1 PUSH BP ; Save R1 + 0667 1E 2 PUSH DS ; Save R1 + 0668 56 3 PUSH SI ; Save R1 + 0669 8B EC mov BP, SP ; Set up Stack Frame + + 066B 8B 46 0A mov AX, [BP].LDR_Sync ; Get Vertical Sync Flag + 066E 0B C0 or AX, AX ; is Sync Flag = 0? + 0670 74 05 jz @LDR_Load ; if so, skip call + + 0672 9A ---- 0795 R call f SYNC_DISPLAY ; wait for vsync + + ; Determine register #'s, size to copy, etc + + 0677 @LDR_Load: + + 0677 C5 76 10 lds SI, [BP].LDR_PalData ; DS:SI -> Palette Data + 067A BA 03C8 mov DX, DAC_WRITE_ADDR ; DAC register # selector + + CLR AX, BX ; Clear for byte loads + 067D 33 C0 1 XOR AX, AX ; Set Register = 0 + 067F 33 DB 2 XOR BX, BX ; Set Register = 0 + 0681 8A 46 0E mov AL, [BP].LDR_StartReg ; Get Start Register + 0684 8A 5E 0C mov BL, [BP].LDR_EndReg ; Get End Register + + 0687 2B D8 sub BX, AX ; BX = # of DAC registers -1 + 0689 43 inc BX ; BX = # of DAC registers + 068A 8B CB mov CX, BX ; CX = # of DAC registers + 068C 03 CB add CX, BX ; CX = " " * 2 + 068E 03 CB add CX, BX ; CX = " " * 3 + 0690 FC cld ; Block OUTs forward + 0691 EE out DX, AL ; set up correct register # + + ; Load a block of DAC Registers + + 0692 BA 03C9 mov DX, PEL_DATA_REG ; Dac Data Register + + 0695 F3/ 6E rep outsb ; block set DAC registers + + POPx SI, DS, BP ; Restore Registers + 0697 5E 1 POP SI ; Restore R1 + 0698 1F 2 POP DS ; Restore R1 + 0699 5D 3 POP BP ; Restore R1 + 069A CA 000A ret 10 ; Exit & Clean Up Stack + + 069D LOAD_DAC_REGISTERS ENDP + + + ;==================================================== + ;READ_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%) + ;==================================================== + ; + ; Reads a Block of Vga Palette Registers + ; + ; ENTRY: PalData = Far Pointer to block to store palette data + ; StartReg = First Register # in range to read (0-255) + ; EndReg = Last Register # in Range to read (0-255) + ; + ; EXIT: No meaningful values returned + ; + ; NOTES: PalData is a linear array of 3 byte Palette values + ; in the order: Red (0-63), Green (0-63), Blue (0-63) + ; + + 0012 RDR_STACK STRUC + 0000 0000 0000 0000 DW ?x3 ; BP, ES, DI + 0006 00000000 DD ? ; Caller + 000A 00 00 RDR_EndReg DB ?,? ; Last Register # + 000C 00 00 RDR_StartReg DB ?,? ; First Register # + 000E 00000000 RDR_PalData DD ? ; Far Ptr to Palette Data + RDR_STACK ENDS + + PUBLIC READ_DAC_REGISTERS + + Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 +modex.asm Page 8 - 1 + + + 069D READ_DAC_REGISTERS PROC FAR + + PUSHx BP, ES, DI ; Save Registers + 069D 55 1 PUSH BP ; Save R1 + 069E 06 2 PUSH ES ; Save R1 + 069F 57 3 PUSH DI ; Save R1 + 06A0 8B EC mov BP, SP ; Set up Stack Frame + + ; Determine register #'s, size to copy, etc + + 06A2 C4 7E 0E les DI, [BP].RDR_PalData ; ES:DI -> Palette Buffer + 06A5 BA 03C7 mov DX, DAC_READ_ADDR ; DAC register # selector + + CLR AX, BX ; Clear for byte loads + 06A8 33 C0 1 XOR AX, AX ; Set Register = 0 + 06AA 33 DB 2 XOR BX, BX ; Set Register = 0 + 06AC 8A 46 0C mov AL, [BP].RDR_StartReg ; Get Start Register + 06AF 8A 5E 0A mov BL, [BP].RDR_EndReg ; Get End Register + + 06B2 2B D8 sub BX, AX ; BX = # of DAC registers -1 + 06B4 43 inc BX ; BX = # of DAC registers + 06B5 8B CB mov CX, BX ; CX = # of DAC registers + 06B7 03 CB add CX, BX ; CX = " " * 2 + 06B9 03 CB add CX, BX ; CX = " " * 3 + 06BB FC cld ; Block INs forward + + ; Read a block of DAC Registers + + 06BC EE out DX, AL ; set up correct register # + 06BD BA 03C9 mov DX, PEL_DATA_REG ; Dac Data Register + + 06C0 F3/ 6C rep insb ; block read DAC registers + + POPx DI, ES, BP ; Restore Registers + + 06C2 5F 1 POP DI ; Restore R1 + 06C3 07 2 POP ES ; Restore R1 + 06C4 5D 3 POP BP ; Restore R1 + 06C5 CA 0008 ret 8 ; Exit & Clean Up Stack + + 06C8 READ_DAC_REGISTERS ENDP + + + ; ===== PAGE FLIPPING AND SCROLLING ROUTINES ===== + + ;========================= + ;SET_ACTIVE_PAGE (PageNo%) + ;========================= + ; + ; Sets the active display Page to be used for future drawing + ; + ; ENTRY: PageNo = Display Page to make active + ; (values: 0 to Number of Pages - 1) + ; + ; EXIT: No meaningful values returned + ; + + 0008 SAP_STACK STRUC + 0000 0000 DW ? ; BP + 0002 00000000 DD ? ; Caller + 0006 0000 SAP_Page DW ? ; Page # for Drawing + SAP_STACK ENDS + + PUBLIC SET_ACTIVE_PAGE + + 06C8 SET_ACTIVE_PAGE PROC FAR + + 06C8 55 PUSH BP ; Preserve Registers + 06C9 8B EC MOV BP, SP ; Set up Stack Frame + + 06CB 8B 5E 06 MOV BX, [BP].SAP_Page ; Get Desired Page # + 06CE 3B 1E 0004 R CMP BX, LAST_PAGE ; Is Page # Valid? + 06D2 73 0D JAE @SAP_Exit ; IF Not, Do Nothing + + 06D4 89 1E 0012 R MOV ACTIVE_PAGE, BX ; Set Active Page # + + 06D8 D1 E3 SHL BX, 1 ; Scale Page # to Word + 06DA 8B 87 0006 R MOV AX, PAGE_ADDR[BX] ; Get offset to Page + + 06DE A3 0014 R MOV CURRENT_PAGE, AX ; And set for future LES's + + 06E1 @SAP_Exit: + 06E1 5D POP BP ; Restore Registers + 06E2 CA 0002 RET 2 ; Exit and Clean up Stack + + 06E5 SET_ACTIVE_PAGE ENDP + + + ;================ + ;GET_ACTIVE_PAGE% + ;================ + ; + ; Returns the Video Page # currently used for Drawing + ; + ; ENTRY: No Parameters are passed + ; + ; EXIT: AX = Current Video Page used for Drawing + ; + + PUBLIC GET_ACTIVE_PAGE + + 06E5 GET_ACTIVE_PAGE PROC FAR + + 06E5 A1 0012 R MOV AX, ACTIVE_PAGE ; Get Active Page # + 06E8 CB RET ; Exit and Clean up Stack + + 06E9 GET_ACTIVE_PAGE ENDP + + + ;=============================== + ;SET_DISPLAY_PAGE (DisplayPage%) + ;=============================== + ; + ; Sets the currently visible display page. + ; When called this routine syncronizes the display + ; to the vertical blank. + ; + ; ENTRY: PageNo = Display Page to show on the screen + ; (values: 0 to Number of Pages - 1) + ; + ; EXIT: No meaningful values returned + ; + + 0008 SDP_STACK STRUC + 0000 0000 DW ? ; BP + 0002 00000000 DD ? ; Caller + 0006 0000 SDP_Page DW ? ; Page # to Display... + SDP_STACK ENDS + + PUBLIC SET_DISPLAY_PAGE + + 06E9 SET_DISPLAY_PAGE PROC FAR + + 06E9 55 PUSH BP ; Preserve Registers + 06EA 8B EC MOV BP, SP ; Set up Stack Frame + + 06EC 8B 5E 06 MOV BX, [BP].SDP_Page ; Get Desired Page # + 06EF 3B 1E 0004 R CMP BX, LAST_PAGE ; Is Page # Valid? + 06F3 73 2B JAE @SDP_Exit ; IF Not, Do Nothing + + 06F5 89 1E 0010 R MOV DISPLAY_PAGE, BX ; Set Display Page # + + 06F9 D1 E3 SHL BX, 1 ; Scale Page # to Word + 06FB 8B 8F 0006 R MOV CX, PAGE_ADDR[BX] ; Get offset in memory to Page + 06FF 03 0E 001C R ADD CX, CURRENT_MOFFSET ; Adjust for any scrolling + + ; Wait if we are currently in a Vertical Retrace + + 0703 BA 03DA MOV DX, INPUT_1 ; Input Status #1 Register + + 0706 @DP_WAIT0: + 0706 EC IN AL, DX ; Get VGA status + 0707 24 08 AND AL, VERT_RETRACE ; In Display mode yet? + 0709 75 FB JNZ @DP_WAIT0 ; If Not, wait for it + + ; Set the Start Display Address to the new page + + 070B BA 03D4 MOV DX, CRTC_Index ; We Change the VGA Sequencer + + 070E B0 0D MOV AL, START_DISP_LO ; Display Start Low Register + 0710 8A E1 MOV AH, CL ; Low 8 Bits of Start Addr + 0712 EF OUT DX, AX ; Set Display Addr Low + + 0713 B0 0C MOV AL, START_DISP_HI ; Display Start High Register + 0715 8A E5 MOV AH, CH ; High 8 Bits of Start Addr + 0717 EF OUT DX, AX ; Set Display Addr High + + ; Wait for a Vertical Retrace to smooth out things + + 0718 BA 03DA MOV DX, INPUT_1 ; Input Status #1 Register + + 071B @DP_WAIT1: + 071B EC IN AL, DX ; Get VGA status + 071C 24 08 AND AL, VERT_RETRACE ; Vertical Retrace Start? + 071E 74 FB JZ @DP_WAIT1 ; If Not, wait for it + + ; Now Set Display Starting Address + + + 0720 @SDP_Exit: + 0720 5D POP BP ; Restore Registers + 0721 CA 0002 RET 2 ; Exit and Clean up Stack + + 0724 SET_DISPLAY_PAGE ENDP + + + ;================= + ;GET_DISPLAY_PAGE% + ;================= + ; + ; Returns the Video Page # currently displayed + ; + ; ENTRY: No Parameters are passed + ; + ; EXIT: AX = Current Video Page being displayed + ; + + PUBLIC GET_DISPLAY_PAGE + + 0724 GET_DISPLAY_PAGE PROC FAR + + 0724 A1 0010 R MOV AX, DISPLAY_PAGE ; Get Display Page # + 0727 CB RET ; Exit & Clean Up Stack + + 0728 GET_DISPLAY_PAGE ENDP + + + ;======================================= + ;SET_WINDOW (DisplayPage%, Xpos%, Ypos%) + ;======================================= + ; + ; Since a Logical Screen can be larger than the Physical + ; Screen, Scrolling is possible. This routine sets the + ; Upper Left Corner of the Screen to the specified Pixel. + ; Also Sets the Display page to simplify combined page + ; flipping and scrolling. When called this routine + ; syncronizes the display to the vertical blank. + ; + ; ENTRY: DisplayPage = Display Page to show on the screen + ; Xpos = # of pixels to shift screen right + ; Ypos = # of lines to shift screen down + ; + ; EXIT: No meaningful values returned + ; + + 000C SW_STACK STRUC + 0000 0000 DW ? ; BP + 0002 00000000 DD ? ; Caller + 0006 0000 SW_Ypos DW ? ; Y pos of UL Screen Corner + 0008 0000 SW_Xpos DW ? ; X pos of UL Screen Corner + 000A 0000 SW_Page DW ? ; (new) Display Page + SW_STACK ENDS + + PUBLIC SET_WINDOW + + 0728 SET_WINDOW PROC FAR + + 0728 55 PUSH BP ; Preserve Registers + 0729 8B EC MOV BP, SP ; Set up Stack Frame + + ; Check if our Scroll Offsets are Valid + + 072B 8B 5E 0A MOV BX, [BP].SW_Page ; Get Desired Page # + 072E 3B 1E 0004 R CMP BX, LAST_PAGE ; Is Page # Valid? + 0732 73 55 JAE @SW_Exit ; IF Not, Do Nothing + + 0734 8B 46 06 MOV AX, [BP].SW_Ypos ; Get Desired Y Offset + 0737 3B 06 0020 R CMP AX, MAX_YOFFSET ; Is it Within Limits? + 073B 77 4C JA @SW_Exit ; if not, exit + + 073D 8B 4E 08 MOV CX, [BP].SW_Xpos ; Get Desired X Offset + 0740 3B 0E 001E R CMP CX, MAX_XOFFSET ; Is it Within Limits? + Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 +modex.asm Page 9 - 1 + + + 0744 77 43 JA @SW_Exit ; if not, exit + + ; Compute proper Display start address to use + + 0746 F7 26 0000 R MUL SCREEN_WIDTH ; AX = YOffset * Line Width + 074A C1 E9 02 SHR CX, 2 ; CX / 4 = Bytes into Line + 074D 03 C1 ADD AX, CX ; AX = Offset of Upper Left Pixel + + 074F A3 001C R MOV CURRENT_MOFFSET, AX ; Save Offset Info + + 0752 89 1E 0010 R MOV DISPLAY_PAGE, BX ; Set Current Page # + 0756 D1 E3 SHL BX, 1 ; Scale Page # to Word + 0758 03 87 0006 R ADD AX, PAGE_ADDR[BX] ; Get offset in VGA to Page + 075C 8B D8 MOV BX, AX ; BX = Desired Display Start + + 075E BA 03DA MOV DX, INPUT_1 ; Input Status #1 Register + + ; Wait if we are currently in a Vertical Retrace + + 0761 @SW_WAIT0: + 0761 EC IN AL, DX ; Get VGA status + 0762 24 08 AND AL, VERT_RETRACE ; In Display mode yet? + 0764 75 FB JNZ @SW_WAIT0 ; If Not, wait for it + + ; Set the Start Display Address to the new window + + 0766 BA 03D4 MOV DX, CRTC_Index ; We Change the VGA Sequencer + 0769 B0 0D MOV AL, START_DISP_LO ; Display Start Low Register + 076B 8A E3 MOV AH, BL ; Low 8 Bits of Start Addr + 076D EF OUT DX, AX ; Set Display Addr Low + + 076E B0 0C MOV AL, START_DISP_HI ; Display Start High Register + 0770 8A E7 MOV AH, BH ; High 8 Bits of Start Addr + 0772 EF OUT DX, AX ; Set Display Addr High + + ; Wait for a Vertical Retrace to smooth out things + + 0773 BA 03DA MOV DX, INPUT_1 ; Input Status #1 Register + + 0776 @SW_WAIT1: + 0776 EC IN AL, DX ; Get VGA status + 0777 24 08 AND AL, VERT_RETRACE ; Vertical Retrace Start? + 0779 74 FB JZ @SW_WAIT1 ; If Not, wait for it + + ; Now Set the Horizontal Pixel Pan values + + OUT_8 ATTRIB_Ctrl, PIXEL_PAN_REG ; Select Pixel Pan Register + 077B BA 03C0 1 MOV DX, ATTRIB_Ctrl ; then Select Register + 077E B0 33 1 MOV AL, PIXEL_PAN_REG ; then Get Data Value + 0780 EE 1 OUT DX, AL ; Set I/O Register + + 0781 8B 46 08 MOV AX, [BP].SW_Xpos ; Get Desired X Offset + 0784 24 03 AND AL, 03 ; Get # of Pixels to Pan (0-3) + 0786 D0 E0 SHL AL, 1 ; Shift for 256 Color Mode + 0788 EE OUT DX, AL ; Fine tune the display! + + 0789 @SW_Exit: + 0789 5D POP BP ; Restore Saved Registers + 078A CA 0006 RET 6 ; Exit and Clean up Stack + + 078D SET_WINDOW ENDP + + + ;============= + ;GET_X_OFFSET% + ;============= + ; + ; Returns the X coordinate of the Pixel currently display + ; in the upper left corner of the display + ; + ; ENTRY: No Parameters are passed + ; + ; EXIT: AX = Current Horizontal Scroll Offset + ; + + PUBLIC GET_X_OFFSET + + 078D GET_X_OFFSET PROC FAR + + 078D A1 0018 R MOV AX, CURRENT_XOFFSET ; Get current horz offset + 0790 CB RET ; Exit & Clean Up Stack + + 0791 GET_X_OFFSET ENDP + + + ;============= + ;GET_Y_OFFSET% + ;============= + ; + ; Returns the Y coordinate of the Pixel currently display + ; in the upper left corner of the display + ; + ; ENTRY: No Parameters are passed + ; + ; EXIT: AX = Current Vertical Scroll Offset + ; + + PUBLIC GET_Y_OFFSET + + 0791 GET_Y_OFFSET PROC FAR + + 0791 A1 001A R MOV AX, CURRENT_YOFFSET ; Get current vertical offset + 0794 CB RET ; Exit & Clean Up Stack + + 0795 GET_Y_OFFSET ENDP + + + ;============ + ;SYNC_DISPLAY + ;============ + ; + ; Pauses the computer until the next Vertical Retrace starts + ; + ; ENTRY: No Parameters are passed + ; + ; EXIT: No meaningful values returned + ; + + PUBLIC SYNC_DISPLAY + + 0795 SYNC_DISPLAY PROC FAR + + 0795 BA 03DA MOV DX, INPUT_1 ; Input Status #1 Register + + ; Wait for any current retrace to end + + 0798 @SD_WAIT0: + 0798 EC IN AL, DX ; Get VGA status + 0799 24 08 AND AL, VERT_RETRACE ; In Display mode yet? + 079B 75 FB JNZ @SD_WAIT0 ; If Not, wait for it + + ; Wait for the start of the next vertical retrace + + 079D @SD_WAIT1: + 079D EC IN AL, DX ; Get VGA status + 079E 24 08 AND AL, VERT_RETRACE ; Vertical Retrace Start? + 07A0 74 FB JZ @SD_WAIT1 ; If Not, wait for it + + 07A2 CB RET ; Exit & Clean Up Stack + + 07A3 SYNC_DISPLAY ENDP + + + ; ===== TEXT DISPLAY ROUTINES ===== + + ;================================================== + ;GPRINTC (CharNum%, Xpos%, Ypos%, ColorF%, ColorB%) + ;================================================== + ; + ; Draws an ASCII Text Character using the currently selected + ; 8x8 font on the active display page. It would be a simple + ; exercise to make this routine process variable height fonts. + ; + ; ENTRY: CharNum = ASCII character # to draw + ; Xpos = X position to draw Character at + ; Ypos = Y position of to draw Character at + ; ColorF = Color to draw text character in + ; ColorB = Color to set background to + ; + ; EXIT: No meaningful values returned + ; + + 001E GPC_STACK STRUC + 0000 0000 GPC_Width DW ? ; Screen Width-1 + 0002 00 00 GPC_Lines DB ?,? ; Scan lines to Decode + 0004 0000 GPC_T_SETS DW ? ; Saved Charset Segment + 0006 0000 GPC_T_SETO DW ? ; Saved Charset Offset + 0008 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP + 0000 + 0010 00000000 DD ? ; Caller + 0014 00 00 GPC_ColorB DB ?,? ; Background Color + 0016 00 00 GPC_ColorF DB ?,? ; Text Color + 0018 0000 GPC_Ypos DW ? ; Y Position to Print at + 001A 0000 GPC_Xpos DW ? ; X position to Print at + 001C 00 00 GPC_Char DB ?,? ; Character to Print + GPC_STACK ENDS + + PUBLIC GPRINTC + + 07A3 GPRINTC PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 07A3 55 1 PUSH BP ; Save R1 + 07A4 1E 2 PUSH DS ; Save R1 + 07A5 56 3 PUSH SI ; Save R1 + 07A6 57 4 PUSH DI ; Save R1 + 07A7 83 EC 08 SUB SP, 8 ; Allocate WorkSpace on Stack + 07AA 8B EC MOV BP, SP ; Set up Stack Frame + + 07AC C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page + + 07B0 A1 0000 R MOV AX, SCREEN_WIDTH ; Get Logical Line Width + 07B3 8B D8 MOV BX, AX ; BX = Screen Width + 07B5 4B DEC BX ; = Screen Width-1 + 07B6 89 5E 00 MOV [BP].GPC_Width, BX ; Save for later use + + 07B9 F7 66 18 MUL [BP].GPC_Ypos ; Start of Line = Ypos * Width + 07BC 03 F8 ADD DI, AX ; DI -> Start of Line Ypos + + 07BE 8B 46 1A MOV AX, [BP].GPC_Xpos ; Get Xpos of Character + 07C1 8B C8 MOV CX, AX ; Save Copy of Xpos + 07C3 C1 E8 02 SHR AX, 2 ; Bytes into Line = Xpos/4 + 07C6 03 F8 ADD DI, AX ; DI -> (Xpos, Ypos) + + ;Get Source ADDR of Character Bit Map & Save + + 07C8 8A 46 1C MOV AL, [BP].GPC_Char ; Get Character # + 07CB A8 80 TEST AL, 080h ; Is Hi Bit Set? + 07CD 74 0C JZ @GPC_LowChar ; Nope, use low char set ptr + + 07CF 24 7F AND AL, 07Fh ; Mask Out Hi Bit + 07D1 8B 1E 0026 R MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset + 07D5 8B 16 0028 R MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment + 07D9 EB 08 JMP s @GPC_Set_Char ; Go Setup Character Ptr + + 07DB @GPC_LowChar: + + 07DB 8B 1E 0022 R MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset + 07DF 8B 16 0024 R MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment + + 07E3 @GPC_Set_Char: + 07E3 89 56 04 MOV [BP].GPC_T_SETS, DX ; Save Segment on Stack + + 07E6 B4 00 MOV AH, 0 ; Valid #'s are 0..127 + 07E8 C1 E0 03 SHL AX, 3 ; * 8 Bytes Per Bitmap + 07EB 03 D8 ADD BX, AX ; BX = Offset of Selected char + 07ED 89 5E 06 MOV [BP].GPC_T_SETO, BX ; Save Offset on Stack + + 07F0 83 E1 03 AND CX, PLANE_BITS ; Get Plane # + 07F3 B5 0F MOV CH, ALL_PLANES ; Get Initial Plane mask + 07F5 D2 E5 SHL CH, CL ; And shift into position + 07F7 80 E5 0F AND CH, ALL_PLANES ; And mask to lower nibble + + 07FA B0 04 MOV AL, 04 ; 4-Plane # = # of initial + 07FC 2A C1 SUB AL, CL ; shifts to align bit mask + 07FE 8A C8 MOV CL, AL ; Shift Count for SHL + + ;Get segment of character map + + OUT_8 SC_Index, MAP_MASK ; Setup Plane selections + 0800 BA 03C4 1 MOV DX, SC_Index ; then Select Register + 0803 B0 02 1 MOV AL, MAP_MASK ; then Get Data Value + 0805 EE 1 OUT DX, AL ; Set I/O Register + 0806 42 INC DX ; DX -> SC_Data + + 0807 B0 08 MOV AL, 08 ; 8 Lines to Process + 0809 88 46 02 MOV [BP].GPC_Lines, AL ; Save on Stack + + 080C 8E 5E 04 MOV DS, [BP].GPC_T_SETS ; Point to character set + + 080F @GPC_DECODE_CHAR_BYTE: + Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 +modex.asm Page 10 - 1 + + + + 080F 8B 76 06 MOV SI, [BP].GPC_T_SETO ; Get DS:SI = String + + 0812 8A 3C MOV BH, [SI] ; Get Bit Map + 0814 46 INC SI ; Point to Next Line + 0815 89 76 06 MOV [BP].GPC_T_SETO, SI ; And save new Pointer... + + CLR AX ; Clear AX + 0818 33 C0 1 XOR AX, AX ; Set Register = 0 + + CLR BL ; Clear BL + 081A 32 DB 1 XOR BL, BL ; Set Register = 0 + 081C D3 C3 ROL BX, CL ; BL holds left edge bits + 081E 8B F3 MOV SI, BX ; Use as Table Index + 0820 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits + 0823 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL + 0828 74 07 JZ @GPC_NO_LEFT1BITS ; Skip if No Pixels to set + + 082A 8A 66 16 MOV AH, [BP].GPC_ColorF ; Get Foreground Color + 082D EE OUT DX, AL ; Set up Screen Mask + 082E 26: 88 25 MOV ES:[DI], AH ; Write Foreground color + + 0831 @GPC_NO_LEFT1BITS: + 0831 32 C5 XOR AL, CH ; Invert mask for Background + 0833 74 07 JZ @GPC_NO_LEFT0BITS ; Hey, no need for this + + 0835 8A 66 14 MOV AH, [BP].GPC_ColorB ; Get background Color + 0838 EE OUT DX, AL ; Set up Screen Mask + 0839 26: 88 25 MOV ES:[DI], AH ; Write Foreground color + + ;Now Do Middle/Last Band + + 083C @GPC_NO_LEFT0BITS: + 083C 47 INC DI ; Point to next Byte + 083D C1 C3 04 ROL BX, 4 ; Shift 4 bits + + 0840 8B F3 MOV SI, BX ; Make Lookup Pointer + 0842 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits + 0845 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL + 084A 74 07 JZ @GPC_NO_MIDDLE1BITS ; Skip if no pixels to set + + 084C 8A 66 16 MOV AH, [BP].GPC_ColorF ; Get Foreground Color + 084F EE OUT DX, AL ; Set up Screen Mask + 0850 26: 88 25 MOV ES:[DI], AH ; Write Foreground color + + 0853 @GPC_NO_MIDDLE1BITS: + 0853 34 0F XOR AL, ALL_PLANES ; Invert mask for Background + 0855 74 07 JZ @GPC_NO_MIDDLE0BITS ; Hey, no need for this + + 0857 8A 66 14 MOV AH, [BP].GPC_ColorB ; Get background Color + 085A EE OUT DX, AL ; Set up Screen Mask + 085B 26: 88 25 MOV ES:[DI], AH ; Write Foreground color + + 085E @GPC_NO_MIDDLE0BITS: + 085E 80 F5 0F XOR CH, ALL_PLANES ; Invert Clip Mask + 0861 80 F9 04 CMP CL, 4 ; Aligned by 4? + 0864 74 23 JZ @GPC_NEXT_LINE ; If so, Exit now.. + + 0866 47 INC DI ; Point to next Byte + 0867 C1 C3 04 ROL BX, 4 ; Shift 4 bits + + 086A 8B F3 MOV SI, BX ; Make Lookup Pointer + 086C 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits + 086F 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL + 0874 74 07 JZ @GPC_NO_RIGHT1BITS ; Skip if No Pixels to set + + 0876 8A 66 16 MOV AH, [BP].GPC_ColorF ; Get Foreground Color + 0879 EE OUT DX, AL ; Set up Screen Mask + 087A 26: 88 25 MOV ES:[DI], AH ; Write Foreground color + + 087D @GPC_NO_RIGHT1BITS: + + 087D 32 C5 XOR AL, CH ; Invert mask for Background + 087F 74 07 JZ @GPC_NO_RIGHT0BITS ; Hey, no need for this + + 0881 8A 66 14 MOV AH, [BP].GPC_ColorB ; Get background Color + 0884 EE OUT DX, AL ; Set up Screen Mask + 0885 26: 88 25 MOV ES:[DI], AH ; Write Foreground color + + 0888 @GPC_NO_RIGHT0BITS: + 0888 4F DEC DI ; Adjust for Next Line Advance + + 0889 @GPC_NEXT_LINE: + 0889 03 7E 00 ADD DI, [BP].GPC_Width ; Point to Next Line + 088C 80 F5 0F XOR CH, CHAR_BITS ; Flip the Clip mask back + + 088F FE 4E 02 DEC [BP].GPC_Lines ; Count Down Lines + 0892 74 03 JZ @GPC_EXIT ; Ok... Done! + + 0894 E9 FF78 JMP @GPC_DECODE_CHAR_BYTE ; Again! Hey! + + 0897 @GPC_EXIT: + 0897 83 C4 08 ADD SP, 08 ; Deallocate stack workspace + POPx DI, SI, DS, BP ; Restore Saved Registers + 089A 5F 1 POP DI ; Restore R1 + 089B 5E 2 POP SI ; Restore R1 + 089C 1F 3 POP DS ; Restore R1 + 089D 5D 4 POP BP ; Restore R1 + 089E CA 000A RET 10 ; Exit and Clean up Stack + + 08A1 GPRINTC ENDP + + + ;========================================== + ;TGPRINTC (CharNum%, Xpos%, Ypos%, ColorF%) + ;========================================== + ; + ; Transparently draws an ASCII Text Character using the + ; currently selected 8x8 font on the active display page. + ; + ; ENTRY: CharNum = ASCII character # to draw + ; Xpos = X position to draw Character at + ; Ypos = Y position of to draw Character at + ; ColorF = Color to draw text character in + ; + ; EXIT: No meaningful values returned + ; + + 001C TGP_STACK STRUC + 0000 0000 TGP_Width DW ? ; Screen Width-1 + 0002 00 00 TGP_Lines DB ?,? ; Scan lines to Decode + 0004 0000 TGP_T_SETS DW ? ; Saved Charset Segment + 0006 0000 TGP_T_SETO DW ? ; Saved Charset Offset + 0008 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP + 0000 + 0010 00000000 DD ? ; Caller + 0014 00 00 TGP_ColorF DB ?,? ; Text Color + 0016 0000 TGP_Ypos DW ? ; Y Position to Print at + 0018 0000 TGP_Xpos DW ? ; X position to Print at + 001A 00 00 TGP_Char DB ?,? ; Character to Print + TGP_STACK ENDS + + PUBLIC TGPRINTC + + 08A1 TGPRINTC PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 08A1 55 1 PUSH BP ; Save R1 + 08A2 1E 2 PUSH DS ; Save R1 + 08A3 56 3 PUSH SI ; Save R1 + 08A4 57 4 PUSH DI ; Save R1 + 08A5 83 EC 08 SUB SP, 8 ; Allocate WorkSpace on Stack + 08A8 8B EC MOV BP, SP ; Set up Stack Frame + + 08AA C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page + + 08AE A1 0000 R MOV AX, SCREEN_WIDTH ; Get Logical Line Width + 08B1 8B D8 MOV BX, AX ; BX = Screen Width + 08B3 4B DEC BX ; = Screen Width-1 + 08B4 89 5E 00 MOV [BP].TGP_Width, BX ; Save for later use + + 08B7 F7 66 16 MUL [BP].TGP_Ypos ; Start of Line = Ypos * Width + 08BA 03 F8 ADD DI, AX ; DI -> Start of Line Ypos + + 08BC 8B 46 18 MOV AX, [BP].TGP_Xpos ; Get Xpos of Character + 08BF 8B C8 MOV CX, AX ; Save Copy of Xpos + 08C1 C1 E8 02 SHR AX, 2 ; Bytes into Line = Xpos/4 + 08C4 03 F8 ADD DI, AX ; DI -> (Xpos, Ypos) + + ;Get Source ADDR of Character Bit Map & Save + + 08C6 8A 46 1A MOV AL, [BP].TGP_Char ; Get Character # + 08C9 A8 80 TEST AL, 080h ; Is Hi Bit Set? + 08CB 74 0C JZ @TGP_LowChar ; Nope, use low char set ptr + + 08CD 24 7F AND AL, 07Fh ; Mask Out Hi Bit + 08CF 8B 1E 0026 R MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset + 08D3 8B 16 0028 R MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment + 08D7 EB 08 JMP s @TGP_Set_Char ; Go Setup Character Ptr + + 08D9 @TGP_LowChar: + + 08D9 8B 1E 0022 R MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset + 08DD 8B 16 0024 R MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment + + 08E1 @TGP_Set_Char: + 08E1 89 56 04 MOV [BP].TGP_T_SETS, DX ; Save Segment on Stack + + 08E4 B4 00 MOV AH, 0 ; Valid #'s are 0..127 + 08E6 C1 E0 03 SHL AX, 3 ; * 8 Bytes Per Bitmap + 08E9 03 D8 ADD BX, AX ; BX = Offset of Selected char + 08EB 89 5E 06 MOV [BP].TGP_T_SETO, BX ; Save Offset on Stack + + 08EE 83 E1 03 AND CX, PLANE_BITS ; Get Plane # + 08F1 B5 0F MOV CH, ALL_PLANES ; Get Initial Plane mask + 08F3 D2 E5 SHL CH, CL ; And shift into position + 08F5 80 E5 0F AND CH, ALL_PLANES ; And mask to lower nibble + + 08F8 B0 04 MOV AL, 04 ; 4-Plane # = # of initial + 08FA 2A C1 SUB AL, CL ; shifts to align bit mask + 08FC 8A C8 MOV CL, AL ; Shift Count for SHL + + ;Get segment of character map + + OUT_8 SC_Index, MAP_MASK ; Setup Plane selections + 08FE BA 03C4 1 MOV DX, SC_Index ; then Select Register + 0901 B0 02 1 MOV AL, MAP_MASK ; then Get Data Value + 0903 EE 1 OUT DX, AL ; Set I/O Register + 0904 42 INC DX ; DX -> SC_Data + + 0905 B0 08 MOV AL, 08 ; 8 Lines to Process + 0907 88 46 02 MOV [BP].TGP_Lines, AL ; Save on Stack + + 090A 8E 5E 04 MOV DS, [BP].TGP_T_SETS ; Point to character set + + 090D @TGP_DECODE_CHAR_BYTE: + + 090D 8B 76 06 MOV SI, [BP].TGP_T_SETO ; Get DS:SI = String + + 0910 8A 3C MOV BH, [SI] ; Get Bit Map + 0912 46 INC SI ; Point to Next Line + 0913 89 76 06 MOV [BP].TGP_T_SETO, SI ; And save new Pointer... + + 0916 8A 66 14 MOV AH, [BP].TGP_ColorF ; Get Foreground Color + + CLR BL ; Clear BL + 0919 32 DB 1 XOR BL, BL ; Set Register = 0 + 091B D3 C3 ROL BX, CL ; BL holds left edge bits + 091D 8B F3 MOV SI, BX ; Use as Table Index + 091F 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits + 0922 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL + 0927 74 04 JZ @TGP_NO_LEFT1BITS ; Skip if No Pixels to set + + 0929 EE OUT DX, AL ; Set up Screen Mask + 092A 26: 88 25 MOV ES:[DI], AH ; Write Foreground color + + ;Now Do Middle/Last Band + + 092D @TGP_NO_LEFT1BITS: + + 092D 47 INC DI ; Point to next Byte + 092E C1 C3 04 ROL BX, 4 ; Shift 4 bits + + 0931 8B F3 MOV SI, BX ; Make Lookup Pointer + 0933 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits + 0936 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL + 093B 74 04 JZ @TGP_NO_MIDDLE1BITS ; Skip if no pixels to set + + 093D EE OUT DX, AL ; Set up Screen Mask + 093E 26: 88 25 MOV ES:[DI], AH ; Write Foreground color + + 0941 @TGP_NO_MIDDLE1BITS: + 0941 80 F5 0F XOR CH, ALL_PLANES ; Invert Clip Mask + 0944 80 F9 04 CMP CL, 4 ; Aligned by 4? + 0947 74 15 JZ @TGP_NEXT_LINE ; If so, Exit now.. + + 0949 47 INC DI ; Point to next Byte + 094A C1 C3 04 ROL BX, 4 ; Shift 4 bits + + 094D 8B F3 MOV SI, BX ; Make Lookup Pointer + 094F 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits + Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 +modex.asm Page 11 - 1 + + + 0952 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL + 0957 74 04 JZ @TGP_NO_RIGHT1BITS ; Skip if No Pixels to set + + 0959 EE OUT DX, AL ; Set up Screen Mask + 095A 26: 88 25 MOV ES:[DI], AH ; Write Foreground color + + 095D @TGP_NO_RIGHT1BITS: + + 095D 4F DEC DI ; Adjust for Next Line Advance + + 095E @TGP_NEXT_LINE: + 095E 03 7E 00 ADD DI, [BP].TGP_Width ; Point to Next Line + 0961 80 F5 0F XOR CH, CHAR_BITS ; Flip the Clip mask back + + 0964 FE 4E 02 DEC [BP].TGP_Lines ; Count Down Lines + 0967 74 02 JZ @TGP_EXIT ; Ok... Done! + + 0969 EB A2 JMP @TGP_DECODE_CHAR_BYTE ; Again! Hey! + + 096B @TGP_EXIT: + 096B 83 C4 08 ADD SP, 08 ; Deallocate stack workspace + POPx DI, SI, DS, BP ; Restore Saved Registers + 096E 5F 1 POP DI ; Restore R1 + 096F 5E 2 POP SI ; Restore R1 + 0970 1F 3 POP DS ; Restore R1 + 0971 5D 4 POP BP ; Restore R1 + 0972 CA 0008 RET 8 ; Exit and Clean up Stack + + 0975 TGPRINTC ENDP + + + ;=============================================================== + ;PRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%) + ;=============================================================== + ; + ; Routine to quickly Print a null terminated ASCII string on the + ; active display page up to a maximum length. + ; + ; ENTRY: String = Far Pointer to ASCII string to print + ; MaxLen = # of characters to print if no null found + ; Xpos = X position to draw Text at + ; Ypos = Y position of to draw Text at + ; ColorF = Color to draw text in + ; ColorB = Color to set background to + ; + ; EXIT: No meaningful values returned + ; + + 001A PS_STACK STRUC + 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP + 0000 + 0008 00000000 DD ? ; Caller + 000C 0000 PS_ColorB DW ? ; Background Color + 000E 0000 PS_ColorF DW ? ; Text Color + 0010 0000 PS_Ypos DW ? ; Y Position to Print at + 0012 0000 PS_Xpos DW ? ; X position to Print at + 0014 0000 PS_Len DW ? ; Maximum Length of string to print + 0016 0000 0000 PS_Text DW ?,? ; Far Ptr to Text String + PS_STACK ENDS + + PUBLIC PRINT_STR + + 0975 PRINT_STR PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 0975 55 1 PUSH BP ; Save R1 + 0976 1E 2 PUSH DS ; Save R1 + 0977 56 3 PUSH SI ; Save R1 + 0978 57 4 PUSH DI ; Save R1 + 0979 8B EC MOV BP, SP ; Set up Stack Frame + + 097B @PS_Print_It: + + 097B 8B 4E 14 MOV CX, [BP].PS_Len ; Get Remaining text Length + 097E E3 2F JCXZ @PS_Exit ; Exit when out of text + + 0980 C4 7E 16 LES DI, d [BP].PS_Text ; ES:DI -> Current Char in Text + 0983 26: 8A 05 MOV AL, ES:[DI] ; AL = Text Character + 0986 25 00FF AND AX, 00FFh ; Clear High Word + 0989 74 24 JZ @PS_Exit ; Exit if null character + + 098B FF 4E 14 DEC [BP].PS_Len ; Remaining Text length-- + 098E FF 46 16 INC [BP].PS_Text ; Point to Next text char + + ; Set up Call to GPRINTC + + 0991 50 PUSH AX ; Set Character Parameter + 0992 8B 5E 12 MOV BX, [BP].PS_Xpos ; Get Xpos + 0995 53 PUSH BX ; Set Xpos Parameter + 0996 83 C3 08 ADD BX, 8 ; Advance 1 Char to Right + 0999 89 5E 12 MOV [BP].PS_Xpos, BX ; Save for next time through + + 099C 8B 5E 10 MOV BX, [BP].PS_Ypos ; Get Ypos + 099F 53 PUSH BX ; Set Ypos Parameter + + 09A0 8B 5E 0E MOV BX, [BP].PS_ColorF ; Get Text Color + 09A3 53 PUSH BX ; Set ColorF Parameter + + 09A4 8B 5E 0C MOV BX, [BP].PS_ColorB ; Get Background Color + 09A7 53 PUSH BX ; Set ColorB Parameter + + 09A8 9A ---- 07A3 R CALL f GPRINTC ; Print Character! + 09AD EB CC JMP s @PS_Print_It ; Process next character + + 09AF @PS_Exit: + POPx DI, SI, DS, BP ; Restore Saved Registers + 09AF 5F 1 POP DI ; Restore R1 + 09B0 5E 2 POP SI ; Restore R1 + 09B1 1F 3 POP DS ; Restore R1 + 09B2 5D 4 POP BP ; Restore R1 + 09B3 CA 000E RET 14 ; Exit and Clean up Stack + + 09B6 PRINT_STR ENDP + + + ;================================================================ + ;TPRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%) + ;================================================================ + ; + ; Routine to quickly transparently Print a null terminated ASCII + ; string on the active display page up to a maximum length. + ; + ; ENTRY: String = Far Pointer to ASCII string to print + ; MaxLen = # of characters to print if no null found + ; Xpos = X position to draw Text at + ; Ypos = Y position of to draw Text at + ; ColorF = Color to draw text in + ; + ; EXIT: No meaningful values returned + ; + + 0018 TPS_STACK STRUC + 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP + 0000 + 0008 00000000 DD ? ; Caller + 000C 0000 TPS_ColorF DW ? ; Text Color + 000E 0000 TPS_Ypos DW ? ; Y Position to Print at + 0010 0000 TPS_Xpos DW ? ; X position to Print at + 0012 0000 TPS_Len DW ? ; Maximum Length of string to print + 0014 0000 0000 TPS_Text DW ?,? ; Far Ptr to Text String + TPS_STACK ENDS + + PUBLIC TPRINT_STR + + 09B6 TPRINT_STR PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 09B6 55 1 PUSH BP ; Save R1 + 09B7 1E 2 PUSH DS ; Save R1 + 09B8 56 3 PUSH SI ; Save R1 + 09B9 57 4 PUSH DI ; Save R1 + 09BA 8B EC MOV BP, SP ; Set up Stack Frame + + 09BC @TPS_Print_It: + + 09BC 8B 4E 12 MOV CX, [BP].TPS_Len ; Get Remaining text Length + 09BF E3 2B JCXZ @TPS_Exit ; Exit when out of text + + 09C1 C4 7E 14 LES DI, d [BP].TPS_Text ; ES:DI -> Current Char in Text + 09C4 26: 8A 05 MOV AL, ES:[DI] ; AL = Text Character + 09C7 25 00FF AND AX, 00FFh ; Clear High Word + 09CA 74 20 JZ @TPS_Exit ; Exit if null character + + 09CC FF 4E 12 DEC [BP].TPS_Len ; Remaining Text length-- + 09CF FF 46 14 INC [BP].TPS_Text ; Point to Next text char + + ; Set up Call to TGPRINTC + + 09D2 50 PUSH AX ; Set Character Parameter + 09D3 8B 5E 10 MOV BX, [BP].TPS_Xpos ; Get Xpos + 09D6 53 PUSH BX ; Set Xpos Parameter + 09D7 83 C3 08 ADD BX, 8 ; Advance 1 Char to Right + 09DA 89 5E 10 MOV [BP].TPS_Xpos, BX ; Save for next time through + + 09DD 8B 5E 0E MOV BX, [BP].TPS_Ypos ; Get Ypos + 09E0 53 PUSH BX ; Set Ypos Parameter + + 09E1 8B 5E 0C MOV BX, [BP].TPS_ColorF ; Get Text Color + 09E4 53 PUSH BX ; Set ColorF Parameter + + 09E5 9A ---- 08A1 R CALL f TGPRINTC ; Print Character! + 09EA EB D0 JMP s @TPS_Print_It ; Process next character + + 09EC @TPS_Exit: + POPx DI, SI, DS, BP ; Restore Saved Registers + 09EC 5F 1 POP DI ; Restore R1 + 09ED 5E 2 POP SI ; Restore R1 + 09EE 1F 3 POP DS ; Restore R1 + 09EF 5D 4 POP BP ; Restore R1 + 09F0 CA 000C RET 12 ; Exit and Clean up Stack + + 09F3 TPRINT_STR ENDP + + + ;=========================================== + ;SET_DISPLAY_FONT(SEG FontData, FontNumber%) + ;=========================================== + ; + ; Allows the user to specify their own font data for + ; wither the lower or upper 128 characters. + ; + ; ENTRY: FontData = Far Pointer to Font Bitmaps + ; FontNumber = Which half of set this is + ; = 0, Lower 128 characters + ; = 1, Upper 128 characters + ; + ; EXIT: No meaningful values returned + ; + + 000C SDF_STACK STRUC + 0000 0000 DW ? ; BP + 0002 00000000 DD ? ; Caller + 0006 0000 SDF_Which DW ? ; Hi Table/Low Table Flag + 0008 00000000 SDF_Font DD ? ; Far Ptr to Font Table + SDF_STACK ENDS + + PUBLIC SET_DISPLAY_FONT + + 09F3 SET_DISPLAY_FONT PROC FAR + + 09F3 55 PUSH BP ; Preserve Registers + 09F4 8B EC MOV BP, SP ; Set up Stack Frame + + 09F6 C4 7E 08 LES DI, [BP].SDF_Font ; Get Far Ptr to Font + + 09F9 BE 0022 R MOV SI, o CHARSET_LOW ; Assume Lower 128 chars + 09FC F7 46 06 0001 TEST [BP].SDF_Which, 1 ; Font #1 selected? + 0A01 74 03 JZ @SDF_Set_Font ; If not, skip ahead + + 0A03 BE 0026 R MOV SI, o CHARSET_HI ; Ah, really it's 128-255 + + 0A06 @SDF_Set_Font: + 0A06 89 3C MOV [SI], DI ; Set Font Pointer Offset + 0A08 8C 44 02 MOV [SI+2], ES ; Set Font Pointer Segment + + 0A0B 5D POP BP ; Restore Registers + 0A0C CA 0006 RET 6 ; We are Done.. Outa here + + 0A0F SET_DISPLAY_FONT ENDP + + + ; ===== BITMAP (SPRITE) DISPLAY ROUTINES ===== + + ;====================================================== + ;DRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%) + ;====================================================== + ; + ; Draws a variable sized Graphics Bitmap such as a + ; picture or an Icon on the current Display Page in + ; Mode X. The Bitmap is stored in a linear byte array + ; corresponding to (0,0) (1,0), (2,0) .. (Width, Height) + Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 +modex.asm Page 12 - 1 + + + ; This is the same linear manner as mode 13h graphics. + ; + ; ENTRY: Image = Far Pointer to Bitmap Data + ; Xpos = X position to Place Upper Left pixel at + ; Ypos = Y position to Place Upper Left pixel at + ; Width = Width of the Bitmap in Pixels + ; Height = Height of the Bitmap in Pixels + ; + ; EXIT: No meaningful values returned + ; + + 0022 DB_STACK STRUC + 0000 0000 DB_LineO DW ? ; Offset to Next Line + 0002 0000 DB_PixCount DW ? ; (Minimum) # of Pixels/Line + 0004 0000 DB_Start DW ? ; Addr of Upper Left Pixel + 0006 0000 DB_PixSkew DW ? ; # of bytes to Adjust EOL + 0008 0000 DB_SkewFlag DW ? ; Extra Pix on Plane Flag + 000A 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP + 0000 + 0012 00000000 DD ? ; Caller + 0016 0000 DB_Height DW ? ; Height of Bitmap in Pixels + 0018 0000 DB_Width DW ? ; Width of Bitmap in Pixels + 001A 0000 DB_Ypos DW ? ; Y position to Draw Bitmap at + 001C 0000 DB_Xpos DW ? ; X position to Draw Bitmap at + 001E 00000000 DB_Image DD ? ; Far Pointer to Graphics Bitmap + DB_STACK ENDS + + PUBLIC DRAW_BITMAP + + 0A0F DRAW_BITMAP PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 0A0F 55 1 PUSH BP ; Save R1 + 0A10 1E 2 PUSH DS ; Save R1 + 0A11 56 3 PUSH SI ; Save R1 + 0A12 57 4 PUSH DI ; Save R1 + 0A13 83 EC 0A SUB SP, 10 ; Allocate workspace + 0A16 8B EC MOV BP, SP ; Set up Stack Frame + + 0A18 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page + 0A1C FC CLD ; Direction Flag = Forward + + 0A1D 8B 46 1A MOV AX, [BP].DB_Ypos ; Get UL Corner Ypos + 0A20 F7 26 0000 R MUL SCREEN_WIDTH ; AX = Offset to Line Ypos + + 0A24 8B 5E 1C MOV BX, [BP].DB_Xpos ; Get UL Corner Xpos + 0A27 8A CB MOV CL, BL ; Save Plane # in CL + 0A29 C1 EB 02 SHR BX, 2 ; Xpos/4 = Offset Into Line + + 0A2C 03 F8 ADD DI, AX ; ES:DI -> Start of Line + 0A2E 03 FB ADD DI, BX ; ES:DI -> Upper Left Pixel + 0A30 89 7E 04 MOV [BP].DB_Start, DI ; Save Starting Addr + + ; Compute line to line offset + + 0A33 8B 5E 18 MOV BX, [BP].DB_Width ; Get Width of Image + 0A36 8B D3 MOV DX, BX ; Save Copy in DX + 0A38 C1 EB 02 SHR BX, 2 ; /4 = width in bands + 0A3B A1 0000 R MOV AX, SCREEN_WIDTH ; Get Screen Width + 0A3E 2B C3 SUB AX, BX ; - (Bitmap Width/4) + + 0A40 89 46 00 MOV [BP].DB_LineO, AX ; Save Line Width offset + 0A43 89 5E 02 MOV [BP].DB_PixCount, BX ; Minimum # pix to copy + + 0A46 83 E2 03 AND DX, PLANE_BITS ; Get "partial band" size (0-3) + 0A49 89 56 06 MOV [BP].DB_PixSkew, DX ; Also End of Line Skew + 0A4C 89 56 08 MOV [BP].DB_SkewFlag, DX ; Save as Flag/Count + + 0A4F 83 E1 03 AND CX, PLANE_BITS ; CL = Starting Plane # + 0A52 B8 1102 MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select + 0A55 D2 E4 SHL AH, CL ; Select correct Plane + OUT_16 SC_Index, AX ; Select Plane... + 0A57 BA 03C4 1 MOV DX, SC_Index ; then Select Register + 0A5A EF 1 OUT DX, AX ; Set I/O Register(s) + 0A5B 8A FC MOV BH, AH ; BH = Saved Plane Mask + 0A5D B3 04 MOV BL, 4 ; BL = Planes to Copy + + 0A5F @DB_COPY_PLANE: + + 0A5F C5 76 1E LDS SI, [BP].DB_Image ; DS:SI-> Source Image + 0A62 8B 56 16 MOV DX, [BP].DB_Height ; # of Lines to Copy + 0A65 8B 7E 04 MOV DI, [BP].DB_Start ; ES:DI-> Dest pos + + 0A68 @DB_COPY_LINE: + 0A68 8B 4E 02 MOV CX, [BP].DB_PixCount ; Min # to copy + + 0A6B F6 C1 FC TEST CL, 0FCh ; 16+PixWide? + 0A6E 74 18 JZ @DB_COPY_REMAINDER ; Nope... + + ; Pixel Copy loop has been unrolled to x4 + + 0A70 @DB_COPY_LOOP: + 0A70 A4 MOVSB ; Copy Bitmap Pixel + 0A71 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane + 0A74 A4 MOVSB ; Copy Bitmap Pixel + 0A75 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane + 0A78 A4 MOVSB ; Copy Bitmap Pixel + 0A79 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane + 0A7C A4 MOVSB ; Copy Bitmap Pixel + 0A7D 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane + + 0A80 80 E9 04 SUB CL, 4 ; Pixels to Copy=-4 + 0A83 F6 C1 FC TEST CL, 0FCh ; 4+ Pixels Left? + 0A86 75 E8 JNZ @DB_COPY_LOOP ; if so, do another block + + 0A88 @DB_COPY_REMAINDER: + 0A88 E3 07 JCXZ @DB_NEXT_LINE ; Any Pixels left on line + + 0A8A @DB_COPY2: + 0A8A A4 MOVSB ; Copy Bitmap Pixel + 0A8B 83 C6 03 ADD SI,3 ; Skip to Next Byte in same plane + LOOPx CX, @DB_COPY2 ; Pixels to Copy--, Loop until done + 0A8E 49 1 DEC CX ; Counter-- + 0A8F 75 F9 1 JNZ @DB_COPY2 ; Jump if not 0 + + 0A91 @DB_NEXT_LINE: + + ; any Partial Pixels? (some planes only) + + 0A91 0B 4E 08 OR CX, [BP].DB_SkewFlag ; Get Skew Count + 0A94 74 03 JZ @DB_NEXT2 ; if no partial pixels + + 0A96 A4 MOVSB ; Copy Bitmap Pixel + 0A97 4F DEC DI ; Back up to align + 0A98 4E DEC SI ; Back up to align + + 0A99 @DB_NEXT2: + 0A99 03 76 06 ADD SI, [BP].DB_PixSkew ; Adjust Skew + 0A9C 03 7E 00 ADD DI, [BP].DB_LineO ; Set to Next Display Line + LOOPx DX, @DB_COPY_LINE ; Lines to Copy--, Loop if more + 0A9F 4A 1 DEC DX ; Counter-- + 0AA0 75 C6 1 JNZ @DB_COPY_LINE ; Jump if not 0 + + ; Copy Next Plane.... + + 0AA2 FE CB DEC BL ; Planes to Go-- + 0AA4 74 1B JZ @DB_Exit ; Hey! We are done + + 0AA6 D0 C7 ROL BH, 1 ; Next Plane in line... + OUT_8 SC_Data, BH ; Select Plane + 0AA8 BA 03C5 1 MOV DX, SC_Data ; then Select Register + 0AAB 8A C7 1 MOV AL, BH ; then Get Data Value + 0AAD EE 1 OUT DX, AL ; Set I/O Register + + 0AAE 3C 12 CMP AL, 12h ; Carry Set if AL=11h + 0AB0 83 56 04 00 ADC [BP].DB_Start, 0 ; Screen Addr =+Carry + 0AB4 FF 46 1E INC w [BP].DB_Image ; Start @ Next Byte + + 0AB7 83 6E 08 01 SUB [BP].DB_SkewFlag, 1 ; Reduce Planes to Skew + 0ABB 83 56 08 00 ADC [BP].DB_SkewFlag, 0 ; Back to 0 if it was -1 + + 0ABF EB 9E JMP s @DB_COPY_PLANE ; Go Copy the Next Plane + + 0AC1 @DB_Exit: + 0AC1 83 C4 0A ADD SP, 10 ; Deallocate workspace + POPx DI, SI, DS, BP ; Restore Saved Registers + 0AC4 5F 1 POP DI ; Restore R1 + 0AC5 5E 2 POP SI ; Restore R1 + 0AC6 1F 3 POP DS ; Restore R1 + 0AC7 5D 4 POP BP ; Restore R1 + 0AC8 CA 000C RET 12 ; Exit and Clean up Stack + + 0ACB DRAW_BITMAP ENDP + + + ;======================================================= + ;TDRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%) + ;======================================================= + ; + ; Transparently Draws a variable sized Graphics Bitmap + ; such as a picture or an Icon on the current Display Page + ; in Mode X. Pixels with a value of 0 are not drawn, + ; leaving the previous "background" contents intact. + ; + ; The Bitmap format is the same as for the DRAW_BITMAP function. + ; + ; ENTRY: Image = Far Pointer to Bitmap Data + ; Xpos = X position to Place Upper Left pixel at + ; Ypos = Y position to Place Upper Left pixel at + ; Width = Width of the Bitmap in Pixels + ; Height = Height of the Bitmap in Pixels + ; + ; EXIT: No meaningful values returned + ; + + 0022 TB_STACK STRUC + 0000 0000 TB_LineO DW ? ; Offset to Next Line + 0002 0000 TB_PixCount DW ? ; (Minimum) # of Pixels/Line + 0004 0000 TB_Start DW ? ; Addr of Upper Left Pixel + 0006 0000 TB_PixSkew DW ? ; # of bytes to Adjust EOL + 0008 0000 TB_SkewFlag DW ? ; Extra Pix on Plane Flag + 000A 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP + 0000 + 0012 00000000 DD ? ; Caller + 0016 0000 TB_Height DW ? ; Height of Bitmap in Pixels + 0018 0000 TB_Width DW ? ; Width of Bitmap in Pixels + 001A 0000 TB_Ypos DW ? ; Y position to Draw Bitmap at + 001C 0000 TB_Xpos DW ? ; X position to Draw Bitmap at + 001E 00000000 TB_Image DD ? ; Far Pointer to Graphics Bitmap + TB_STACK ENDS + + PUBLIC TDRAW_BITMAP + + 0ACB TDRAW_BITMAP PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 0ACB 55 1 PUSH BP ; Save R1 + 0ACC 1E 2 PUSH DS ; Save R1 + 0ACD 56 3 PUSH SI ; Save R1 + 0ACE 57 4 PUSH DI ; Save R1 + 0ACF 83 EC 0A SUB SP, 10 ; Allocate workspace + 0AD2 8B EC MOV BP, SP ; Set up Stack Frame + + 0AD4 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page + 0AD8 FC CLD ; Direction Flag = Forward + + 0AD9 8B 46 1A MOV AX, [BP].TB_Ypos ; Get UL Corner Ypos + 0ADC F7 26 0000 R MUL SCREEN_WIDTH ; AX = Offset to Line Ypos + + 0AE0 8B 5E 1C MOV BX, [BP].TB_Xpos ; Get UL Corner Xpos + 0AE3 8A CB MOV CL, BL ; Save Plane # in CL + 0AE5 C1 EB 02 SHR BX, 2 ; Xpos/4 = Offset Into Line + + 0AE8 03 F8 ADD DI, AX ; ES:DI -> Start of Line + 0AEA 03 FB ADD DI, BX ; ES:DI -> Upper Left Pixel + 0AEC 89 7E 04 MOV [BP].TB_Start, DI ; Save Starting Addr + + ; Compute line to line offset + + 0AEF 8B 5E 18 MOV BX, [BP].TB_Width ; Get Width of Image + 0AF2 8B D3 MOV DX, BX ; Save Copy in DX + 0AF4 C1 EB 02 SHR BX, 2 ; /4 = width in bands + 0AF7 A1 0000 R MOV AX, SCREEN_WIDTH ; Get Screen Width + 0AFA 2B C3 SUB AX, BX ; - (Bitmap Width/4) + + 0AFC 89 46 00 MOV [BP].TB_LineO, AX ; Save Line Width offset + 0AFF 89 5E 02 MOV [BP].TB_PixCount, BX ; Minimum # pix to copy + + 0B02 83 E2 03 AND DX, PLANE_BITS ; Get "partial band" size (0-3) + 0B05 89 56 06 MOV [BP].TB_PixSkew, DX ; Also End of Line Skew + 0B08 89 56 08 MOV [BP].TB_SkewFlag, DX ; Save as Flag/Count + + 0B0B 83 E1 03 AND CX, PLANE_BITS ; CL = Starting Plane # + 0B0E B8 1102 MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select + 0B11 D2 E4 SHL AH, CL ; Select correct Plane + OUT_16 SC_Index, AX ; Select Plane... + 0B13 BA 03C4 1 MOV DX, SC_Index ; then Select Register + 0B16 EF 1 OUT DX, AX ; Set I/O Register(s) + 0B17 8A FC MOV BH, AH ; BH = Saved Plane Mask + 0B19 B3 04 MOV BL, 4 ; BL = Planes to Copy + + Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 +modex.asm Page 13 - 1 + + + 0B1B @TB_COPY_PLANE: + + 0B1B C5 76 1E LDS SI, [BP].TB_Image ; DS:SI-> Source Image + 0B1E 8B 56 16 MOV DX, [BP].TB_Height ; # of Lines to Copy + 0B21 8B 7E 04 MOV DI, [BP].TB_Start ; ES:DI-> Dest pos + + ; Here AH is set with the value to be considered + ; "Transparent". It can be changed! + + 0B24 B4 00 MOV AH, 0 ; Value to Detect 0 + + 0B26 @TB_COPY_LINE: + 0B26 8B 4E 02 MOV CX, [BP].TB_PixCount ; Min # to copy + + 0B29 F6 C1 FC TEST CL, 0FCh ; 16+PixWide? + 0B2C 74 3A JZ @TB_COPY_REMAINDER ; Nope... + + ; Pixel Copy loop has been unrolled to x4 + + 0B2E @TB_COPY_LOOP: + 0B2E AC LODSB ; Get Pixel Value in AL + 0B2F 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane + 0B32 38 E0 CMP AL, AH ; It is "Transparent"? + 0B34 74 03 JE @TB_SKIP_01 ; Skip ahead if so + 0B36 26: 88 05 MOV ES:[DI], AL ; Copy Pixel to VGA screen + + 0B39 @TB_SKIP_01: + 0B39 AC LODSB ; Get Pixel Value in AL + 0B3A 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane + 0B3D 38 E0 CMP AL, AH ; It is "Transparent"? + 0B3F 74 04 JE @TB_SKIP_02 ; Skip ahead if so + 0B41 26: 88 45 01 MOV ES:[DI+1], AL ; Copy Pixel to VGA screen + + 0B45 @TB_SKIP_02: + 0B45 AC LODSB ; Get Pixel Value in AL + 0B46 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane + 0B49 38 E0 CMP AL, AH ; It is "Transparent"? + 0B4B 74 04 JE @TB_SKIP_03 ; Skip ahead if so + 0B4D 26: 88 45 02 MOV ES:[DI+2], AL ; Copy Pixel to VGA screen + + 0B51 @TB_SKIP_03: + 0B51 AC LODSB ; Get Pixel Value in AL + 0B52 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane + 0B55 38 E0 CMP AL, AH ; It is "Transparent"? + 0B57 74 04 JE @TB_SKIP_04 ; Skip ahead if so + 0B59 26: 88 45 03 MOV ES:[DI+3], AL ; Copy Pixel to VGA screen + + 0B5D @TB_SKIP_04: + 0B5D 83 C7 04 ADD DI, 4 ; Adjust Pixel Write Location + 0B60 80 E9 04 SUB CL, 4 ; Pixels to Copy=-4 + 0B63 F6 C1 FC TEST CL, 0FCh ; 4+ Pixels Left? + 0B66 75 C6 JNZ @TB_COPY_LOOP ; if so, do another block + + 0B68 @TB_COPY_REMAINDER: + 0B68 E3 0F JCXZ @TB_NEXT_LINE ; Any Pixels left on line + + 0B6A @TB_COPY2: + 0B6A AC LODSB ; Get Pixel Value in AL + 0B6B 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane + 0B6E 38 E0 CMP AL, AH ; It is "Transparent"? + 0B70 74 03 JE @TB_SKIP_05 ; Skip ahead if so + 0B72 26: 88 05 MOV ES:[DI], AL ; Copy Pixel to VGA screen + + 0B75 @TB_SKIP_05: + 0B75 47 INC DI ; Advance Dest Addr + LOOPx CX, @TB_COPY2 ; Pixels to Copy--, Loop until done + 0B76 49 1 DEC CX ; Counter-- + 0B77 75 F1 1 JNZ @TB_COPY2 ; Jump if not 0 + + 0B79 @TB_NEXT_LINE: + + ; any Partial Pixels? (some planes only) + + 0B79 0B 4E 08 OR CX, [BP].TB_SkewFlag ; Get Skew Count + 0B7C 74 09 JZ @TB_NEXT2 ; if no partial pixels + + 0B7E AC LODSB ; Get Pixel Value in AL + 0B7F 4E DEC SI ; Backup to Align + 0B80 38 E0 CMP AL, AH ; It is "Transparent"? + 0B82 74 03 JE @TB_NEXT2 ; Skip ahead if so + 0B84 26: 88 05 MOV ES:[DI], AL ; Copy Pixel to VGA screen + + 0B87 @TB_NEXT2: + 0B87 03 76 06 ADD SI, [BP].TB_PixSkew ; Adjust Skew + 0B8A 03 7E 00 ADD DI, [BP].TB_LineO ; Set to Next Display Line + LOOPx DX, @TB_COPY_LINE ; Lines to Copy--, Loop if More + 0B8D 4A 1 DEC DX ; Counter-- + 0B8E 75 96 1 JNZ @TB_COPY_LINE ; Jump if not 0 + + ;Copy Next Plane.... + + 0B90 FE CB DEC BL ; Planes to Go-- + 0B92 74 1C JZ @TB_Exit ; Hey! We are done + + 0B94 D0 C7 ROL BH, 1 ; Next Plane in line... + OUT_8 SC_Data, BH ; Select Plane + 0B96 BA 03C5 1 MOV DX, SC_Data ; then Select Register + 0B99 8A C7 1 MOV AL, BH ; then Get Data Value + 0B9B EE 1 OUT DX, AL ; Set I/O Register + + 0B9C 3C 12 CMP AL, 12h ; Carry Set if AL=11h + 0B9E 83 56 04 00 ADC [BP].TB_Start, 0 ; Screen Addr =+Carry + 0BA2 FF 46 1E INC w [BP].TB_Image ; Start @ Next Byte + + 0BA5 83 6E 08 01 SUB [BP].TB_SkewFlag, 1 ; Reduce Planes to Skew + 0BA9 83 56 08 00 ADC [BP].TB_SkewFlag, 0 ; Back to 0 if it was -1 + + 0BAD E9 FF6B JMP @TB_COPY_PLANE ; Go Copy the next Plane + + 0BB0 @TB_Exit: + 0BB0 83 C4 0A ADD SP, 10 ; Deallocate workspace + POPx DI, SI, DS, BP ; Restore Saved Registers + 0BB3 5F 1 POP DI ; Restore R1 + 0BB4 5E 2 POP SI ; Restore R1 + 0BB5 1F 3 POP DS ; Restore R1 + 0BB6 5D 4 POP BP ; Restore R1 + 0BB7 CA 000C RET 12 ; Exit and Clean up Stack + + 0BBA TDRAW_BITMAP ENDP + + + ; ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES ===== + + ;================================== + ;COPY_PAGE (SourcePage%, DestPage%) + ;================================== + ; + ; Duplicate on display page onto another + ; + ; ENTRY: SourcePage = Display Page # to Duplicate + ; DestPage = Display Page # to hold copy + ; + ; EXIT: No meaningful values returned + ; + + 0010 CP_STACK STRUC + 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP + 0000 + 0008 00000000 DD ? ; Caller + 000C 0000 CP_DestP DW ? ; Page to hold copied image + 000E 0000 CP_SourceP DW ? ; Page to Make copy from + CP_STACK ENDS + + PUBLIC COPY_PAGE + + 0BBA COPY_PAGE PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 0BBA 55 1 PUSH BP ; Save R1 + 0BBB 1E 2 PUSH DS ; Save R1 + 0BBC 56 3 PUSH SI ; Save R1 + 0BBD 57 4 PUSH DI ; Save R1 + 0BBE 8B EC MOV BP, SP ; Set up Stack Frame + 0BC0 FC CLD ; Block Xfer Forwards + + ; Make sure Page #'s are valid + + 0BC1 8B 46 0E MOV AX, [BP].CP_SourceP ; Get Source Page # + 0BC4 3B 06 0004 R CMP AX, LAST_PAGE ; is it > Max Page #? + 0BC8 73 3D JAE @CP_Exit ; if so, abort + + 0BCA 8B 5E 0C MOV BX, [BP].CP_DestP ; Get Destination Page # + 0BCD 3B 1E 0004 R CMP BX, LAST_PAGE ; is it > Max Page #? + 0BD1 73 34 JAE @CP_Exit ; if so, abort + + 0BD3 3B C3 CMP AX, BX ; Pages #'s the same? + 0BD5 74 30 JE @CP_Exit ; if so, abort + + ; Setup DS:SI and ES:DI to Video Pages + + 0BD7 D1 E3 SHL BX, 1 ; Scale index to Word + 0BD9 8B BF 0006 R MOV DI, PAGE_ADDR[BX] ; Offset to Dest Page + + 0BDD 8B D8 MOV BX, AX ; Index to Source page + 0BDF D1 E3 SHL BX, 1 ; Scale index to Word + 0BE1 8B B7 0006 R MOV SI, PAGE_ADDR[BX] ; Offset to Source Page + + 0BE5 8B 0E 000E R MOV CX, PAGE_SIZE ; Get size of Page + 0BE9 A1 0016 R MOV AX, CURRENT_SEGMENT ; Get Video Mem Segment + 0BEC 8E C0 MOV ES, AX ; ES:DI -> Dest Page + 0BEE 8E D8 MOV DS, AX ; DS:SI -> Source Page + + ; Setup VGA registers for Mem to Mem copy + + OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on + 0BF0 BA 03CE 1 MOV DX, GC_Index ; then Select Register + 0BF3 B8 0008 1 MOV AX, LATCHES_ON ; then Get Data Value + 0BF6 EF 1 OUT DX, AX ; Set I/O Register(s) + OUT_16 SC_Index, ALL_PLANES_ON ; Copy all Planes + 0BF7 BA 03C4 1 MOV DX, SC_Index ; then Select Register + 0BFA B8 0F02 1 MOV AX, ALL_PLANES_ON ; then Get Data Value + 0BFD EF 1 OUT DX, AX ; Set I/O Register(s) + + ; Note.. Do *NOT* use MOVSW or MOVSD - they will + ; Screw with the latches which are 8 bits x 4 + + 0BFE F3/ A4 REP MOVSB ; Copy entire Page! + + ; Reset VGA for normal memory access + + OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = off + 0C00 BA 03CE 1 MOV DX, GC_Index ; then Select Register + 0C03 B8 FF08 1 MOV AX, LATCHES_OFF ; then Get Data Value + 0C06 EF 1 OUT DX, AX ; Set I/O Register(s) + + 0C07 @CP_Exit: + POPx DI, SI, DS, BP ; Restore Saved Registers + 0C07 5F 1 POP DI ; Restore R1 + 0C08 5E 2 POP SI ; Restore R1 + 0C09 1F 3 POP DS ; Restore R1 + 0C0A 5D 4 POP BP ; Restore R1 + 0C0B CA 0004 RET 4 ; Exit and Clean up Stack + + 0C0E COPY_PAGE ENDP + + + ;========================================================================== + ;COPY_BITMAP (SourcePage%, X1%, Y1%, X2%, Y2%, DestPage%, DestX1%, DestY1%) + ;========================================================================== + ; + ; Copies a Bitmap Image from one Display Page to Another + ; This Routine is Limited to copying Images with the same + ; Plane Alignment. To Work: (X1 MOD 4) must = (DestX1 MOD 4) + ; Copying an Image to the Same Page is supported, but results + ; may be defined when the when the rectangular areas + ; (X1, Y1) - (X2, Y2) and (DestX1, DestY1) - + ; (DestX1+(X2-X1), DestY1+(Y2-Y1)) overlap... + ; No Paramter checking to done to insure that + ; X2 >= X1 and Y2 >= Y1. Be Careful... + ; + ; ENTRY: SourcePage = Display Page # with Source Image + ; X1 = Upper Left Xpos of Source Image + ; Y1 = Upper Left Ypos of Source Image + ; X2 = Lower Right Xpos of Source Image + ; Y2 = Lower Right Ypos of Source Image + ; DestPage = Display Page # to copy Image to + ; DestX1 = Xpos to Copy UL Corner of Image to + ; DestY1 = Ypos to Copy UL Corner of Image to + ; + ; EXIT: AX = Success Flag: 0 = Failure / -1= Success + ; + + 0020 CB_STACK STRUC + 0000 0000 CB_Height DW ? ; Height of Image in Lines + 0002 0000 CB_Width DW ? ; Width of Image in "bands" + 0004 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP + 0000 + 000C 00000000 DD ? ; Caller + 0010 0000 CB_DestY1 DW ? ; Destination Ypos + 0012 0000 CB_DestX1 DW ? ; Destination Xpos + 0014 0000 CB_DestP DW ? ; Page to Copy Bitmap To + Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 +modex.asm Page 14 - 1 + + + 0016 0000 CB_Y2 DW ? ; LR Ypos of Image + 0018 0000 CB_X2 DW ? ; LR Xpos of Image + 001A 0000 CB_Y1 DW ? ; UL Ypos of Image + 001C 0000 CB_X1 DW ? ; UL Xpos of Image + 001E 0000 CB_SourceP DW ? ; Page containing Source Bitmap + CB_STACK ENDS + + PUBLIC COPY_BITMAP + + 0C0E COPY_BITMAP PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 0C0E 55 1 PUSH BP ; Save R1 + 0C0F 1E 2 PUSH DS ; Save R1 + 0C10 56 3 PUSH SI ; Save R1 + 0C11 57 4 PUSH DI ; Save R1 + 0C12 83 EC 04 SUB SP, 4 ; Allocate WorkSpace on Stack + 0C15 8B EC MOV BP, SP ; Set up Stack Frame + + ; Prep Registers (and keep jumps short!) + + 0C17 8E 06 0016 R MOV ES, CURRENT_SEGMENT ; ES -> VGA Ram + 0C1B FC CLD ; Block Xfer Forwards + + ; Make sure Parameters are valid + + 0C1C 8B 5E 1E MOV BX, [BP].CB_SourceP ; Get Source Page # + 0C1F 3B 1E 0004 R CMP BX, LAST_PAGE ; is it > Max Page #? + 0C23 73 7D JAE @CB_Abort ; if so, abort + + 0C25 8B 4E 14 MOV CX, [BP].CB_DestP ; Get Destination Page # + 0C28 3B 0E 0004 R CMP CX, LAST_PAGE ; is it > Max Page #? + 0C2C 73 74 JAE @CB_Abort ; if so, abort + + 0C2E 8B 46 1C MOV AX, [BP].CB_X1 ; Get Source X1 + 0C31 33 46 12 XOR AX, [BP].CB_DestX1 ; Compare Bits 0-1 + 0C34 83 E0 03 AND AX, PLANE_BITS ; Check Plane Bits + 0C37 75 69 JNZ @CB_Abort ; They should cancel out + + ; Setup for Copy processing + + OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select + 0C39 BA 03C4 1 MOV DX, SC_INDEX ; then Select Register + 0C3C B0 02 1 MOV AL, MAP_MASK ; then Get Data Value + 0C3E EE 1 OUT DX, AL ; Set I/O Register + OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on + 0C3F BA 03CE 1 MOV DX, GC_Index ; then Select Register + 0C42 B8 0008 1 MOV AX, LATCHES_ON ; then Get Data Value + 0C45 EF 1 OUT DX, AX ; Set I/O Register(s) + + ; Compute Info About Images, Setup ES:SI & ES:DI + + 0C46 8B 46 16 MOV AX, [BP].CB_Y2 ; Height of Bitmap in lines + 0C49 2B 46 1A SUB AX, [BP].CB_Y1 ; is Y2 - Y1 + 1 + 0C4C 40 INC AX ; (add 1 since were not 0 based) + 0C4D 89 46 00 MOV [BP].CB_Height, AX ; Save on Stack for later use + + 0C50 8B 46 18 MOV AX, [BP].CB_X2 ; Get # of "Bands" of 4 Pixels + 0C53 8B 56 1C MOV DX, [BP].CB_X1 ; the Bitmap Occupies as X2-X1 + 0C56 C1 E8 02 SHR AX, 2 ; Get X2 Band (X2 / 4) + 0C59 C1 EA 02 SHR DX, 2 ; Get X1 Band (X1 / 4) + 0C5C 2B C2 SUB AX, DX ; AX = # of Bands - 1 + 0C5E 40 INC AX ; AX = # of Bands + 0C5F 89 46 02 MOV [BP].CB_Width, AX ; Save on Stack for later use + + 0C62 D1 E3 SHL BX, 1 ; Scale Source Page to Word + 0C64 8B B7 0006 R MOV SI, PAGE_ADDR[BX] ; SI = Offset of Source Page + 0C68 8B 46 1A MOV AX, [BP].CB_Y1 ; Get Source Y1 Line + 0C6B F7 26 0000 R MUL SCREEN_WIDTH ; AX = Offset to Line Y1 + 0C6F 03 F0 ADD SI, AX ; SI = Offset to Line Y1 + 0C71 8B 46 1C MOV AX, [BP].CB_X1 ; Get Source X1 + 0C74 C1 E8 02 SHR AX, 2 ; X1 / 4 = Byte offset + 0C77 03 F0 ADD SI, AX ; SI = Byte Offset to (X1,Y1) + + 0C79 8B D9 MOV BX, CX ; Dest Page Index to BX + 0C7B D1 E3 SHL BX, 1 ; Scale Source Page to Word + 0C7D 8B BF 0006 R MOV DI, PAGE_ADDR[BX] ; DI = Offset of Dest Page + 0C81 8B 46 10 MOV AX, [BP].CB_DestY1 ; Get Dest Y1 Line + 0C84 F7 26 0000 R MUL SCREEN_WIDTH ; AX = Offset to Line Y1 + 0C88 03 F8 ADD DI, AX ; DI = Offset to Line Y1 + 0C8A 8B 46 12 MOV AX, [BP].CB_DestX1 ; Get Dest X1 + 0C8D C1 E8 02 SHR AX, 2 ; X1 / 4 = Byte offset + 0C90 03 F8 ADD DI, AX ; DI = Byte Offset to (D-X1,D-Y1) + + 0C92 8B 4E 02 MOV CX, [BP].CB_Width ; CX = Width of Image (Bands) + 0C95 49 DEC CX ; CX = 1? + 0C96 74 0F JE @CB_Only_One_Band ; 0 Means Image Width of 1 Band + + 0C98 8B 5E 1C MOV BX, [BP].CB_X1 ; Get Source X1 + 0C9B 83 E3 03 AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 00?) + 0C9E 74 70 JZ @CB_Check_Right ; if so, check right alignment + 0CA0 75 41 JNZ @CB_Left_Band ; not aligned? well.. + + 0CA2 @CB_Abort: + CLR AX ; Return False (Failure) + 0CA2 33 C0 1 XOR AX, AX ; Set Register = 0 + 0CA4 E9 00D7 JMP @CB_Exit ; and Finish Up + + ; Copy when Left & Right Clip Masks overlap... + + 0CA7 @CB_Only_One_Band: + 0CA7 8B 5E 1C MOV BX, [BP].CB_X1 ; Get Left Clip Mask + 0CAA 83 E3 03 AND BX, PLANE_BITS ; Mask out Row # + 0CAD 2E: 8A 87 0000 R MOV AL, Left_Clip_Mask[BX] ; Get Left Edge Mask + 0CB2 8B 5E 18 MOV BX, [BP].CB_X2 ; Get Right Clip Mask + 0CB5 83 E3 03 AND BX, PLANE_BITS ; Mask out Row # + 0CB8 2E: 22 87 0004 R AND AL, Right_Clip_Mask[BX] ; Get Right Edge Mask byte + + OUT_8 SC_Data, AL ; Clip For Left & Right Masks + 0CBD BA 03C5 1 MOV DX, SC_Data ; then Select Register + 0CC0 EE 1 OUT DX, AL ; Set I/O Register + + 0CC1 8B 4E 00 MOV CX, [BP].CB_Height ; CX = # of Lines to Copy + 0CC4 8B 16 0000 R MOV DX, SCREEN_WIDTH ; DX = Width of Screen + CLR BX ; BX = Offset into Image + 0CC8 33 DB 1 XOR BX, BX ; Set Register = 0 + + 0CCA @CB_One_Loop: + 0CCA 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches + 0CCD 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches + 0CD0 03 DA ADD BX, DX ; Advance Offset to Next Line + LOOPjz CX, @CB_One_Done ; Exit Loop if Finished + 0CD2 49 1 DEC CX ; Counter-- + 0CD3 74 0B 1 JZ @CB_One_Done ; Jump if 0 + + 0CD5 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches + 0CD8 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches + 0CDB 03 DA ADD BX, DX ; Advance Offset to Next Line + LOOPx CX, @CB_One_Loop ; Loop until Finished + 0CDD 49 1 DEC CX ; Counter-- + 0CDE 75 EA 1 JNZ @CB_One_Loop ; Jump if not 0 + + 0CE0 @CB_One_Done: + 0CE0 E9 0094 JMP @CB_Finish ; Outa Here! + + ; Copy Left Edge of Bitmap + + 0CE3 @CB_Left_Band: + + OUT_8 SC_Data, Left_Clip_Mask[BX] ; Set Left Edge Plane Mask + 0CE3 BA 03C5 1 MOV DX, SC_Data ; then Select Register + 0CE6 2E: 8A 87 0000 R 1 MOV AL, Left_Clip_Mask[BX] ; then Get Data Value + 0CEB EE 1 OUT DX, AL ; Set I/O Register + + 0CEC 8B 4E 00 MOV CX, [BP].CB_Height ; CX = # of Lines to Copy + 0CEF 8B 16 0000 R MOV DX, SCREEN_WIDTH ; DX = Width of Screen + CLR BX ; BX = Offset into Image + 0CF3 33 DB 1 XOR BX, BX ; Set Register = 0 + + 0CF5 @CB_Left_Loop: + 0CF5 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches + 0CF8 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches + 0CFB 03 DA ADD BX, DX ; Advance Offset to Next Line + LOOPjz CX, @CB_Left_Done ; Exit Loop if Finished + 0CFD 49 1 DEC CX ; Counter-- + 0CFE 74 0B 1 JZ @CB_Left_Done ; Jump if 0 + + 0D00 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches + 0D03 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches + 0D06 03 DA ADD BX, DX ; Advance Offset to Next Line + LOOPx CX, @CB_Left_Loop ; Loop until Finished + 0D08 49 1 DEC CX ; Counter-- + 0D09 75 EA 1 JNZ @CB_Left_Loop ; Jump if not 0 + + 0D0B @CB_Left_Done: + 0D0B 47 INC DI ; Move Dest Over 1 band + 0D0C 46 INC SI ; Move Source Over 1 band + 0D0D FF 4E 02 DEC [BP].CB_Width ; Band Width-- + + ; Determine if Right Edge of Bitmap needs special copy + + 0D10 @CB_Check_Right: + 0D10 8B 5E 18 MOV BX, [BP].CB_X2 ; Get Source X2 + 0D13 83 E3 03 AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 11?) + 0D16 80 FB 03 CMP BL, 03h ; Plane = 3? + 0D19 74 2C JE @CB_Copy_Middle ; Copy the Middle then! + + ; Copy Right Edge of Bitmap + + 0D1B @CB_Right_Band: + + OUT_8 SC_Data, Right_Clip_Mask[BX] ; Set Right Edge Plane Mask + 0D1B BA 03C5 1 MOV DX, SC_Data ; then Select Register + 0D1E 2E: 8A 87 0004 R 1 MOV AL, Right_Clip_Mask[BX] ; then Get Data Value + 0D23 EE 1 OUT DX, AL ; Set I/O Register + + 0D24 FF 4E 02 DEC [BP].CB_Width ; Band Width-- + 0D27 8B 4E 00 MOV CX, [BP].CB_Height ; CX = # of Lines to Copy + 0D2A 8B 16 0000 R MOV DX, SCREEN_WIDTH ; DX = Width of Screen + 0D2E 8B 5E 02 MOV BX, [BP].CB_Width ; BX = Offset to Right Edge + + 0D31 @CB_Right_Loop: + 0D31 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches + 0D34 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches + 0D37 03 DA ADD BX, DX ; Advance Offset to Next Line + LOOPjz CX, @CB_Right_Done ; Exit Loop if Finished + 0D39 49 1 DEC CX ; Counter-- + 0D3A 74 0B 1 JZ @CB_Right_Done ; Jump if 0 + + 0D3C 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches + 0D3F 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches + 0D42 03 DA ADD BX, DX ; Advance Offset to Next Line + LOOPx CX, @CB_Right_Loop ; Loop until Finished + 0D44 49 1 DEC CX ; Counter-- + 0D45 75 EA 1 JNZ @CB_Right_Loop ; Jump if not 0 + + 0D47 @CB_Right_Done: + + ; Copy the Main Block of the Bitmap + + 0D47 @CB_Copy_Middle: + + 0D47 8B 4E 02 MOV CX, [BP].CB_Width ; Get Width Remaining + 0D4A E3 2B JCXZ @CB_Finish ; Exit if Done + + OUT_8 SC_Data, ALL_PLANES ; Copy all Planes + 0D4C BA 03C5 1 MOV DX, SC_Data ; then Select Register + 0D4F B0 0F 1 MOV AL, ALL_PLANES ; then Get Data Value + 0D51 EE 1 OUT DX, AL ; Set I/O Register + + 0D52 8B 16 0000 R MOV DX, SCREEN_WIDTH ; Get Width of Screen minus + 0D56 2B D1 SUB DX, CX ; Image width (for Adjustment) + 0D58 8B 46 00 MOV AX, [BP].CB_Height ; AX = # of Lines to Copy + 0D5B 8B D9 MOV BX, CX ; BX = Quick REP reload count + 0D5D 8C C1 MOV CX, ES ; Move VGA Segment + 0D5F 8E D9 MOV DS, CX ; Into DS + + ; Actual Copy Loop. REP MOVSB does the work + + 0D61 @CB_Middle_Copy: + 0D61 8B CB MOV CX, BX ; Recharge Rep Count + 0D63 F3/ A4 REP MOVSB ; Move Bands + LOOPjz AX, @CB_Finish ; Exit Loop if Finished + 0D65 48 1 DEC AX ; Counter-- + 0D66 74 0F 1 JZ @CB_Finish ; Jump if 0 + + 0D68 03 F2 ADD SI, DX ; Adjust DS:SI to Next Line + 0D6A 03 FA ADD DI, DX ; Adjust ES:DI to Next Line + + 0D6C 8B CB MOV CX, BX ; Recharge Rep Count + 0D6E F3/ A4 REP MOVSB ; Move Bands + + 0D70 03 F2 ADD SI, DX ; Adjust DS:SI to Next Line + 0D72 03 FA ADD DI, DX ; Adjust ES:DI to Next Line + LOOPx AX, @CB_Middle_Copy ; Copy Lines until Done + 0D74 48 1 DEC AX ; Counter-- + 0D75 75 EA 1 JNZ @CB_Middle_Copy ; Jump if not 0 + + 0D77 @CB_Finish: + OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = on + 0D77 BA 03CE 1 MOV DX, GC_Index ; then Select Register + Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 +modex.asm Page 15 - 1 + + + 0D7A B8 FF08 1 MOV AX, LATCHES_OFF ; then Get Data Value + 0D7D EF 1 OUT DX, AX ; Set I/O Register(s) + + 0D7E @CB_Exit: + 0D7E 83 C4 04 ADD SP, 04 ; Deallocate stack workspace + POPx DI, SI, DS, BP ; Restore Saved Registers + 0D81 5F 1 POP DI ; Restore R1 + 0D82 5E 2 POP SI ; Restore R1 + 0D83 1F 3 POP DS ; Restore R1 + 0D84 5D 4 POP BP ; Restore R1 + 0D85 CA 0010 RET 16 ; Exit and Clean up Stack + + 0D88 COPY_BITMAP ENDP + + END ; End of Code Segment + Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 +modex.asm Symbols 16 - 1 + + + + +Macros: + + N a m e Type + +CLR . . . . . . . . . . . . . . Proc +LOOPjz . . . . . . . . . . . . . Proc +LOOPx . . . . . . . . . . . . . Proc +OUT_16 . . . . . . . . . . . . . Proc +OUT_8 . . . . . . . . . . . . . Proc +POPx . . . . . . . . . . . . . . Proc +PUSHx . . . . . . . . . . . . . Proc + Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 +modex.asm Symbols 17 - 1 + + + + +Structures and Unions: + + N a m e Size + Offset Type + +CB_STACK . . . . . . . . . . . . 0020 + CB_Height . . . . . . . . . . 0000 Word + CB_Width . . . . . . . . . . . 0002 Word + CB_DestY1 . . . . . . . . . . 0010 Word + CB_DestX1 . . . . . . . . . . 0012 Word + CB_DestP . . . . . . . . . . . 0014 Word + CB_Y2 . . . . . . . . . . . . 0016 Word + CB_X2 . . . . . . . . . . . . 0018 Word + CB_Y1 . . . . . . . . . . . . 001A Word + CB_X1 . . . . . . . . . . . . 001C Word + CB_SourceP . . . . . . . . . . 001E Word +CP_STACK . . . . . . . . . . . . 0010 + CP_DestP . . . . . . . . . . . 000C Word + CP_SourceP . . . . . . . . . . 000E Word +CVS_STACK . . . . . . . . . . . 000A + CVS_COLOR . . . . . . . . . . 0008 Byte +DB_STACK . . . . . . . . . . . . 0022 + DB_LineO . . . . . . . . . . . 0000 Word + DB_PixCount . . . . . . . . . 0002 Word + DB_Start . . . . . . . . . . . 0004 Word + DB_PixSkew . . . . . . . . . . 0006 Word + DB_SkewFlag . . . . . . . . . 0008 Word + DB_Height . . . . . . . . . . 0016 Word + DB_Width . . . . . . . . . . . 0018 Word + DB_Ypos . . . . . . . . . . . 001A Word + DB_Xpos . . . . . . . . . . . 001C Word + DB_Image . . . . . . . . . . . 001E DWord +DL_STACK . . . . . . . . . . . . 0014 + DL_ColorF . . . . . . . . . . 000A Byte + DL_Ypos2 . . . . . . . . . . . 000C Word + DL_Xpos2 . . . . . . . . . . . 000E Word + DL_Ypos1 . . . . . . . . . . . 0010 Word + DL_Xpos1 . . . . . . . . . . . 0012 Word +FB_STACK . . . . . . . . . . . . 0016 + FB_Color . . . . . . . . . . . 000C Byte + FB_Ypos2 . . . . . . . . . . . 000E Word + FB_Xpos2 . . . . . . . . . . . 0010 Word + FB_Ypos1 . . . . . . . . . . . 0012 Word + FB_Xpos1 . . . . . . . . . . . 0014 Word +GDR_STACK . . . . . . . . . . . 000E + GDR_Blue . . . . . . . . . . . 0006 Word + GDR_Green . . . . . . . . . . 0008 Word + GDR_Red . . . . . . . . . . . 000A Word + GDR_Register . . . . . . . . . 000C Byte +GPC_STACK . . . . . . . . . . . 001E + GPC_Width . . . . . . . . . . 0000 Word + GPC_Lines . . . . . . . . . . 0002 Byte + GPC_T_SETS . . . . . . . . . . 0004 Word + GPC_T_SETO . . . . . . . . . . 0006 Word + GPC_ColorB . . . . . . . . . . 0014 Byte + GPC_ColorF . . . . . . . . . . 0016 Byte + GPC_Ypos . . . . . . . . . . . 0018 Word + GPC_Xpos . . . . . . . . . . . 001A Word + GPC_Char . . . . . . . . . . . 001C Byte +LDR_STACK . . . . . . . . . . . 0014 + LDR_Sync . . . . . . . . . . . 000A Word + LDR_EndReg . . . . . . . . . . 000C Byte + LDR_StartReg . . . . . . . . . 000E Byte + LDR_PalData . . . . . . . . . 0010 DWord +Mode_Data_Table . . . . . . . . 000C + M_MiscR . . . . . . . . . . . 0000 Byte + M_Pages . . . . . . . . . . . 0001 Byte + M_XSize . . . . . . . . . . . 0002 Word + M_YSize . . . . . . . . . . . 0004 Word + M_XMax . . . . . . . . . . . . 0006 Word + M_YMax . . . . . . . . . . . . 0008 Word + M_CRTC . . . . . . . . . . . . 000A Word +PS_STACK . . . . . . . . . . . . 001A + PS_ColorB . . . . . . . . . . 000C Word + PS_ColorF . . . . . . . . . . 000E Word + PS_Ypos . . . . . . . . . . . 0010 Word + PS_Xpos . . . . . . . . . . . 0012 Word + PS_Len . . . . . . . . . . . . 0014 Word + PS_Text . . . . . . . . . . . 0016 Word +RDR_STACK . . . . . . . . . . . 0012 + RDR_EndReg . . . . . . . . . . 000A Byte + RDR_StartReg . . . . . . . . . 000C Byte + RDR_PalData . . . . . . . . . 000E DWord +RP_STACK . . . . . . . . . . . . 000C + RP_Ypos . . . . . . . . . . . 0008 Word + RP_Xpos . . . . . . . . . . . 000A Word +SAP_STACK . . . . . . . . . . . 0008 + SAP_Page . . . . . . . . . . . 0006 Word +SDF_STACK . . . . . . . . . . . 000C + SDF_Which . . . . . . . . . . 0006 Word + SDF_Font . . . . . . . . . . . 0008 DWord +SDP_STACK . . . . . . . . . . . 0008 + SDP_Page . . . . . . . . . . . 0006 Word +SDR_STACK . . . . . . . . . . . 000E + SDR_Blue . . . . . . . . . . . 0006 Byte + SDR_Green . . . . . . . . . . 0008 Byte + SDR_Red . . . . . . . . . . . 000A Byte + SDR_Register . . . . . . . . . 000C Byte +SM_STACK . . . . . . . . . . . . 000A + SM_Mode . . . . . . . . . . . 0008 Word +SP_STACK . . . . . . . . . . . . 000E + SETP_Color . . . . . . . . . . 0008 Byte + SETP_Ypos . . . . . . . . . . 000A Word + SETP_Xpos . . . . . . . . . . 000C Word +SVM_STACK . . . . . . . . . . . 0016 + SVM_Table . . . . . . . . . . 0000 Word + SVM_Pages . . . . . . . . . . 000E Word + SVM_Ysize . . . . . . . . . . 0010 Word + SVM_Xsize . . . . . . . . . . 0012 Word + SVM_Mode . . . . . . . . . . . 0014 Word +SW_STACK . . . . . . . . . . . . 000C + SW_Ypos . . . . . . . . . . . 0006 Word + SW_Xpos . . . . . . . . . . . 0008 Word + SW_Page . . . . . . . . . . . 000A Word +TB_STACK . . . . . . . . . . . . 0022 + TB_LineO . . . . . . . . . . . 0000 Word + TB_PixCount . . . . . . . . . 0002 Word + TB_Start . . . . . . . . . . . 0004 Word + TB_PixSkew . . . . . . . . . . 0006 Word + TB_SkewFlag . . . . . . . . . 0008 Word + TB_Height . . . . . . . . . . 0016 Word + TB_Width . . . . . . . . . . . 0018 Word + TB_Ypos . . . . . . . . . . . 001A Word + TB_Xpos . . . . . . . . . . . 001C Word + TB_Image . . . . . . . . . . . 001E DWord +TGP_STACK . . . . . . . . . . . 001C + TGP_Width . . . . . . . . . . 0000 Word + TGP_Lines . . . . . . . . . . 0002 Byte + TGP_T_SETS . . . . . . . . . . 0004 Word + TGP_T_SETO . . . . . . . . . . 0006 Word + TGP_ColorF . . . . . . . . . . 0014 Byte + TGP_Ypos . . . . . . . . . . . 0016 Word + TGP_Xpos . . . . . . . . . . . 0018 Word + TGP_Char . . . . . . . . . . . 001A Byte +TPS_STACK . . . . . . . . . . . 0018 + TPS_ColorF . . . . . . . . . . 000C Word + TPS_Ypos . . . . . . . . . . . 000E Word + TPS_Xpos . . . . . . . . . . . 0010 Word + TPS_Len . . . . . . . . . . . 0012 Word + TPS_Text . . . . . . . . . . . 0014 Word + Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 +modex.asm Symbols 18 - 1 + + + + +Segments and Groups: + + N a m e Size Length Align Combine Class + +DGROUP . . . . . . . . . . . . . GROUP +_DATA . . . . . . . . . . . . . 16 Bit 0000 Word Public 'DATA' +_BSS . . . . . . . . . . . . . . 16 Bit 002A Word Public 'BSS' +MODEX_TEXT . . . . . . . . . . . 16 Bit 0D88 Word Public 'CODE' + Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 +modex.asm Symbols 19 - 1 + + + + +Procedures, parameters and locals: + + N a m e Type Value Attr + +CLEAR_VGA_SCREEN . . . . . . . . P Far 0280 MODEX_TEXT Length= 0022 Public +COPY_BITMAP . . . . . . . . . . P Far 0C0E MODEX_TEXT Length= 017E Public +COPY_PAGE . . . . . . . . . . . P Far 0BBA MODEX_TEXT Length= 0054 Public +DRAW_BITMAP . . . . . . . . . . P Far 0A0F MODEX_TEXT Length= 00BC Public +DRAW_LINE . . . . . . . . . . . P Far 040B MODEX_TEXT Length= 02A7 Public +FILL_BLOCK . . . . . . . . . . . P Far 0300 MODEX_TEXT Length= 010B Public +GET_ACTIVE_PAGE . . . . . . . . P Far 06E5 MODEX_TEXT Length= 0004 Public +GET_DAC_REGISTER . . . . . . . . P Far 0641 MODEX_TEXT Length= 0025 Public +GET_DISPLAY_PAGE . . . . . . . . P Far 0724 MODEX_TEXT Length= 0004 Public +GET_X_OFFSET . . . . . . . . . . P Far 078D MODEX_TEXT Length= 0004 Public +GET_Y_OFFSET . . . . . . . . . . P Far 0791 MODEX_TEXT Length= 0004 Public +GPRINTC . . . . . . . . . . . . P Far 07A3 MODEX_TEXT Length= 00FE Public +LOAD_DAC_REGISTERS . . . . . . . P Far 0666 MODEX_TEXT Length= 0037 Public +PRINT_STR . . . . . . . . . . . P Far 0975 MODEX_TEXT Length= 0041 Public +READ_DAC_REGISTERS . . . . . . . P Far 069D MODEX_TEXT Length= 002B Public +READ_POINT . . . . . . . . . . . P Far 02D2 MODEX_TEXT Length= 002E Public +SET_ACTIVE_PAGE . . . . . . . . P Far 06C8 MODEX_TEXT Length= 001D Public +SET_DAC_REGISTER . . . . . . . . P Far 0624 MODEX_TEXT Length= 001D Public +SET_DISPLAY_FONT . . . . . . . . P Far 09F3 MODEX_TEXT Length= 001C Public +SET_DISPLAY_PAGE . . . . . . . . P Far 06E9 MODEX_TEXT Length= 003B Public +SET_MODEX . . . . . . . . . . . P Far 0251 MODEX_TEXT Length= 002F Public +SET_POINT . . . . . . . . . . . P Far 02A2 MODEX_TEXT Length= 0030 Public +SET_VGA_MODEX . . . . . . . . . P Far 0104 MODEX_TEXT Length= 014D Public +SET_WINDOW . . . . . . . . . . . P Far 0728 MODEX_TEXT Length= 0065 Public +SYNC_DISPLAY . . . . . . . . . . P Far 0795 MODEX_TEXT Length= 000E Public +TDRAW_BITMAP . . . . . . . . . . P Far 0ACB MODEX_TEXT Length= 00EF Public +TGPRINTC . . . . . . . . . . . . P Far 08A1 MODEX_TEXT Length= 00D4 Public +TPRINT_STR . . . . . . . . . . . P Far 09B6 MODEX_TEXT Length= 003D Public + Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 +modex.asm Symbols 20 - 1 + + + + +Symbols: + + N a m e Type Value Attr + +?x3 . . . . . . . . . . . . . . Text ?,?,? +?x4 . . . . . . . . . . . . . . Text ?,?,?,? +@CB_Abort . . . . . . . . . . . L Near 0CA2 MODEX_TEXT +@CB_Check_Right . . . . . . . . L Near 0D10 MODEX_TEXT +@CB_Copy_Middle . . . . . . . . L Near 0D47 MODEX_TEXT +@CB_Exit . . . . . . . . . . . . L Near 0D7E MODEX_TEXT +@CB_Finish . . . . . . . . . . . L Near 0D77 MODEX_TEXT +@CB_Left_Band . . . . . . . . . L Near 0CE3 MODEX_TEXT +@CB_Left_Done . . . . . . . . . L Near 0D0B MODEX_TEXT +@CB_Left_Loop . . . . . . . . . L Near 0CF5 MODEX_TEXT +@CB_Middle_Copy . . . . . . . . L Near 0D61 MODEX_TEXT +@CB_One_Done . . . . . . . . . . L Near 0CE0 MODEX_TEXT +@CB_One_Loop . . . . . . . . . . L Near 0CCA MODEX_TEXT +@CB_Only_One_Band . . . . . . . L Near 0CA7 MODEX_TEXT +@CB_Right_Band . . . . . . . . . L Near 0D1B MODEX_TEXT +@CB_Right_Done . . . . . . . . . L Near 0D47 MODEX_TEXT +@CB_Right_Loop . . . . . . . . . L Near 0D31 MODEX_TEXT +@CP_Exit . . . . . . . . . . . . L Near 0C07 MODEX_TEXT +@CodeSize . . . . . . . . . . . Number 0001h +@DB_COPY2 . . . . . . . . . . . L Near 0A8A MODEX_TEXT +@DB_COPY_LINE . . . . . . . . . L Near 0A68 MODEX_TEXT +@DB_COPY_LOOP . . . . . . . . . L Near 0A70 MODEX_TEXT +@DB_COPY_PLANE . . . . . . . . . L Near 0A5F MODEX_TEXT +@DB_COPY_REMAINDER . . . . . . . L Near 0A88 MODEX_TEXT +@DB_Exit . . . . . . . . . . . . L Near 0AC1 MODEX_TEXT +@DB_NEXT2 . . . . . . . . . . . L Near 0A99 MODEX_TEXT +@DB_NEXT_LINE . . . . . . . . . L Near 0A91 MODEX_TEXT +@DL_BREZHAM . . . . . . . . . . L Near 04C7 MODEX_TEXT +@DL_DeltaYOK2 . . . . . . . . . L Near 0515 MODEX_TEXT +@DL_DeltaYOK . . . . . . . . . . L Near 04DC MODEX_TEXT +@DL_DrawLeft . . . . . . . . . . L Near 051F MODEX_TEXT +@DL_DrawRight . . . . . . . . . L Near 05A3 MODEX_TEXT +@DL_EXIT2 . . . . . . . . . . . L Near 061E MODEX_TEXT +@DL_EXIT . . . . . . . . . . . . L Near 04C4 MODEX_TEXT +@DL_HORZ . . . . . . . . . . . . L Near 0433 MODEX_TEXT +@DL_LONGLN . . . . . . . . . . . L Near 0461 MODEX_TEXT +@DL_NOSWAP1 . . . . . . . . . . L Near 0428 MODEX_TEXT +@DL_NOSWAP2 . . . . . . . . . . L Near 048C MODEX_TEXT +@DL_SLLExit . . . . . . . . . . L Near 0563 MODEX_TEXT +@DL_SLLL2nc . . . . . . . . . . L Near 0543 MODEX_TEXT +@DL_SLLL3nc . . . . . . . . . . L Near 0558 MODEX_TEXT +@DL_SLLLoop . . . . . . . . . . L Near 0537 MODEX_TEXT +@DL_SLR2nc . . . . . . . . . . . L Near 05C5 MODEX_TEXT +@DL_SLR3nc . . . . . . . . . . . L Near 05D9 MODEX_TEXT +@DL_SLRExit . . . . . . . . . . L Near 05E3 MODEX_TEXT +@DL_SLRLoop . . . . . . . . . . L Near 05B9 MODEX_TEXT +@DL_STLExit . . . . . . . . . . L Near 05A1 MODEX_TEXT +@DL_STLLoop . . . . . . . . . . L Near 0575 MODEX_TEXT +@DL_STLnc2 . . . . . . . . . . . L Near 0588 MODEX_TEXT +@DL_STLnc3 . . . . . . . . . . . L Near 059D MODEX_TEXT +@DL_ShallowLeft . . . . . . . . L Near 0525 MODEX_TEXT +@DL_ShallowRight . . . . . . . . L Near 05A7 MODEX_TEXT +@DL_SteepLeft . . . . . . . . . L Near 0566 MODEX_TEXT +@DL_SteepRight . . . . . . . . . L Near 05E5 MODEX_TEXT +@DL_VLINE . . . . . . . . . . . L Near 0481 MODEX_TEXT +@DL_VLoop . . . . . . . . . . . L Near 04B4 MODEX_TEXT +@DL_XRSEG . . . . . . . . . . . L Near 0479 MODEX_TEXT +@DP_WAIT0 . . . . . . . . . . . L Near 0706 MODEX_TEXT +@DP_WAIT1 . . . . . . . . . . . L Near 071B MODEX_TEXT +@DataSize . . . . . . . . . . . Number 0000h +@FB_EXIT . . . . . . . . . . . . L Near 0404 MODEX_TEXT +@FB_LEFT_CONT . . . . . . . . . L Near 037A MODEX_TEXT +@FB_LEFT_LOOP . . . . . . . . . L Near 036A MODEX_TEXT +@FB_L_PLANE_FLUSH . . . . . . . L Near 037C MODEX_TEXT +@FB_MIDDLE_LOOP . . . . . . . . L Near 03C7 MODEX_TEXT +@FB_NORMAL . . . . . . . . . . . L Near 034C MODEX_TEXT +@FB_NOSWAP1 . . . . . . . . . . L Near 031F MODEX_TEXT +@FB_NOSWAP2 . . . . . . . . . . L Near 0339 MODEX_TEXT +@FB_ONE_BAND_ONLY . . . . . . . L Near 03D2 MODEX_TEXT +@FB_ONE_LOOP . . . . . . . . . . L Near 03F4 MODEX_TEXT +@FB_RIGHT_CONT . . . . . . . . . L Near 03B0 MODEX_TEXT +@FB_RIGHT_LOOP . . . . . . . . . L Near 03A0 MODEX_TEXT +@FB_RIGHT . . . . . . . . . . . L Near 037D MODEX_TEXT +@FB_R_EDGE_FLUSH . . . . . . . . L Near 03B3 MODEX_TEXT +@GPC_DECODE_CHAR_BYTE . . . . . L Near 080F MODEX_TEXT +@GPC_EXIT . . . . . . . . . . . L Near 0897 MODEX_TEXT +@GPC_LowChar . . . . . . . . . . L Near 07DB MODEX_TEXT +@GPC_NEXT_LINE . . . . . . . . . L Near 0889 MODEX_TEXT +@GPC_NO_LEFT0BITS . . . . . . . L Near 083C MODEX_TEXT +@GPC_NO_LEFT1BITS . . . . . . . L Near 0831 MODEX_TEXT +@GPC_NO_MIDDLE0BITS . . . . . . L Near 085E MODEX_TEXT +@GPC_NO_MIDDLE1BITS . . . . . . L Near 0853 MODEX_TEXT +@GPC_NO_RIGHT0BITS . . . . . . . L Near 0888 MODEX_TEXT +@GPC_NO_RIGHT1BITS . . . . . . . L Near 087D MODEX_TEXT +@GPC_Set_Char . . . . . . . . . L Near 07E3 MODEX_TEXT +@Interface . . . . . . . . . . . Number 0000h +@LDR_Load . . . . . . . . . . . L Near 0677 MODEX_TEXT +@Model . . . . . . . . . . . . . Number 0004h +@PS_Exit . . . . . . . . . . . . L Near 09AF MODEX_TEXT +@PS_Print_It . . . . . . . . . . L Near 097B MODEX_TEXT +@SAP_Exit . . . . . . . . . . . L Near 06E1 MODEX_TEXT +@SDF_Set_Font . . . . . . . . . L Near 0A06 MODEX_TEXT +@SDP_Exit . . . . . . . . . . . L Near 0720 MODEX_TEXT +@SD_WAIT0 . . . . . . . . . . . L Near 0798 MODEX_TEXT +@SD_WAIT1 . . . . . . . . . . . L Near 079D MODEX_TEXT +@SMX_Exit . . . . . . . . . . . L Near 027B MODEX_TEXT +@STRLoop . . . . . . . . . . . . L Near 05F4 MODEX_TEXT +@STRnc2 . . . . . . . . . . . . L Near 0606 MODEX_TEXT +@STRnc3 . . . . . . . . . . . . L Near 061A MODEX_TEXT +@SVM_BadModeSetup . . . . . . . L Near 015C MODEX_TEXT +@SVM_Continue . . . . . . . . . L Near 0161 MODEX_TEXT +@SVM_EXIT . . . . . . . . . . . L Near 0247 MODEX_TEXT +@SVM_Set_Data . . . . . . . . . L Near 01AA MODEX_TEXT +@SVM_Set_Pages . . . . . . . . . L Near 0207 MODEX_TEXT +@SVM_Setup_CRTC . . . . . . . . L Near 019D MODEX_TEXT +@SVM_Setup_Table . . . . . . . . L Near 0193 MODEX_TEXT +@SW_Exit . . . . . . . . . . . . L Near 0789 MODEX_TEXT +@SW_WAIT0 . . . . . . . . . . . L Near 0761 MODEX_TEXT +@SW_WAIT1 . . . . . . . . . . . L Near 0776 MODEX_TEXT +@TB_COPY2 . . . . . . . . . . . L Near 0B6A MODEX_TEXT +@TB_COPY_LINE . . . . . . . . . L Near 0B26 MODEX_TEXT +@TB_COPY_LOOP . . . . . . . . . L Near 0B2E MODEX_TEXT +@TB_COPY_PLANE . . . . . . . . . L Near 0B1B MODEX_TEXT +@TB_COPY_REMAINDER . . . . . . . L Near 0B68 MODEX_TEXT +@TB_Exit . . . . . . . . . . . . L Near 0BB0 MODEX_TEXT +@TB_NEXT2 . . . . . . . . . . . L Near 0B87 MODEX_TEXT +@TB_NEXT_LINE . . . . . . . . . L Near 0B79 MODEX_TEXT +@TB_SKIP_01 . . . . . . . . . . L Near 0B39 MODEX_TEXT +@TB_SKIP_02 . . . . . . . . . . L Near 0B45 MODEX_TEXT +@TB_SKIP_03 . . . . . . . . . . L Near 0B51 MODEX_TEXT +@TB_SKIP_04 . . . . . . . . . . L Near 0B5D MODEX_TEXT +@TB_SKIP_05 . . . . . . . . . . L Near 0B75 MODEX_TEXT +@TGP_DECODE_CHAR_BYTE . . . . . L Near 090D MODEX_TEXT +@TGP_EXIT . . . . . . . . . . . L Near 096B MODEX_TEXT +@TGP_LowChar . . . . . . . . . . L Near 08D9 MODEX_TEXT +@TGP_NEXT_LINE . . . . . . . . . L Near 095E MODEX_TEXT +@TGP_NO_LEFT1BITS . . . . . . . L Near 092D MODEX_TEXT +@TGP_NO_MIDDLE1BITS . . . . . . L Near 0941 MODEX_TEXT +@TGP_NO_RIGHT1BITS . . . . . . . L Near 095D MODEX_TEXT +@TGP_Set_Char . . . . . . . . . L Near 08E1 MODEX_TEXT +@TPS_Exit . . . . . . . . . . . L Near 09EC MODEX_TEXT +@TPS_Print_It . . . . . . . . . L Near 09BC MODEX_TEXT +@code . . . . . . . . . . . . . Text MODEX_TEXT +@data . . . . . . . . . . . . . Text DGROUP +@fardata? . . . . . . . . . . . Text FAR_BSS +@fardata . . . . . . . . . . . . Text FAR_DATA +@stack . . . . . . . . . . . . . Text DGROUP +ACTIVE_PAGE . . . . . . . . . . Word 0012 _BSS +ALL_PLANES_ON . . . . . . . . . Number 0F02h +ALL_PLANES . . . . . . . . . . . Number 000Fh +ASYNC_RESET . . . . . . . . . . Number 0100h +ATTRIB_Ctrl . . . . . . . . . . Number 03C0h +CHAIN4_OFF . . . . . . . . . . . Number 0604h +CHARSET_HI . . . . . . . . . . . Word 0026 _BSS +CHARSET_LOW . . . . . . . . . . Word 0022 _BSS +CHAR_BITS . . . . . . . . . . . Number 000Fh +CRTC_Data . . . . . . . . . . . Number 03D5h +CRTC_Index . . . . . . . . . . . Number 03D4h +CURRENT_MOFFSET . . . . . . . . Word 001C _BSS +CURRENT_PAGE . . . . . . . . . . Word 0014 _BSS +CURRENT_SEGMENT . . . . . . . . Word 0016 _BSS +CURRENT_XOFFSET . . . . . . . . Word 0018 _BSS +CURRENT_YOFFSET . . . . . . . . Word 001A _BSS +Char_Plane_Data . . . . . . . . Byte 0008 MODEX_TEXT +DAC_READ_ADDR . . . . . . . . . Number 03C7h +DAC_WRITE_ADDR . . . . . . . . . Number 03C8h +DISPLAY_PAGE . . . . . . . . . . Word 0010 _BSS +False . . . . . . . . . . . . . Number 0000h +GC_Index . . . . . . . . . . . . Number 03CEh +GET_CHAR_PTR . . . . . . . . . . Number 1130h +INPUT_1 . . . . . . . . . . . . Number 03DAh +LAST_PAGE . . . . . . . . . . . Word 0004 _BSS +LATCHES_OFF . . . . . . . . . . Number FF08h +LATCHES_ON . . . . . . . . . . . Number 0008h +Left_Clip_Mask . . . . . . . . . Byte 0000 MODEX_TEXT +MAP_MASK_PLANE1 . . . . . . . . Number 0102h +MAP_MASK_PLANE2 . . . . . . . . Number 1102h +MAP_MASK . . . . . . . . . . . . Number 0002h +MAX_XOFFSET . . . . . . . . . . Word 001E _BSS +MAX_YOFFSET . . . . . . . . . . Word 0020 _BSS +MISC_OUTPUT . . . . . . . . . . Number 03C2h +MODE_200_Tall . . . . . . . . . L Near 0044 MODEX_TEXT +MODE_240_Tall . . . . . . . . . L Near 0054 MODEX_TEXT +MODE_320_Wide . . . . . . . . . L Near 0028 MODEX_TEXT +MODE_320x200 . . . . . . . . . . L Near 0074 MODEX_TEXT +MODE_320x240 . . . . . . . . . . L Near 00BC MODEX_TEXT +MODE_320x400 . . . . . . . . . . L Near 0086 MODEX_TEXT +MODE_320x480 . . . . . . . . . . L Near 00CE MODEX_TEXT +MODE_360_Wide . . . . . . . . . L Near 0036 MODEX_TEXT +MODE_360x200 . . . . . . . . . . L Near 00E0 MODEX_TEXT +MODE_360x240 . . . . . . . . . . L Near 0098 MODEX_TEXT +MODE_360x400 . . . . . . . . . . L Near 00F2 MODEX_TEXT +MODE_360x480 . . . . . . . . . . L Near 00AA MODEX_TEXT +MODE_400_Tall . . . . . . . . . L Near 0044 MODEX_TEXT +MODE_480_Tall . . . . . . . . . L Near 0054 MODEX_TEXT +MODE_Double_Line . . . . . . . . L Near 0020 MODEX_TEXT +MODE_Single_Line . . . . . . . . L Near 0018 MODEX_TEXT +MODE_TABLE . . . . . . . . . . . L Near 0064 MODEX_TEXT +NUM_MODES . . . . . . . . . . . Number 0008h +PAGE_ADDR . . . . . . . . . . . Word 0006 _BSS +PAGE_SIZE . . . . . . . . . . . Word 000E _BSS +PEL_DATA_REG . . . . . . . . . . Number 03C9h +PIXEL_PAN_REG . . . . . . . . . Number 0033h +PLANE_BITS . . . . . . . . . . . Number 0003h +READ_MAP . . . . . . . . . . . . Number 0004h +ROM_8x8_Hi . . . . . . . . . . . Number 0004h +ROM_8x8_Lo . . . . . . . . . . . Number 0003h +Right_Clip_Mask . . . . . . . . Byte 0004 MODEX_TEXT +SCREEN_HEIGHT . . . . . . . . . Word 0002 _BSS +SCREEN_WIDTH . . . . . . . . . . Word 0000 _BSS +SC_Data . . . . . . . . . . . . Number 03C5h +SC_Index . . . . . . . . . . . . Number 03C4h +SEQU_RESTART . . . . . . . . . . Number 0300h +START_DISP_HI . . . . . . . . . Number 000Ch +START_DISP_LO . . . . . . . . . Number 000Dh +True . . . . . . . . . . . . . . Number -0001h +VERT_RETRACE . . . . . . . . . . Number 0008h +VGA_Segment . . . . . . . . . . Number A000h +b . . . . . . . . . . . . . . . Text BYTE PTR +d . . . . . . . . . . . . . . . Text DWORD PTR +f . . . . . . . . . . . . . . . Text FAR PTR +nil . . . . . . . . . . . . . . Number 0000h +o . . . . . . . . . . . . . . . Text OFFSET +s . . . . . . . . . . . . . . . Text SHORT +w . . . . . . . . . . . . . . . Text WORD PTR + + 0 Warnings + 0 Errors diff --git a/src/lib/modex/modex.sbr b/src/lib/modex/modex.sbr new file mode 100755 index 0000000000000000000000000000000000000000..4da653b0d38749807dfb8156d36fc9787e1da174 GIT binary patch literal 12235 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 literal 0 HcmV?d00001 diff --git a/src/lib/modex/modex105.zip b/src/lib/modex/modex105.zip new file mode 100755 index 0000000000000000000000000000000000000000..9457bd98ecabf87d3e5eb233b115e1edc76cfca7 GIT binary patch literal 264999 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