From a9fb589a2cf020d485b63dff39f9a9196dc81575 Mon Sep 17 00:00:00 2001 From: sparky4 Date: Tue, 24 Nov 2015 13:53:57 -0600 Subject: [PATCH] wwww --- 16/xw/default.fnt | 260 ++++++++++++ 16/xw/makefile | 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/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 + 72 files changed, 10352 insertions(+) create mode 100755 16/xw/default.fnt create mode 100755 16/xw/makefile 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/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 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..d3ad8b71 --- /dev/null +++ b/16/xw/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/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..45bd900f --- /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 zcmb7q4O~-Kw(mM0If;>kfJmve5G~DEX(=UbN+HsWLPVb*OsisTMLX@-I+JPrVL12GE~udS1Y%zMW-Go4$|TPRhr!YJ||Rr zJHOuFJFv3$UVE*z*Is+=&vO>8xX7i^!(^s@WB=Z#CXkEhb&hB%5lsM024n*s10eS%6F|a^mCo=n2w@C+#QqMu><1Si%=+xg4aOhtzcz5^}bkA^@o9L zE02i;LmvsNcCwn~QqjigfFv7N%G);2a&f+7Tc^&&v7(Xlwm_-K`08g3Ze;Yq_}A&1 zH}Zqzv%pATrbZQ!R1p+y)JmAp?Gmjmj3xdU3izFJmwcg_Jdd0aj!rsTZi`nN0LG9A z>jTM!#H>!9_sUxD+UGrM|90&wFXiUura%4akAGlYzpiSn_Xq2(KYq1FBkv+~)h-kI zjrE5(-XG$wPtdg?0Sb?%A^{hw+ApB9S%SflRh+qE7mqOLlz0zEQ85l2O5#Rryhk40 z+*uOOtWfTX)fe-g7ppIQjcGSjEa%JP4&Kwudvs5to|_z0H~)3|W~c~Lb^DzWZ>-TBvvugm)=|o_AD&qCuJtCc_bR$9vNh>Jzu9>tH> zNc;Execqpk-frqcK9*j=sOc5Ec8dMn5hBDxhOVE}h@m*V^ezhGHA(Rrx;O`d>JGjDQ)xzO7D1O!+UZt9s!ZeP9Xk$tq7yL|z6axqC?E zn_vBxRh7b!a4WdxPf(Wrb!FqK)EZsaBQQ|@pf}nZ^?xF?8qO&1NfcNydRnPJON$n5 zyzy5I?j7hI5C#J^!)Tt?2%n+%dhc~%G~m0Tx~0KAC@(TFg(+t)Hn<1II^3U&+bc&M z^-q%bd%-mW{>#a&JnXt2Tr=1z!j$W10c)-!NAHl6d#?`ty0>?{H3M_z#N31aHG@Jm z=D^|8?t%JcH%LbPz8kScpI855qzkJ+=CTSqC)!*kZW@X`MuzJLZo51f9?N-atZSlHfMx7G-wxb@@Q2_)R&vMN$u6mkrd*Z@O1= zT=&r^FPw*?LOgfovg#1G)S!=yhx9ja7bux%*vDdXA1`Nq$jj!Bc{%+P-tUt*Z*ucl z5dR;D=Ro{`Z|UX(nLT{Ke2NdG_wqrv^tyD3&%X>CdCJ|*lHIp8+QThp`4&jK4P`A* z;Fii-KHz^yW~Ctx36XBI%I>5V)bBR7zyh~Ha3__uzz(;BR+qJW!b7!_tJam9m4$J8 zSak^#mMU^#cDpat7SJKEkTR>OkNMmjsgHNH`;2P-6PEvw<~95%OA{{lRJIeZZZF|{Y2Cxf1q;w!&~Cft9*oZ z7gCp`O+eTW#N(arG1}d@=w|5k^qz+&hO6%m8L6?m=aH)E0rySpQx4N^WF`mPV@;Je z8xb(Fd#vR{5wgSrS)HZ2?cwh65c6&R_2ysi-0btk`{I39;yzC-7ON|;kfoq5fh|j7 zODr*#kJVXXl;QOGoEa3q64|^tawSgAHM3{0aZ)_8^WXk$XC$r{bhTTzZmq4`vSmx1 zrNA;3e-=w#Uh(we>C3)QVla@Uh}0~wL5zt8a9Le3mz8n*{r)ka?Ah_z zZ2PIUh+(x^ETKLShZe|Zt4u&X{AHt_@`5zjLwt$BVx3I|B?YU0+TbOt)uqWv+!+uu&7ONMfs$2mxANEf* z7z_;!>u77kj*B}QwleSI8KaK9Zz2-5(3WF+-VDCJh1G|rR;>>VYW}AUHEN#8L4Pf4 zPfXQoVfCo|Dk{q(rtHnV9kiunhGj;{7Ah$zVI~kdAI*zVExN_!f;C3P&HWO1^3P!6(Kpz)V5w=+w@ z4+*h^(aTqtml5SLGUI=F$&wQA5!9==fSIi2VQfO5Nc7xlR1A87t4@SH7&{hA2J%dd z@dM3Z`btWcEb%bR9H7yiOrTDLB*pb7WpDZ|KM{sEunrx}_*ED20`TD}ZD zi-4iLJPjAn7y@ey2KfxWG9USN>=@gz<9{PAHUG?jKGyDa30zR3*}0A(&{eb1Zl;&T zQ<)kmwajmDV}Yfh#C6f-+A>yBhw)fvK|BXXSR5v$S~Bu1J61ar?V=3LzNv|NrY7`b zWUz{;j!Ir!vY>=83uRIS`5m%`g6fA=$3&2Q>&hi>POQkb?kFy`g<9Sc2 za!=-I`4N?$NsT1R8J*>s9*1K@rL)?!yu-n;T0UN%D(7%8z08U%wOp&0C7(=`$AOtu zPzR89u6_%`+{v2gkU9~Q2 zh8nF1ST-lKKddLCn9WBqOfi2U+VG3PTgT$`j%UYeHe~~d@)xjw7Oe$LJ07jGSOQ>% zab+_y3(xwVXH+KK-+0zv-euK+J)WTERL#p zd${*v??w5%yv<>1ahe*<#iro40#p9w7MH1IzA5;NCrtUnf%Ms?k^YtvM!~*vfhp<; z#p5^<)!(vg$dQ*x^*5~>?h9nPOpH^G==5|{5mX7bt8|*!4zn1dU+o>oZ85aCQ7E;P zX@%I8^1OO1%RTOJny|&qzl^JA?3y;Q{qJ8;ULJFoh)cvI}l>b~u-WAK#Y2pF$1Q zJV|rXG8{64;?}U&>edd9*!HfC=Qhtbac&&=762Jly%+3Z?RapvFq=id=iC((RFyT%H!(U-|=(Uw_P>|+&9KgnoX6d>S1#s4%j$T-+A8jUlzuX zoCeu9ysQETP8><&%WmM*Tw}}?il?N^uU6DU=V|w~`enlucU#y&^LOJNZ$`%pYS1B~ zg+8IufWAuCBiOziLs!bDUkiKZ)y)*b!s(m~!q77LB<>&JiP+-GMRNC-LvN>NZU1Nb z62~3+jFC}slGj)mLAy}E{R2iMw5!hh$)O9vwci@5ZyoxB(3%vy za`SqtDR}AnEsgBGWe>9>-tA|CD~;~DgnQWUYM54Wi}`Y4i?~GRpELt}KjNO@R|rjF zr7k$>A)M5X=(8;KDX*ojocu!ip+x?zl%~`-CjUJBAo3=CvE@%Gjj10`zLJh(33<5} z_!os=h%f7YCcUm7oUl6i5zDhF+fyqh<)_i))#-j#`wJ53$i;QhgDKCYWTz0>g-aYx zNG@&=Bu|0_E+a@gIL0+~oQntPB1oPD>7{!pjb4T>XF}I`{>lW*UoS(KGokA|53U&? z?cf*})1`7*K)MK$rt3W4!W`w|{x6JJkTBwFB+ZC_U|gD@#&w?m8Y!WkBc66}%lSIg z_6A>=x+mqIQWmCmrSzq&P8~?$QrD-ZrG6*%^;BF`^jJEjG_Z9_Q}7#6r(9exsposS zMyijQlDF-k*M_Sl<#hb&>$Ir%Q@QPDsbkARlOS8ku7E`8Ig8v~OH#l7GM+Zca_nf|5_nfM2tD!}p=Ka@^McKO_IEbxEpq z&Pm>p>(LwEZUcs3ZgYA{K*V&J+nj-fHf3sFRZCOHOVhqtDld{S7a!^p24;`l+&{qn z`bTeRDp_Zpo-jf9R@mXh)-YBS`=m4DR*+p{w|w$yj6 z%Kf?sjLy=PkMpMKmLDMFnQFs38BSpXe}D^q9{fY>WE=To88v(x*JAJl(o;PRX1%9F zk~~->TarLAdm`nTp&#*0=l#W^hrGHDDc!?mEkETiPWMnX7h!p7<9gD)QXBQ8M{l%N zD)$PlbCe80F$-4%G5J3n@?255FRuJJzFTz@W;PIm6-GyJgTWD8EIER&iiN!!zEk*@ z4fn-P)@H@tue~RBqR^b`*)S>AQQn~UaznsYhAr~BAl7$1+e12FN7P?iFV9EwD zc9Ms(s=EqNz9A*{KJPGjswNaVl06#)(p-)}Q|))^$DC(+=!Vz&N(c;+IbzmcG`^hmegZ1fnqHSaJb@?!DQBo++z zIHIQ6;<2Ambksi#MGtXQe}SrWETo1ajCYk7`tZ?1sZ?}!{gja*`TXVQe=AfQl7vs6 zZ~f;_=L934&JK2dIvb*wpU)oq^!aXo@nrOzf%RD{dHGhZd-r7YIf%w^b!z_Qo^)Vi zgKe_Mc)1z@s7#8%rcB52O(NbQwVvxN75%jRH9rMPlNwi=J4-Du35^R=J4*8?3%*IP zhJGa+-YCl5c>Q$XoYx4+cg}?ti1PVBX%3GxT`>Tvc1A1f>-wM>mSo+t%5_ARVO(MLnRT|F-$6Ackl0#b+}e;o9GIp{UJ{HF#J zc`xVMvw$K9Jf3dVw@b_GuViiR{5ko@o>(s&iN`D2mh?=MulX0HbIYH7W<}+ym09{z zq0dd!Oo=TP^t{ADtNS&T6*M#IX0_rm#&*-IEj9aM#HBS!7vn zIb@-ce&J}9-c}?Ts7kUmr%|+5?rMzWWEN0;)Dkd1N`XuVwP)s1V;JftVWr8XmON^4 zQs@=VTrNG`t-8Rh%+%U#R;KY^_v!ta$0x&6%%y|PkJ3cRLEZ-rFW~W#r#YXLd^-Fr zuVhlQ18XF;7Gk*u7hVP(Ud=0d#?rQ+XIgGhZwz}SrGVx{hav}FM9Bdo251x)_`{!x zdF9ZsJlGy754I~DEicE^ttbL5&rTNeoP|}qs1KfQlX|8_h`(prec6vb=6Jl|iNYf1 ztl}rDpQ?VvyB4p%e^6ERYL%6&&wH(uYcf*#t5x2$ufDS0I_K4Oe^a&grI)?d8819w zedLJ(`-4y9TW7yo<$3;<7wzF~l9RgYi*e4c=DM4mbah=!zTs#p;cZ1r`Azz|G+U9b zDj6B6&aer-E)_R$-Juh7wJa7oM^|U#g9EL>zJrTt;+g6R`wP2j#9-GY z!+!Wp*xNsvAKsgV#TbiF`z9k><=M9gz$jd&y zz-q*1<5r4d8B3_s7Mu(lFccb?u9qm9QGPg$l*zOlrY9YqN{W$vwvmvRDx?Zq{B8ub zfFN9@$Fj;?B-)NIO~M?HdH&wECwrzFZK*9wH zea=y@5cHLciH~E!LEGvKK#O0 zCC4`yQ7W-r!~VjfHGJ^sZ64!S(n;uWLlChIK562KO#)UK;j^5hRg+vya^i`Ny!}Mc z(Hcp{OHF%tuiT|pV)#md8Zow@DgV#=aapk5fUh3n!K1^cg)im?HC}ZQ&%{=Jj77+U z!PEJ}Y)NM#IVY>8es}Kv&;L*LWW4hGKt4Hd=r>+7Ch~5%#^{cIY7a-nvK+UR#op9w z4TibQA^UB?`%yvR@6oW|8&7y8wEj2Md|^90pt7>Iw{m;g&TB8`x^ZtA(O&oj#6(LZ zw#8uI7u4fj>qcFtTjB^uetaW&k(0gi#PkEIQdwW@o!dXU{x-U z-BFYJN>(b@YAZ%I_M{D zD6L0?+53vld#!%Zrg()p(a+_xIj0Zel2Oyb)UhEHQC6U(@=3?YOQL*K!@|+}GbA5F zXDhSlCz!krT4}h$Uv2EY)O#k@)jyOU_J6vmTd`7)^H3wmpbd-K=G?ImYn3V-SuNjjY!Tp9x 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 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 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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/mxbb.asm b/16/xw/mxbb.asm new file mode 100755 index 00000000..ac6668ce --- /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. + + -- 2.39.2